diff --git a/.utils/bulk-update-subtrees.sh b/.utils/bulk-update-subtrees.sh index bb19a207d25..051b204f252 100755 --- a/.utils/bulk-update-subtrees.sh +++ b/.utils/bulk-update-subtrees.sh @@ -6,6 +6,7 @@ if [ "$(git rev-parse --show-prefix)" != "" ]; then exit fi +shopt -s globstar for file in **/.gitsubtree; do subtree="$(dirname "${file}")" echo -e "\n\nUpdating ${subtree}..." diff --git a/2048/application.fam b/2048/application.fam index 3f10db411b1..3fe90e83434 100644 --- a/2048/application.fam +++ b/2048/application.fam @@ -11,6 +11,6 @@ App( fap_icon="game_2048.png", fap_category="Games", fap_author="@eugene-kirzhanov", - fap_version="1.4", + fap_version="1.5", fap_description="Play the port of the 2048 game on Flipper Zero.", ) diff --git a/4inrow/application.fam b/4inrow/application.fam index 6a99bfbc0b8..fb2e60ea872 100644 --- a/4inrow/application.fam +++ b/4inrow/application.fam @@ -12,6 +12,6 @@ App( fap_category="Games", fap_author="leo-need-more-coffee", fap_weburl="https://github.com/leo-need-more-coffee/flipperzero-4inrow", - fap_version="1.1", + fap_version="1.2", fap_description="4 in row Game", ) diff --git a/airmouse/CHANGELOG.md b/airmouse/CHANGELOG.md index 1f2403e3845..a9530435913 100644 --- a/airmouse/CHANGELOG.md +++ b/airmouse/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## v1.2 (2024-06-05) + +**Support multiple IMU models** + + - Apart from BMI160, you can now use LSM6DS3 or LSM6DSO + ## v1.1 (2024-03-14) **BLE updates/fixes** diff --git a/airmouse/README.md b/airmouse/README.md index 86b96245e74..99d20de214a 100644 --- a/airmouse/README.md +++ b/airmouse/README.md @@ -27,10 +27,24 @@ Using it is really simple: See early prototype [in action](https://www.youtube.com/watch?v=DdxAmmsYfMA). +## How? + + * Clone this repository with `git clone --recurse-submodules` to include the driver implementations. + * Build the project using `ufbt` + ## Hardware The custom module is using Bosch BMI160 accelerometer/gyroscope chip connected via I2C. +Note: in fact, some other IMU chips are also supported. +It's detected via the first found I2C Address. + +| Chip | Expected I2C Address | +|:--------:|:--------------------:| +| BMI160 | 0x69 | +| LSM6DS3 | 0x6A | +| LSM6DSO | 0x6B | + Take a look into the [schematic](https://github.com/ginkage/FlippAirMouse/tree/main/schematic) folder for Gerber, BOM and CPL files, so you can order directly from JLCPCB. Original idea: diff --git a/airmouse/air_mouse.c b/airmouse/air_mouse.c index 54a6e80273b..4f0a296ef1f 100644 --- a/airmouse/air_mouse.c +++ b/airmouse/air_mouse.c @@ -91,7 +91,7 @@ AirMouse* air_mouse_app_alloc() { view_dispatcher_add_view( app->view_dispatcher, AirMouseViewSubmenu, submenu_get_view(app->submenu)); - // Dialog view + // Dialog views app->dialog = dialog_ex_alloc(); dialog_ex_set_result_callback(app->dialog, air_mouse_dialog_callback); dialog_ex_set_context(app->dialog, app); @@ -102,6 +102,14 @@ AirMouse* air_mouse_app_alloc() { view_dispatcher_add_view( app->view_dispatcher, AirMouseViewExitConfirm, dialog_ex_get_view(app->dialog)); + app->error_dialog = dialog_ex_alloc(); + dialog_ex_set_header(app->error_dialog, "Failed to init IMU", 63, 0, AlignCenter, AlignTop); + dialog_ex_set_text( + app->error_dialog, "Please connect sensor module", 63, 30, AlignCenter, AlignTop); + view_set_previous_callback(dialog_ex_get_view(app->error_dialog), air_mouse_exit); + view_dispatcher_add_view( + app->view_dispatcher, AirMouseViewError, dialog_ex_get_view(app->error_dialog)); + // Bluetooth view app->bt_mouse = bt_mouse_alloc(app->view_dispatcher); view_set_previous_callback(bt_mouse_get_view(app->bt_mouse), air_mouse_exit_confirm_view); @@ -135,6 +143,8 @@ void air_mouse_app_free(AirMouse* app) { submenu_free(app->submenu); view_dispatcher_remove_view(app->view_dispatcher, AirMouseViewExitConfirm); dialog_ex_free(app->dialog); + view_dispatcher_remove_view(app->view_dispatcher, AirMouseViewError); + dialog_ex_free(app->error_dialog); view_dispatcher_remove_view(app->view_dispatcher, AirMouseViewBtMouse); bt_mouse_free(app->bt_mouse); view_dispatcher_remove_view(app->view_dispatcher, AirMouseViewUsbMouse); @@ -156,8 +166,7 @@ int32_t air_mouse_app(void* p) { AirMouse* app = air_mouse_app_alloc(); if(!imu_begin()) { - air_mouse_app_free(app); - return -1; + view_dispatcher_switch_to_view(app->view_dispatcher, AirMouseViewError); } view_dispatcher_run(app->view_dispatcher); diff --git a/airmouse/air_mouse.h b/airmouse/air_mouse.h index 3a1ba783ec1..95925ff6d6d 100644 --- a/airmouse/air_mouse.h +++ b/airmouse/air_mouse.h @@ -15,6 +15,7 @@ typedef struct { ViewDispatcher* view_dispatcher; Submenu* submenu; DialogEx* dialog; + DialogEx* error_dialog; BtMouse* bt_mouse; UsbMouse* usb_mouse; Calibration* calibration; @@ -27,4 +28,5 @@ typedef enum { AirMouseViewUsbMouse, AirMouseViewCalibration, AirMouseViewExitConfirm, + AirMouseViewError, } AirMouseView; diff --git a/airmouse/application.fam b/airmouse/application.fam index 61cf1edbd4c..1d3a7073d3e 100644 --- a/airmouse/application.fam +++ b/airmouse/application.fam @@ -1,12 +1,31 @@ App( appid="air_mouse", - name="[BMI160] Air Mouse", + name="[BMI/LSM] Air Mouse", apptype=FlipperAppType.EXTERNAL, entry_point="air_mouse_app", stack_size=10 * 1024, fap_category="GPIO", fap_icon="mouse_10px.png", - fap_version="1.1", + fap_version="1.2", fap_libs=["ble_profile"], sources=["*.c", "*.cc"], + fap_private_libs=[ + Lib( + name="bmi160-api", + cflags=["-Wno-error"], + sources=[ + "bmi160.c", + "bmi160.h", + "bmi160_defs.h", + ], + ), + Lib( + name="lsm6ds3tr-api", + cflags=["-Wno-error"], + ), + Lib( + name="lsm6dso-api", + cflags=["-Wno-error"], + ), + ], ) diff --git a/airmouse/build.sh b/airmouse/build.sh new file mode 100755 index 00000000000..0337819c373 --- /dev/null +++ b/airmouse/build.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +ufbt \ No newline at end of file diff --git a/airmouse/lib/bmi160-api/.gitsubtree b/airmouse/lib/bmi160-api/.gitsubtree new file mode 100644 index 00000000000..700eeb895b5 --- /dev/null +++ b/airmouse/lib/bmi160-api/.gitsubtree @@ -0,0 +1 @@ +https://github.com/boschsensortec/BMI160_SensorAPI master / diff --git a/airmouse/lib/bmi160-api/LICENSE b/airmouse/lib/bmi160-api/LICENSE new file mode 100644 index 00000000000..39d644246fb --- /dev/null +++ b/airmouse/lib/bmi160-api/LICENSE @@ -0,0 +1,30 @@ +Copyright (c) 2021 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. \ No newline at end of file diff --git a/airmouse/lib/bmi160-api/README.md b/airmouse/lib/bmi160-api/README.md new file mode 100644 index 00000000000..a29e977c406 --- /dev/null +++ b/airmouse/lib/bmi160-api/README.md @@ -0,0 +1,42 @@ +# BMI160 Sensor API + +### Sensor overview + +The small, low power BMI160 is a low noise 16-bit IMU designed for mobile applications such as AR or indoor navigation, providing highly accurate sensor data and real-time sensor data. The low current consumption of BMI160 enables always-on applications in battery-driven devices. This sensor features a configurable on-chip interrupt engine which provides motion-based gesture recognition and context awareness as always-on background functions. + +### Target Application +- Augmented reality and immersive gaming +- Indoor navigation +- 3D-scanning / indoor mapping +- Advanced gesture recognition +- Immersive gaming +- 9-axis motion detection +- Air mouse applications and pointers +- Pedometer / step counting +- Advanced system power management for mobile applications +- Optical image stabilization of camera modules +- Free-fall detection and warranty logging + +### Features +- Any-motion detection (accelerometer) +- Significant motion detection (accelerometer) +- Step detector (accelerometer) +- Tap sensing (accelerometer) +- Orientation recognition (accelerometer) +- Flat detection (accelerometer) +- Low-G / Free-fall detection (accelerometer) +- High-G detection (accelerometer) +- Slow-motion alert / No-motion interrupt (accelerometer) +- Data ready detection (accelerometer, gyroscope and external sensors) +- PMU trigger (gyroscope) +- FIFO interrupts ((accelerometer, gyroscope and external sensors) + +### Important links + +- [BMI160 product page](https://www.bosch-sensortec.com/products/motion-sensors/imus/bmi160/) +- [BMI160 datasheet](https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmi160-ds000.pdf) +- [BMI160 shuttle board flyer](https://www.bosch-sensortec.com/media/boschsensortec/downloads/shuttle_board_flyer/bst-dhw-fl022.pdf) +- [Community support page](https://community.bosch-sensortec.com) + +--- +#### Copyright (C) 2020 Bosch Sensortec GmbH \ No newline at end of file diff --git a/airmouse/lib/bmi160-api/bmi160.c b/airmouse/lib/bmi160-api/bmi160.c new file mode 100644 index 00000000000..733db9f0d88 --- /dev/null +++ b/airmouse/lib/bmi160-api/bmi160.c @@ -0,0 +1,6428 @@ +/** +* Copyright (c) 2021 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 bmi160.c +* @date 2021-10-05 +* @version v3.9.2 +* +*/ + +#include "bmi160.h" + +/* Below look up table follows the enum bmi160_int_types. + * Hence any change should match to the enum bmi160_int_types + */ +const uint8_t int_mask_lookup_table[13] = { + BMI160_INT1_SLOPE_MASK, BMI160_INT1_SLOPE_MASK, BMI160_INT2_LOW_STEP_DETECT_MASK, BMI160_INT1_DOUBLE_TAP_MASK, + BMI160_INT1_SINGLE_TAP_MASK, BMI160_INT1_ORIENT_MASK, BMI160_INT1_FLAT_MASK, BMI160_INT1_HIGH_G_MASK, + BMI160_INT1_LOW_G_MASK, BMI160_INT1_NO_MOTION_MASK, BMI160_INT2_DATA_READY_MASK, BMI160_INT2_FIFO_FULL_MASK, + BMI160_INT2_FIFO_WM_MASK +}; + +/*********************************************************************/ +/* Static function declarations */ + +/*! + * @brief This API configures the pins to fire the + * interrupt signal when it occurs + * + * @param[in] int_config : Structure instance of bmi160_int_settg. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t set_intr_pin_config(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev); + +/*! + * @brief This API sets the any-motion interrupt of the sensor. + * This interrupt occurs when accel values exceeds preset threshold + * for a certain period of time. + * + * @param[in] int_config : Structure instance of bmi160_int_settg. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t set_accel_any_motion_int(struct bmi160_int_settg *int_config, struct bmi160_dev *dev); + +/*! + * @brief This API sets tap interrupts.Interrupt is fired when + * tap movements happen. + * + * @param[in] int_config : Structure instance of bmi160_int_settg. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t set_accel_tap_int(struct bmi160_int_settg *int_config, const struct bmi160_dev *dev); + +/*! + * @brief This API sets the data ready interrupt for both accel and gyro. + * This interrupt occurs when new accel and gyro data come. + * + * @param[in] int_config : Structure instance of bmi160_int_settg. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t set_accel_gyro_data_ready_int(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev); + +/*! + * @brief This API sets the significant motion interrupt of the sensor.This + * interrupt occurs when there is change in user location. + * + * @param[in] int_config : Structure instance of bmi160_int_settg. + * @param[in] dev : Structure instance of bmi160_dev. + * + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t set_accel_sig_motion_int(struct bmi160_int_settg *int_config, struct bmi160_dev *dev); + +/*! + * @brief This API sets the no motion/slow motion interrupt of the sensor. + * Slow motion is similar to any motion interrupt.No motion interrupt + * occurs when slope bet. two accel values falls below preset threshold + * for preset duration. + * + * @param[in] int_config : Structure instance of bmi160_int_settg. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t set_accel_no_motion_int(struct bmi160_int_settg *int_config, const struct bmi160_dev *dev); + +/*! + * @brief This API sets the step detection interrupt.This interrupt + * occurs when the single step causes accel values to go above + * preset threshold. + * + * @param[in] int_config : Structure instance of bmi160_int_settg. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t set_accel_step_detect_int(struct bmi160_int_settg *int_config, const struct bmi160_dev *dev); + +/*! + * @brief This API sets the orientation interrupt of the sensor.This + * interrupt occurs when there is orientation change in the sensor + * with respect to gravitational field vector g. + * + * @param[in] int_config : Structure instance of bmi160_int_settg. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t set_accel_orientation_int(struct bmi160_int_settg *int_config, const struct bmi160_dev *dev); + +/*! + * @brief This API sets the flat interrupt of the sensor.This interrupt + * occurs in case of flat orientation + * + * @param[in] int_config : Structure instance of bmi160_int_settg. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t set_accel_flat_detect_int(struct bmi160_int_settg *int_config, const struct bmi160_dev *dev); + +/*! + * @brief This API sets the low-g interrupt of the sensor.This interrupt + * occurs during free-fall. + * + * @param[in] int_config : Structure instance of bmi160_int_settg. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t set_accel_low_g_int(struct bmi160_int_settg *int_config, const struct bmi160_dev *dev); + +/*! + * @brief This API sets the high-g interrupt of the sensor.The interrupt + * occurs if the absolute value of acceleration data of any enabled axis + * exceeds the programmed threshold and the sign of the value does not + * change for a preset duration. + * + * @param[in] int_config : Structure instance of bmi160_int_settg. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t set_accel_high_g_int(struct bmi160_int_settg *int_config, const struct bmi160_dev *dev); + +/*! + * @brief This API sets the default configuration parameters of accel & gyro. + * Also maintain the previous state of configurations. + * + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error. + */ +static void default_param_settg(struct bmi160_dev *dev); + +/*! + * @brief This API is used to validate the device structure pointer for + * null conditions. + * + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t null_ptr_check(const struct bmi160_dev *dev); + +/*! + * @brief This API set the accel configuration. + * + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t set_accel_conf(struct bmi160_dev *dev); + +/*! + * @brief This API gets the accel configuration. + * + * @param[out] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t get_accel_conf(struct bmi160_dev *dev); + +/*! + * @brief This API check the accel configuration. + * + * @param[in] data : Pointer to store the updated accel config. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t check_accel_config(uint8_t *data, const struct bmi160_dev *dev); + +/*! + * @brief This API process the accel odr. + * + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t process_accel_odr(uint8_t *data, const struct bmi160_dev *dev); + +/*! + * @brief This API process the accel bandwidth. + * + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t process_accel_bw(uint8_t *data, const struct bmi160_dev *dev); + +/*! + * @brief This API process the accel range. + * + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t process_accel_range(uint8_t *data, const struct bmi160_dev *dev); + +/*! + * @brief This API checks the invalid settings for ODR & Bw for Accel and Gyro. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t check_invalid_settg(const struct bmi160_dev *dev); + +/*! + * @brief This API set the gyro configuration. + * + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t set_gyro_conf(struct bmi160_dev *dev); + +/*! + * @brief This API get the gyro configuration. + * + * @param[out] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t get_gyro_conf(struct bmi160_dev *dev); + +/*! + * @brief This API check the gyro configuration. + * + * @param[in] data : Pointer to store the updated gyro config. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t check_gyro_config(uint8_t *data, const struct bmi160_dev *dev); + +/*! + * @brief This API process the gyro odr. + * + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t process_gyro_odr(uint8_t *data, const struct bmi160_dev *dev); + +/*! + * @brief This API process the gyro bandwidth. + * + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t process_gyro_bw(uint8_t *data, const struct bmi160_dev *dev); + +/*! + * @brief This API process the gyro range. + * + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t process_gyro_range(uint8_t *data, const struct bmi160_dev *dev); + +/*! + * @brief This API sets the accel power mode. + * + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t set_accel_pwr(struct bmi160_dev *dev); + +/*! + * @brief This API process the undersampling setting of Accel. + * + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t process_under_sampling(uint8_t *data, const struct bmi160_dev *dev); + +/*! + * @brief This API sets the gyro power mode. + * + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error. + */ +static int8_t set_gyro_pwr(struct bmi160_dev *dev); + +/*! + * @brief This API reads accel data along with sensor time if time is requested + * by user. Kindly refer the user guide(README.md) for more info. + * + * @param[in] len : len to read no of bytes + * @param[out] accel : Structure pointer to store accel data + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t get_accel_data(uint8_t len, struct bmi160_sensor_data *accel, const struct bmi160_dev *dev); + +/*! + * @brief This API reads accel data along with sensor time if time is requested + * by user. Kindly refer the user guide(README.md) for more info. + * + * @param[in] len : len to read no of bytes + * @param[out] gyro : Structure pointer to store accel data + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t get_gyro_data(uint8_t len, struct bmi160_sensor_data *gyro, const struct bmi160_dev *dev); + +/*! + * @brief This API reads accel and gyro data along with sensor time + * if time is requested by user. + * Kindly refer the user guide(README.md) for more info. + * + * @param[in] len : len to read no of bytes + * @param[out] accel : Structure pointer to store accel data + * @param[out] gyro : Structure pointer to store accel data + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t get_accel_gyro_data(uint8_t len, + struct bmi160_sensor_data *accel, + struct bmi160_sensor_data *gyro, + const struct bmi160_dev *dev); + +/*! + * @brief This API enables the any-motion interrupt for accel. + * + * @param[in] any_motion_int_cfg : Structure instance of + * bmi160_acc_any_mot_int_cfg. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t enable_accel_any_motion_int(const struct bmi160_acc_any_mot_int_cfg *any_motion_int_cfg, + struct bmi160_dev *dev); + +/*! + * @brief This API disable the sig-motion interrupt. + * + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t disable_sig_motion_int(const struct bmi160_dev *dev); + +/*! + * @brief This API configure the source of data(filter & pre-filter) + * for any-motion interrupt. + * + * @param[in] any_motion_int_cfg : Structure instance of + * bmi160_acc_any_mot_int_cfg. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t config_any_motion_src(const struct bmi160_acc_any_mot_int_cfg *any_motion_int_cfg, + const struct bmi160_dev *dev); + +/*! + * @brief This API configure the duration and threshold of + * any-motion interrupt. + * + * @param[in] any_motion_int_cfg : Structure instance of + * bmi160_acc_any_mot_int_cfg. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t config_any_dur_threshold(const struct bmi160_acc_any_mot_int_cfg *any_motion_int_cfg, + const struct bmi160_dev *dev); + +/*! + * @brief This API configure necessary setting of any-motion interrupt. + * + * @param[in] int_config : Structure instance of bmi160_int_settg. + * @param[in] any_motion_int_cfg : Structure instance of + * bmi160_acc_any_mot_int_cfg. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t config_any_motion_int_settg(const struct bmi160_int_settg *int_config, + const struct bmi160_acc_any_mot_int_cfg *any_motion_int_cfg, + const struct bmi160_dev *dev); + +/*! + * @brief This API enable the data ready interrupt. + * + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t enable_data_ready_int(const struct bmi160_dev *dev); + +/*! + * @brief This API enables the no motion/slow motion interrupt. + * + * @param[in] no_mot_int_cfg : Structure instance of + * bmi160_acc_no_motion_int_cfg. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t enable_no_motion_int(const struct bmi160_acc_no_motion_int_cfg *no_mot_int_cfg, + const struct bmi160_dev *dev); + +/*! + * @brief This API configure the interrupt PIN setting for + * no motion/slow motion interrupt. + * + * @param[in] int_config : structure instance of bmi160_int_settg. + * @param[in] no_mot_int_cfg : Structure instance of + * bmi160_acc_no_motion_int_cfg. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t config_no_motion_int_settg(const struct bmi160_int_settg *int_config, + const struct bmi160_acc_no_motion_int_cfg *no_mot_int_cfg, + const struct bmi160_dev *dev); + +/*! + * @brief This API configure the source of interrupt for no motion. + * + * @param[in] no_mot_int_cfg : Structure instance of + * bmi160_acc_no_motion_int_cfg. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t config_no_motion_data_src(const struct bmi160_acc_no_motion_int_cfg *no_mot_int_cfg, + const struct bmi160_dev *dev); + +/*! + * @brief This API configure the duration and threshold of + * no motion/slow motion interrupt along with selection of no/slow motion. + * + * @param[in] no_mot_int_cfg : Structure instance of + * bmi160_acc_no_motion_int_cfg. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t config_no_motion_dur_thr(const struct bmi160_acc_no_motion_int_cfg *no_mot_int_cfg, + const struct bmi160_dev *dev); + +/*! + * @brief This API enables the sig-motion motion interrupt. + * + * @param[in] sig_mot_int_cfg : Structure instance of + * bmi160_acc_sig_mot_int_cfg. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t enable_sig_motion_int(const struct bmi160_acc_sig_mot_int_cfg *sig_mot_int_cfg, struct bmi160_dev *dev); + +/*! + * @brief This API configure the interrupt PIN setting for + * significant motion interrupt. + * + * @param[in] int_config : Structure instance of bmi160_int_settg. + * @param[in] sig_mot_int_cfg : Structure instance of + * bmi160_acc_sig_mot_int_cfg. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t config_sig_motion_int_settg(const struct bmi160_int_settg *int_config, + const struct bmi160_acc_sig_mot_int_cfg *sig_mot_int_cfg, + const struct bmi160_dev *dev); + +/*! + * @brief This API configure the source of data(filter & pre-filter) + * for sig motion interrupt. + * + * @param[in] sig_mot_int_cfg : Structure instance of + * bmi160_acc_sig_mot_int_cfg. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t config_sig_motion_data_src(const struct bmi160_acc_sig_mot_int_cfg *sig_mot_int_cfg, + const struct bmi160_dev *dev); + +/*! + * @brief This API configure the threshold, skip and proof time of + * sig motion interrupt. + * + * @param[in] sig_mot_int_cfg : Structure instance of + * bmi160_acc_sig_mot_int_cfg. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t config_sig_dur_threshold(const struct bmi160_acc_sig_mot_int_cfg *sig_mot_int_cfg, + const struct bmi160_dev *dev); + +/*! + * @brief This API enables the step detector interrupt. + * + * @param[in] step_detect_int_cfg : Structure instance of + * bmi160_acc_step_detect_int_cfg. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t enable_step_detect_int(const struct bmi160_acc_step_detect_int_cfg *step_detect_int_cfg, + const struct bmi160_dev *dev); + +/*! + * @brief This API configure the step detector parameter. + * + * @param[in] step_detect_int_cfg : Structure instance of + * bmi160_acc_step_detect_int_cfg. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t config_step_detect(const struct bmi160_acc_step_detect_int_cfg *step_detect_int_cfg, + const struct bmi160_dev *dev); + +/*! + * @brief This API enables the single/double tap interrupt. + * + * @param[in] int_config : Structure instance of bmi160_int_settg. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t enable_tap_int(const struct bmi160_int_settg *int_config, + const struct bmi160_acc_tap_int_cfg *tap_int_cfg, + const struct bmi160_dev *dev); + +/*! + * @brief This API configure the interrupt PIN setting for + * tap interrupt. + * + * @param[in] int_config : Structure instance of bmi160_int_settg. + * @param[in] tap_int_cfg : Structure instance of bmi160_acc_tap_int_cfg. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t config_tap_int_settg(const struct bmi160_int_settg *int_config, + const struct bmi160_acc_tap_int_cfg *tap_int_cfg, + const struct bmi160_dev *dev); + +/*! + * @brief This API configure the source of data(filter & pre-filter) + * for tap interrupt. + * + * @param[in] tap_int_cfg : Structure instance of bmi160_acc_tap_int_cfg. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t config_tap_data_src(const struct bmi160_acc_tap_int_cfg *tap_int_cfg, const struct bmi160_dev *dev); + +/*! + * @brief This API configure the parameters of tap interrupt. + * Threshold, quite, shock, and duration. + * + * @param[in] int_config : Structure instance of bmi160_int_settg. + * @param[in] tap_int_cfg : Structure instance of bmi160_acc_tap_int_cfg. + * @param[in] dev : structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t config_tap_param(const struct bmi160_int_settg *int_config, + const struct bmi160_acc_tap_int_cfg *tap_int_cfg, + const struct bmi160_dev *dev); + +/*! + * @brief This API enable the external mode configuration. + * + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t config_sec_if(const struct bmi160_dev *dev); + +/*! + * @brief This API configure the ODR of the auxiliary sensor. + * + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t config_aux_odr(const struct bmi160_dev *dev); + +/*! + * @brief This API maps the actual burst read length set by user. + * + * @param[in] len : Pointer to store the read length. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t map_read_len(uint16_t *len, const struct bmi160_dev *dev); + +/*! + * @brief This API configure the settings of auxiliary sensor. + * + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t config_aux_settg(const struct bmi160_dev *dev); + +/*! + * @brief This API extract the read data from auxiliary sensor. + * + * @param[in] map_len : burst read value. + * @param[in] reg_addr : Address of register to read. + * @param[in] aux_data : Pointer to store the read data. + * @param[in] len : length to read the data. + * @param[in] dev : Structure instance of bmi160_dev. + * @note : Refer user guide for detailed info. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t extract_aux_read(uint16_t map_len, + uint8_t reg_addr, + uint8_t *aux_data, + uint16_t len, + const struct bmi160_dev *dev); + +/*! + * @brief This API enables the orient interrupt. + * + * @param[in] orient_int_cfg : Structure instance of bmi160_acc_orient_int_cfg. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t enable_orient_int(const struct bmi160_acc_orient_int_cfg *orient_int_cfg, const struct bmi160_dev *dev); + +/*! + * @brief This API configure the necessary setting of orientation interrupt. + * + * @param[in] orient_int_cfg : Structure instance of bmi160_acc_orient_int_cfg. + * @param[in] dev : structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t config_orient_int_settg(const struct bmi160_acc_orient_int_cfg *orient_int_cfg, + const struct bmi160_dev *dev); + +/*! + * @brief This API enables the flat interrupt. + * + * @param[in] flat_int : Structure instance of bmi160_acc_flat_detect_int_cfg. + * @param[in] dev : structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t enable_flat_int(const struct bmi160_acc_flat_detect_int_cfg *flat_int, const struct bmi160_dev *dev); + +/*! + * @brief This API configure the necessary setting of flat interrupt. + * + * @param[in] flat_int : Structure instance of bmi160_acc_flat_detect_int_cfg. + * @param[in] dev : structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t config_flat_int_settg(const struct bmi160_acc_flat_detect_int_cfg *flat_int, + const struct bmi160_dev *dev); + +/*! + * @brief This API enables the Low-g interrupt. + * + * @param[in] low_g_int : Structure instance of bmi160_acc_low_g_int_cfg. + * @param[in] dev : structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t enable_low_g_int(const struct bmi160_acc_low_g_int_cfg *low_g_int, const struct bmi160_dev *dev); + +/*! + * @brief This API configure the source of data(filter & pre-filter) for low-g interrupt. + * + * @param[in] low_g_int : Structure instance of bmi160_acc_low_g_int_cfg. + * @param[in] dev : structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t config_low_g_data_src(const struct bmi160_acc_low_g_int_cfg *low_g_int, const struct bmi160_dev *dev); + +/*! + * @brief This API configure the necessary setting of low-g interrupt. + * + * @param[in] low_g_int : Structure instance of bmi160_acc_low_g_int_cfg. + * @param[in] dev : structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t config_low_g_int_settg(const struct bmi160_acc_low_g_int_cfg *low_g_int, const struct bmi160_dev *dev); + +/*! + * @brief This API enables the high-g interrupt. + * + * @param[in] high_g_int_cfg : Structure instance of bmi160_acc_high_g_int_cfg. + * @param[in] dev : structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t enable_high_g_int(const struct bmi160_acc_high_g_int_cfg *high_g_int_cfg, const struct bmi160_dev *dev); + +/*! + * @brief This API configure the source of data(filter & pre-filter) + * for high-g interrupt. + * + * @param[in] high_g_int_cfg : Structure instance of bmi160_acc_high_g_int_cfg. + * @param[in] dev : structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t config_high_g_data_src(const struct bmi160_acc_high_g_int_cfg *high_g_int_cfg, + const struct bmi160_dev *dev); + +/*! + * @brief This API configure the necessary setting of high-g interrupt. + * + * @param[in] high_g_int_cfg : Structure instance of bmi160_acc_high_g_int_cfg. + * @param[in] dev : structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t config_high_g_int_settg(const struct bmi160_acc_high_g_int_cfg *high_g_int_cfg, + const struct bmi160_dev *dev); + +/*! + * @brief This API configure the behavioural setting of interrupt pin. + * + * @param[in] int_config : Structure instance of bmi160_int_settg. + * @param[in] dev : structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t config_int_out_ctrl(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev); + +/*! + * @brief This API configure the mode(input enable, latch or non-latch) of interrupt pin. + * + * @param[in] int_config : Structure instance of bmi160_int_settg. + * @param[in] dev : structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t config_int_latch(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev); + +/*! + * @brief This API performs the self test for accelerometer of BMI160 + * + * @param[in] dev : structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t perform_accel_self_test(struct bmi160_dev *dev); + +/*! + * @brief This API enables to perform the accel self test by setting proper + * configurations to facilitate accel self test + * + * @param[in] dev : structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t enable_accel_self_test(struct bmi160_dev *dev); + +/*! + * @brief This API performs accel self test with positive excitation + * + * @param[in] accel_pos : Structure pointer to store accel data + * for positive excitation + * @param[in] dev : structure instance of bmi160_dev + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t accel_self_test_positive_excitation(struct bmi160_sensor_data *accel_pos, const struct bmi160_dev *dev); + +/*! + * @brief This API performs accel self test with negative excitation + * + * @param[in] accel_neg : Structure pointer to store accel data + * for negative excitation + * @param[in] dev : structure instance of bmi160_dev + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t accel_self_test_negative_excitation(struct bmi160_sensor_data *accel_neg, const struct bmi160_dev *dev); + +/*! + * @brief This API validates the accel self test results + * + * @param[in] accel_pos : Structure pointer to store accel data + * for positive excitation + * @param[in] accel_neg : Structure pointer to store accel data + * for negative excitation + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error / +ve value -> Self test fail + */ +static int8_t validate_accel_self_test(const struct bmi160_sensor_data *accel_pos, + const struct bmi160_sensor_data *accel_neg); + +/*! + * @brief This API performs the self test for gyroscope of BMI160 + * + * @param[in] dev : structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t perform_gyro_self_test(const struct bmi160_dev *dev); + +/*! + * @brief This API enables the self test bit to trigger self test for gyro + * + * @param[in] dev : structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t enable_gyro_self_test(const struct bmi160_dev *dev); + +/*! + * @brief This API validates the self test results of gyro + * + * @param[in] dev : structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t validate_gyro_self_test(const struct bmi160_dev *dev); + +/*! + * @brief This API sets FIFO full interrupt of the sensor.This interrupt + * occurs when the FIFO is full and the next full data sample would cause + * a FIFO overflow, which may delete the old samples. + * + * @param[in] int_config : Structure instance of bmi160_int_settg. + * @param[in] dev : structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t set_fifo_full_int(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev); + +/*! + * @brief This enable the FIFO full interrupt engine. + * + * @param[in] int_config : Structure instance of bmi160_int_settg. + * @param[in] dev : structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t enable_fifo_full_int(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev); + +/*! + * @brief This API sets FIFO watermark interrupt of the sensor.The FIFO + * watermark interrupt is fired, when the FIFO fill level is above a fifo + * watermark. + * + * @param[in] int_config : Structure instance of bmi160_int_settg. + * @param[in] dev : structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t set_fifo_watermark_int(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev); + +/*! + * @brief This enable the FIFO watermark interrupt engine. + * + * @param[in] int_config : Structure instance of bmi160_int_settg. + * @param[in] dev : structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t enable_fifo_wtm_int(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev); + +/*! + * @brief This API is used to reset the FIFO related configurations + * in the fifo_frame structure. + * + * @param[in] dev : structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static void reset_fifo_data_structure(const struct bmi160_dev *dev); + +/*! + * @brief This API is used to read number of bytes filled + * currently in FIFO buffer. + * + * @param[in] bytes_to_read : Number of bytes available in FIFO at the + * instant which is obtained from FIFO counter. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error. + * @retval Any non zero value -> Fail + * + */ +static int8_t get_fifo_byte_counter(uint16_t *bytes_to_read, struct bmi160_dev const *dev); + +/*! + * @brief This API is used to compute the number of bytes of accel FIFO data + * which is to be parsed in header-less mode + * + * @param[out] data_index : The start index for parsing data + * @param[out] data_read_length : Number of bytes to be parsed + * @param[in] acc_frame_count : Number of accelerometer frames to be read + * @param[in] dev : Structure instance of bmi160_dev. + * + */ +static void get_accel_len_to_parse(uint16_t *data_index, + uint16_t *data_read_length, + const uint8_t *acc_frame_count, + const struct bmi160_dev *dev); + +/*! + * @brief This API is used to parse the accelerometer data from the + * FIFO data in both header mode and header-less mode. + * It updates the idx value which is used to store the index of + * the current data byte which is parsed. + * + * @param[in,out] acc : structure instance of sensor data + * @param[in,out] idx : Index value of number of bytes parsed + * @param[in,out] acc_idx : Index value of accelerometer data + * (x,y,z axes) frames parsed + * @param[in] frame_info : It consists of either fifo_data_enable + * parameter in header-less mode or + * frame header data in header mode + * @param[in] dev : structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static void unpack_accel_frame(struct bmi160_sensor_data *acc, + uint16_t *idx, + uint8_t *acc_idx, + uint8_t frame_info, + const struct bmi160_dev *dev); + +/*! + * @brief This API is used to parse the accelerometer data from the + * FIFO data and store it in the instance of the structure bmi160_sensor_data. + * + * @param[in,out] accel_data : structure instance of sensor data + * @param[in,out] data_start_index : Index value of number of bytes parsed + * @param[in] dev : structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static void unpack_accel_data(struct bmi160_sensor_data *accel_data, + uint16_t data_start_index, + const struct bmi160_dev *dev); + +/*! + * @brief This API is used to parse the accelerometer data from the + * FIFO data in header mode. + * + * @param[in,out] accel_data : Structure instance of sensor data + * @param[in,out] accel_length : Number of accelerometer frames + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static void extract_accel_header_mode(struct bmi160_sensor_data *accel_data, + uint8_t *accel_length, + const struct bmi160_dev *dev); + +/*! + * @brief This API computes the number of bytes of gyro FIFO data + * which is to be parsed in header-less mode + * + * @param[out] data_index : The start index for parsing data + * @param[out] data_read_length : No of bytes to be parsed from FIFO buffer + * @param[in] gyro_frame_count : Number of Gyro data frames to be read + * @param[in] dev : Structure instance of bmi160_dev. + */ +static void get_gyro_len_to_parse(uint16_t *data_index, + uint16_t *data_read_length, + const uint8_t *gyro_frame_count, + const struct bmi160_dev *dev); + +/*! + * @brief This API is used to parse the gyroscope's data from the + * FIFO data in both header mode and header-less mode. + * It updates the idx value which is used to store the index of + * the current data byte which is parsed. + * + * @param[in,out] gyro : structure instance of sensor data + * @param[in,out] idx : Index value of number of bytes parsed + * @param[in,out] gyro_idx : Index value of gyro data + * (x,y,z axes) frames parsed + * @param[in] frame_info : It consists of either fifo_data_enable + * parameter in header-less mode or + * frame header data in header mode + * @param[in] dev : structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static void unpack_gyro_frame(struct bmi160_sensor_data *gyro, + uint16_t *idx, + uint8_t *gyro_idx, + uint8_t frame_info, + const struct bmi160_dev *dev); + +/*! + * @brief This API is used to parse the gyro data from the + * FIFO data and store it in the instance of the structure bmi160_sensor_data. + * + * @param[in,out] gyro_data : structure instance of sensor data + * @param[in,out] data_start_index : Index value of number of bytes parsed + * @param[in] dev : structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static void unpack_gyro_data(struct bmi160_sensor_data *gyro_data, + uint16_t data_start_index, + const struct bmi160_dev *dev); + +/*! + * @brief This API is used to parse the gyro data from the + * FIFO data in header mode. + * + * @param[in,out] gyro_data : Structure instance of sensor data + * @param[in,out] gyro_length : Number of gyro frames + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static void extract_gyro_header_mode(struct bmi160_sensor_data *gyro_data, + uint8_t *gyro_length, + const struct bmi160_dev *dev); + +/*! + * @brief This API computes the number of bytes of aux FIFO data + * which is to be parsed in header-less mode + * + * @param[out] data_index : The start index for parsing data + * @param[out] data_read_length : No of bytes to be parsed from FIFO buffer + * @param[in] aux_frame_count : Number of Aux data frames to be read + * @param[in] dev : Structure instance of bmi160_dev. + */ +static void get_aux_len_to_parse(uint16_t *data_index, + uint16_t *data_read_length, + const uint8_t *aux_frame_count, + const struct bmi160_dev *dev); + +/*! + * @brief This API is used to parse the aux's data from the + * FIFO data in both header mode and header-less mode. + * It updates the idx value which is used to store the index of + * the current data byte which is parsed + * + * @param[in,out] aux_data : structure instance of sensor data + * @param[in,out] idx : Index value of number of bytes parsed + * @param[in,out] aux_index : Index value of gyro data + * (x,y,z axes) frames parsed + * @param[in] frame_info : It consists of either fifo_data_enable + * parameter in header-less mode or + * frame header data in header mode + * @param[in] dev : structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static void unpack_aux_frame(struct bmi160_aux_data *aux_data, + uint16_t *idx, + uint8_t *aux_index, + uint8_t frame_info, + const struct bmi160_dev *dev); + +/*! + * @brief This API is used to parse the aux data from the + * FIFO data and store it in the instance of the structure bmi160_aux_data. + * + * @param[in,out] aux_data : structure instance of sensor data + * @param[in,out] data_start_index : Index value of number of bytes parsed + * @param[in] dev : structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static void unpack_aux_data(struct bmi160_aux_data *aux_data, uint16_t data_start_index, const struct bmi160_dev *dev); + +/*! + * @brief This API is used to parse the aux data from the + * FIFO data in header mode. + * + * @param[in,out] aux_data : Structure instance of sensor data + * @param[in,out] aux_length : Number of aux frames + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static void extract_aux_header_mode(struct bmi160_aux_data *aux_data, uint8_t *aux_length, + const struct bmi160_dev *dev); + +/*! + * @brief This API checks the presence of non-valid frames in the read fifo data. + * + * @param[in,out] data_index : The index of the current data to + * be parsed from fifo data + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static void check_frame_validity(uint16_t *data_index, const struct bmi160_dev *dev); + +/*! + * @brief This API is used to move the data index ahead of the + * current_frame_length parameter when unnecessary FIFO data appears while + * extracting the user specified data. + * + * @param[in,out] data_index : Index of the FIFO data which + * is to be moved ahead of the + * current_frame_length + * @param[in] current_frame_length : Number of bytes in a particular frame + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static void move_next_frame(uint16_t *data_index, uint8_t current_frame_length, const struct bmi160_dev *dev); + +/*! + * @brief This API is used to parse and store the sensor time from the + * FIFO data in the structure instance dev. + * + * @param[in,out] data_index : Index of the FIFO data which + * has the sensor time. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static void unpack_sensortime_frame(uint16_t *data_index, const struct bmi160_dev *dev); + +/*! + * @brief This API is used to parse and store the skipped_frame_count from + * the FIFO data in the structure instance dev. + * + * @param[in,out] data_index : Index of the FIFO data which + * has the skipped frame count. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static void unpack_skipped_frame(uint16_t *data_index, const struct bmi160_dev *dev); + +/*! + * @brief This API is used to get the FOC status from the sensor + * + * @param[in,out] foc_status : Result of FOC status. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t get_foc_status(uint8_t *foc_status, struct bmi160_dev const *dev); + +/*! + * @brief This API is used to configure the offset enable bits in the sensor + * + * @param[in,out] foc_conf : Structure instance of bmi160_foc_conf which + * has the FOC and offset configurations + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t configure_offset_enable(const struct bmi160_foc_conf *foc_conf, struct bmi160_dev const *dev); + +/*! + * @brief This API is used to trigger the FOC in the sensor + * + * @param[in,out] offset : Structure instance of bmi160_offsets which + * reads and stores the offset values after FOC + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t trigger_foc(struct bmi160_offsets *offset, struct bmi160_dev const *dev); + +/*! + * @brief This API is used to map/unmap the Dataready(Accel & Gyro), FIFO full + * and FIFO watermark interrupt + * + * @param[in] int_config : Structure instance of bmi160_int_settg which + * stores the interrupt type and interrupt channel + * configurations to map/unmap the interrupt pins + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t map_hardware_interrupt(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev); + +/*! + * @brief This API is used to map/unmap the Any/Sig motion, Step det/Low-g, + * Double tap, Single tap, Orientation, Flat, High-G, Nomotion interrupt pins. + * + * @param[in] int_config : Structure instance of bmi160_int_settg which + * stores the interrupt type and interrupt channel + * configurations to map/unmap the interrupt pins + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval zero -> Success / -ve value -> Error + */ +static int8_t map_feature_interrupt(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev); + +/*********************** User function definitions ****************************/ + +/*! + * @brief This API reads the data from the given register address + * of sensor. + */ +int8_t bmi160_get_regs(uint8_t reg_addr, uint8_t *data, uint16_t len, const struct bmi160_dev *dev) +{ + int8_t rslt = BMI160_OK; + + /* Null-pointer check */ + if ((dev == NULL) || (dev->read == NULL)) + { + rslt = BMI160_E_NULL_PTR; + } + else if (len == 0) + { + rslt = BMI160_E_READ_WRITE_LENGTH_INVALID; + } + else + { + /* Configuring reg_addr for SPI Interface */ + if (dev->intf == BMI160_SPI_INTF) + { + reg_addr = (reg_addr | BMI160_SPI_RD_MASK); + } + + rslt = dev->read(dev->id, reg_addr, data, len); + } + + return rslt; +} + +/*! + * @brief This API writes the given data to the register address + * of sensor. + */ +int8_t bmi160_set_regs(uint8_t reg_addr, uint8_t *data, uint16_t len, const struct bmi160_dev *dev) +{ + int8_t rslt = BMI160_OK; + uint8_t count = 0; + + /* Null-pointer check */ + if ((dev == NULL) || (dev->write == NULL)) + { + rslt = BMI160_E_NULL_PTR; + } + else if (len == 0) + { + rslt = BMI160_E_READ_WRITE_LENGTH_INVALID; + } + else + { + /* Configuring reg_addr for SPI Interface */ + if (dev->intf == BMI160_SPI_INTF) + { + reg_addr = (reg_addr & BMI160_SPI_WR_MASK); + } + + if ((dev->prev_accel_cfg.power == BMI160_ACCEL_NORMAL_MODE) || + (dev->prev_gyro_cfg.power == BMI160_GYRO_NORMAL_MODE)) + { + rslt = dev->write(dev->id, reg_addr, data, len); + + /* Kindly refer bmi160 data sheet section 3.2.4 */ + dev->delay_ms(1); + + } + else + { + /*Burst write is not allowed in + * suspend & low power mode */ + for (; count < len; count++) + { + rslt = dev->write(dev->id, reg_addr, &data[count], 1); + reg_addr++; + + /* Kindly refer bmi160 data sheet section 3.2.4 */ + dev->delay_ms(1); + + } + } + + if (rslt != BMI160_OK) + { + rslt = BMI160_E_COM_FAIL; + } + } + + return rslt; +} + +/*! + * @brief This API is the entry point for sensor.It performs + * the selection of I2C/SPI read mechanism according to the + * selected interface and reads the chip-id of bmi160 sensor. + */ +int8_t bmi160_init(struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data; + uint8_t try = 3; + + /* Null-pointer check */ + rslt = null_ptr_check(dev); + + /* Dummy read of 0x7F register to enable SPI Interface + * if SPI is used */ + if ((rslt == BMI160_OK) && (dev->intf == BMI160_SPI_INTF)) + { + rslt = bmi160_get_regs(BMI160_SPI_COMM_TEST_ADDR, &data, 1, dev); + } + + if (rslt == BMI160_OK) + { + /* Assign chip id as zero */ + dev->chip_id = 0; + + while ((try--) && (dev->chip_id != BMI160_CHIP_ID)) + { + /* Read chip_id */ + rslt = bmi160_get_regs(BMI160_CHIP_ID_ADDR, &dev->chip_id, 1, dev); + } + + if ((rslt == BMI160_OK) && (dev->chip_id == BMI160_CHIP_ID)) + { + dev->any_sig_sel = BMI160_BOTH_ANY_SIG_MOTION_DISABLED; + + /* Soft reset */ + rslt = bmi160_soft_reset(dev); + } + else + { + rslt = BMI160_E_DEV_NOT_FOUND; + } + } + + return rslt; +} + +/*! + * @brief This API resets and restarts the device. + * All register values are overwritten with default parameters. + */ +int8_t bmi160_soft_reset(struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data = BMI160_SOFT_RESET_CMD; + + /* Null-pointer check */ + if ((dev == NULL) || (dev->delay_ms == NULL)) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + /* Reset the device */ + rslt = bmi160_set_regs(BMI160_COMMAND_REG_ADDR, &data, 1, dev); + dev->delay_ms(BMI160_SOFT_RESET_DELAY_MS); + if ((rslt == BMI160_OK) && (dev->intf == BMI160_SPI_INTF)) + { + /* Dummy read of 0x7F register to enable SPI Interface + * if SPI is used */ + rslt = bmi160_get_regs(BMI160_SPI_COMM_TEST_ADDR, &data, 1, dev); + } + + if (rslt == BMI160_OK) + { + /* Update the default parameters */ + default_param_settg(dev); + } + } + + return rslt; +} + +/*! + * @brief This API configures the power mode, range and bandwidth + * of sensor. + */ +int8_t bmi160_set_sens_conf(struct bmi160_dev *dev) +{ + int8_t rslt = BMI160_OK; + + /* Null-pointer check */ + if ((dev == NULL) || (dev->delay_ms == NULL)) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + rslt = set_accel_conf(dev); + if (rslt == BMI160_OK) + { + rslt = set_gyro_conf(dev); + if (rslt == BMI160_OK) + { + /* write power mode for accel and gyro */ + rslt = bmi160_set_power_mode(dev); + if (rslt == BMI160_OK) + { + rslt = check_invalid_settg(dev); + } + } + } + } + + return rslt; +} + +/*! + * @brief This API gets accel and gyro configurations. + */ +int8_t bmi160_get_sens_conf(struct bmi160_dev *dev) +{ + int8_t rslt = BMI160_OK; + + /* Null-pointer check */ + if ((dev == NULL) || (dev->delay_ms == NULL)) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + rslt = get_accel_conf(dev); + if (rslt == BMI160_OK) + { + rslt = get_gyro_conf(dev); + } + } + + return rslt; +} + +/*! + * @brief This API sets the power mode of the sensor. + */ +int8_t bmi160_set_power_mode(struct bmi160_dev *dev) +{ + int8_t rslt = 0; + + /* Null-pointer check */ + if ((dev == NULL) || (dev->delay_ms == NULL)) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + rslt = set_accel_pwr(dev); + if (rslt == BMI160_OK) + { + rslt = set_gyro_pwr(dev); + } + } + + return rslt; +} + +/*! + * @brief This API gets the power mode of the sensor. + */ +int8_t bmi160_get_power_mode(struct bmi160_dev *dev) +{ + int8_t rslt = 0; + uint8_t power_mode = 0; + + /* Null-pointer check */ + if ((dev == NULL) || (dev->delay_ms == NULL)) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + rslt = bmi160_get_regs(BMI160_PMU_STATUS_ADDR, &power_mode, 1, dev); + if (rslt == BMI160_OK) + { + /* Power mode of the accel, gyro sensor is obtained */ + dev->gyro_cfg.power = BMI160_GET_BITS(power_mode, BMI160_GYRO_POWER_MODE); + dev->accel_cfg.power = BMI160_GET_BITS(power_mode, BMI160_ACCEL_POWER_MODE); + } + } + + return rslt; +} + +/*! + * @brief This API reads sensor data, stores it in + * the bmi160_sensor_data structure pointer passed by the user. + */ +int8_t bmi160_get_sensor_data(uint8_t select_sensor, + struct bmi160_sensor_data *accel, + struct bmi160_sensor_data *gyro, + const struct bmi160_dev *dev) +{ + int8_t rslt = BMI160_OK; + uint8_t time_sel; + uint8_t sen_sel; + uint8_t len = 0; + + /*Extract the sensor and time select information*/ + sen_sel = select_sensor & BMI160_SEN_SEL_MASK; + time_sel = ((sen_sel & BMI160_TIME_SEL) >> 2); + sen_sel = sen_sel & (BMI160_ACCEL_SEL | BMI160_GYRO_SEL); + if (time_sel == 1) + { + len = 3; + } + + /* Null-pointer check */ + if (dev != NULL) + { + switch (sen_sel) + { + case BMI160_ACCEL_ONLY: + + /* Null-pointer check */ + if (accel == NULL) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + rslt = get_accel_data(len, accel, dev); + } + + break; + case BMI160_GYRO_ONLY: + + /* Null-pointer check */ + if (gyro == NULL) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + rslt = get_gyro_data(len, gyro, dev); + } + + break; + case BMI160_BOTH_ACCEL_AND_GYRO: + + /* Null-pointer check */ + if ((gyro == NULL) || (accel == NULL)) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + rslt = get_accel_gyro_data(len, accel, gyro, dev); + } + + break; + default: + rslt = BMI160_E_INVALID_INPUT; + break; + } + } + else + { + rslt = BMI160_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API configures the necessary interrupt based on + * the user settings in the bmi160_int_settg structure instance. + */ +int8_t bmi160_set_int_config(struct bmi160_int_settg *int_config, struct bmi160_dev *dev) +{ + int8_t rslt = BMI160_OK; + + switch (int_config->int_type) + { + case BMI160_ACC_ANY_MOTION_INT: + + /*Any-motion interrupt*/ + rslt = set_accel_any_motion_int(int_config, dev); + break; + case BMI160_ACC_SIG_MOTION_INT: + + /* Significant motion interrupt */ + rslt = set_accel_sig_motion_int(int_config, dev); + break; + case BMI160_ACC_SLOW_NO_MOTION_INT: + + /* Slow or no motion interrupt */ + rslt = set_accel_no_motion_int(int_config, dev); + break; + case BMI160_ACC_DOUBLE_TAP_INT: + case BMI160_ACC_SINGLE_TAP_INT: + + /* Double tap and single tap Interrupt */ + rslt = set_accel_tap_int(int_config, dev); + break; + case BMI160_STEP_DETECT_INT: + + /* Step detector interrupt */ + rslt = set_accel_step_detect_int(int_config, dev); + break; + case BMI160_ACC_ORIENT_INT: + + /* Orientation interrupt */ + rslt = set_accel_orientation_int(int_config, dev); + break; + case BMI160_ACC_FLAT_INT: + + /* Flat detection interrupt */ + rslt = set_accel_flat_detect_int(int_config, dev); + break; + case BMI160_ACC_LOW_G_INT: + + /* Low-g interrupt */ + rslt = set_accel_low_g_int(int_config, dev); + break; + case BMI160_ACC_HIGH_G_INT: + + /* High-g interrupt */ + rslt = set_accel_high_g_int(int_config, dev); + break; + case BMI160_ACC_GYRO_DATA_RDY_INT: + + /* Data ready interrupt */ + rslt = set_accel_gyro_data_ready_int(int_config, dev); + break; + case BMI160_ACC_GYRO_FIFO_FULL_INT: + + /* Fifo full interrupt */ + rslt = set_fifo_full_int(int_config, dev); + break; + case BMI160_ACC_GYRO_FIFO_WATERMARK_INT: + + /* Fifo water-mark interrupt */ + rslt = set_fifo_watermark_int(int_config, dev); + break; + case BMI160_FIFO_TAG_INT_PIN: + + /* Fifo tagging feature support */ + /* Configure Interrupt pins */ + rslt = set_intr_pin_config(int_config, dev); + break; + default: + break; + } + + return rslt; +} + +/*! + * @brief This API enables or disable the step counter feature. + * 1 - enable step counter (0 - disable) + */ +int8_t bmi160_set_step_counter(uint8_t step_cnt_enable, const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data = 0; + + /* Null-pointer check */ + rslt = null_ptr_check(dev); + if (rslt != BMI160_OK) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + rslt = bmi160_get_regs(BMI160_INT_STEP_CONFIG_1_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + if (step_cnt_enable == BMI160_ENABLE) + { + data |= (uint8_t)(step_cnt_enable << 3); + } + else + { + data &= ~BMI160_STEP_COUNT_EN_BIT_MASK; + } + + rslt = bmi160_set_regs(BMI160_INT_STEP_CONFIG_1_ADDR, &data, 1, dev); + } + } + + return rslt; +} + +/*! + * @brief This API reads the step counter value. + */ +int8_t bmi160_read_step_counter(uint16_t *step_val, const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data[2] = { 0, 0 }; + uint16_t msb = 0; + uint8_t lsb = 0; + + /* Null-pointer check */ + rslt = null_ptr_check(dev); + if (rslt != BMI160_OK) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + rslt = bmi160_get_regs(BMI160_INT_STEP_CNT_0_ADDR, data, 2, dev); + if (rslt == BMI160_OK) + { + lsb = data[0]; + msb = data[1] << 8; + *step_val = msb | lsb; + } + } + + return rslt; +} + +/*! + * @brief This API reads the mention no of byte of data from the given + * register address of auxiliary sensor. + */ +int8_t bmi160_aux_read(uint8_t reg_addr, uint8_t *aux_data, uint16_t len, const struct bmi160_dev *dev) +{ + int8_t rslt = BMI160_OK; + uint16_t map_len = 0; + + /* Null-pointer check */ + if ((dev == NULL) || (dev->read == NULL)) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + if (dev->aux_cfg.aux_sensor_enable == BMI160_ENABLE) + { + rslt = map_read_len(&map_len, dev); + if (rslt == BMI160_OK) + { + rslt = extract_aux_read(map_len, reg_addr, aux_data, len, dev); + } + } + else + { + rslt = BMI160_E_INVALID_INPUT; + } + } + + return rslt; +} + +/*! + * @brief This API writes the mention no of byte of data to the given + * register address of auxiliary sensor. + */ +int8_t bmi160_aux_write(uint8_t reg_addr, uint8_t *aux_data, uint16_t len, const struct bmi160_dev *dev) +{ + int8_t rslt = BMI160_OK; + uint8_t count = 0; + + /* Null-pointer check */ + if ((dev == NULL) || (dev->write == NULL)) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + for (; count < len; count++) + { + /* set data to write */ + rslt = bmi160_set_regs(BMI160_AUX_IF_4_ADDR, aux_data, 1, dev); + dev->delay_ms(BMI160_AUX_COM_DELAY); + if (rslt == BMI160_OK) + { + /* set address to write */ + rslt = bmi160_set_regs(BMI160_AUX_IF_3_ADDR, ®_addr, 1, dev); + dev->delay_ms(BMI160_AUX_COM_DELAY); + if (rslt == BMI160_OK && (count < len - 1)) + { + aux_data++; + reg_addr++; + } + } + } + } + + return rslt; +} + +/*! + * @brief This API initialize the auxiliary sensor + * in order to access it. + */ +int8_t bmi160_aux_init(const struct bmi160_dev *dev) +{ + int8_t rslt; + + /* Null-pointer check */ + rslt = null_ptr_check(dev); + if (rslt != BMI160_OK) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + if (dev->aux_cfg.aux_sensor_enable == BMI160_ENABLE) + { + /* Configures the auxiliary sensor interface settings */ + rslt = config_aux_settg(dev); + } + else + { + rslt = BMI160_E_INVALID_INPUT; + } + } + + return rslt; +} + +/*! + * @brief This API is used to setup the auxiliary sensor of bmi160 in auto mode + * Thus enabling the auto update of 8 bytes of data from auxiliary sensor + * to BMI160 register address 0x04 to 0x0B + */ +int8_t bmi160_set_aux_auto_mode(uint8_t *data_addr, struct bmi160_dev *dev) +{ + int8_t rslt; + + /* Null-pointer check */ + rslt = null_ptr_check(dev); + if (rslt != BMI160_OK) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + if (dev->aux_cfg.aux_sensor_enable == BMI160_ENABLE) + { + /* Write the aux. address to read in 0x4D of BMI160*/ + rslt = bmi160_set_regs(BMI160_AUX_IF_2_ADDR, data_addr, 1, dev); + dev->delay_ms(BMI160_AUX_COM_DELAY); + if (rslt == BMI160_OK) + { + /* Configure the polling ODR for + * auxiliary sensor */ + rslt = config_aux_odr(dev); + if (rslt == BMI160_OK) + { + /* Disable the aux. manual mode, i.e aux. + * sensor is in auto-mode (data-mode) */ + dev->aux_cfg.manual_enable = BMI160_DISABLE; + rslt = bmi160_config_aux_mode(dev); + + /* Auxiliary sensor data is obtained + * in auto mode from this point */ + } + } + } + else + { + rslt = BMI160_E_INVALID_INPUT; + } + } + + return rslt; +} + +/*! + * @brief This API configures the 0x4C register and settings like + * Auxiliary sensor manual enable/ disable and aux burst read length. + */ +int8_t bmi160_config_aux_mode(const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t aux_if[2] = { (uint8_t)(dev->aux_cfg.aux_i2c_addr * 2), 0 }; + + rslt = bmi160_get_regs(BMI160_AUX_IF_1_ADDR, &aux_if[1], 1, dev); + if (rslt == BMI160_OK) + { + /* update the Auxiliary interface to manual/auto mode */ + aux_if[1] = BMI160_SET_BITS(aux_if[1], BMI160_MANUAL_MODE_EN, dev->aux_cfg.manual_enable); + + /* update the burst read length defined by user */ + aux_if[1] = BMI160_SET_BITS_POS_0(aux_if[1], BMI160_AUX_READ_BURST, dev->aux_cfg.aux_rd_burst_len); + + /* Set the secondary interface address and manual mode + * along with burst read length */ + rslt = bmi160_set_regs(BMI160_AUX_IF_0_ADDR, &aux_if[0], 2, dev); + dev->delay_ms(BMI160_AUX_COM_DELAY); + } + + return rslt; +} + +/*! + * @brief This API is used to read the raw uncompensated auxiliary sensor + * data of 8 bytes from BMI160 register address 0x04 to 0x0B + */ +int8_t bmi160_read_aux_data_auto_mode(uint8_t *aux_data, const struct bmi160_dev *dev) +{ + int8_t rslt; + + /* Null-pointer check */ + rslt = null_ptr_check(dev); + if (rslt != BMI160_OK) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + if ((dev->aux_cfg.aux_sensor_enable == BMI160_ENABLE) && (dev->aux_cfg.manual_enable == BMI160_DISABLE)) + { + /* Read the aux. sensor's raw data */ + rslt = bmi160_get_regs(BMI160_AUX_DATA_ADDR, aux_data, 8, dev); + } + else + { + rslt = BMI160_E_INVALID_INPUT; + } + } + + return rslt; +} + +/*! + * @brief This is used to perform self test of accel/gyro of the BMI160 sensor + */ +int8_t bmi160_perform_self_test(uint8_t select_sensor, struct bmi160_dev *dev) +{ + int8_t rslt; + int8_t self_test_rslt = 0; + + /* Null-pointer check */ + rslt = null_ptr_check(dev); + if (rslt != BMI160_OK) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + + /* Proceed if null check is fine */ + switch (select_sensor) + { + case BMI160_ACCEL_ONLY: + rslt = perform_accel_self_test(dev); + break; + case BMI160_GYRO_ONLY: + + /* Set the power mode as normal mode */ + dev->gyro_cfg.power = BMI160_GYRO_NORMAL_MODE; + rslt = bmi160_set_power_mode(dev); + + /* Perform gyro self test */ + if (rslt == BMI160_OK) + { + /* Perform gyro self test */ + rslt = perform_gyro_self_test(dev); + } + + break; + default: + rslt = BMI160_E_INVALID_INPUT; + break; + } + + /* Check to ensure bus error does not occur */ + if (rslt >= BMI160_OK) + { + /* Store the status of self test result */ + self_test_rslt = rslt; + + /* Perform soft reset */ + rslt = bmi160_soft_reset(dev); + + } + + /* Check to ensure bus operations are success */ + if (rslt == BMI160_OK) + { + /* Restore self_test_rslt as return value */ + rslt = self_test_rslt; + } + } + + return rslt; +} + +/*! + * @brief This API reads the data from fifo buffer. + */ +int8_t bmi160_get_fifo_data(struct bmi160_dev const *dev) +{ + int8_t rslt = 0; + uint16_t bytes_to_read = 0; + uint16_t user_fifo_len = 0; + + /* check the bmi160 structure as NULL*/ + if ((dev == NULL) || (dev->fifo->data == NULL)) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + reset_fifo_data_structure(dev); + + /* get current FIFO fill-level*/ + rslt = get_fifo_byte_counter(&bytes_to_read, dev); + if (rslt == BMI160_OK) + { + user_fifo_len = dev->fifo->length; + if ((dev->fifo->length > bytes_to_read)) + { + /* Handling the case where user requests + * more data than available in FIFO */ + dev->fifo->length = bytes_to_read; + } + + if ((dev->fifo->fifo_time_enable == BMI160_FIFO_TIME_ENABLE) && + (bytes_to_read + BMI160_FIFO_BYTES_OVERREAD <= user_fifo_len)) + { + /* Handling case of sensor time availability*/ + dev->fifo->length = dev->fifo->length + BMI160_FIFO_BYTES_OVERREAD; + } + + /* read only the filled bytes in the FIFO Buffer */ + rslt = bmi160_get_regs(BMI160_FIFO_DATA_ADDR, dev->fifo->data, dev->fifo->length, dev); + } + } + + return rslt; +} + +/*! + * @brief This API writes fifo_flush command to command register.This + * action clears all data in the Fifo without changing fifo configuration + * settings + */ +int8_t bmi160_set_fifo_flush(const struct bmi160_dev *dev) +{ + int8_t rslt = 0; + uint8_t data = BMI160_FIFO_FLUSH_VALUE; + uint8_t reg_addr = BMI160_COMMAND_REG_ADDR; + + /* Check the bmi160_dev structure for NULL address*/ + if (dev == NULL) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + rslt = bmi160_set_regs(reg_addr, &data, BMI160_ONE, dev); + } + + return rslt; +} + +/*! + * @brief This API sets the FIFO configuration in the sensor. + */ +int8_t bmi160_set_fifo_config(uint8_t config, uint8_t enable, struct bmi160_dev const *dev) +{ + int8_t rslt = 0; + uint8_t data = 0; + uint8_t reg_addr = BMI160_FIFO_CONFIG_1_ADDR; + uint8_t fifo_config = config & BMI160_FIFO_CONFIG_1_MASK; + + /* Check the bmi160_dev structure for NULL address*/ + if (dev == NULL) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + rslt = bmi160_get_regs(reg_addr, &data, BMI160_ONE, dev); + if (rslt == BMI160_OK) + { + if (fifo_config > 0) + { + if (enable == BMI160_ENABLE) + { + data = data | fifo_config; + } + else + { + data = data & (~fifo_config); + } + } + + /* write fifo frame content configuration*/ + rslt = bmi160_set_regs(reg_addr, &data, BMI160_ONE, dev); + if (rslt == BMI160_OK) + { + /* read fifo frame content configuration*/ + rslt = bmi160_get_regs(reg_addr, &data, BMI160_ONE, dev); + if (rslt == BMI160_OK) + { + /* extract fifo header enabled status */ + dev->fifo->fifo_header_enable = data & BMI160_FIFO_HEAD_ENABLE; + + /* extract accel/gyr/aux. data enabled status */ + dev->fifo->fifo_data_enable = data & BMI160_FIFO_M_G_A_ENABLE; + + /* extract fifo sensor time enabled status */ + dev->fifo->fifo_time_enable = data & BMI160_FIFO_TIME_ENABLE; + } + } + } + } + + return rslt; +} + +/*! @brief This API is used to configure the down sampling ratios of + * the accel and gyro data for FIFO.Also, it configures filtered or + * pre-filtered data for accel and gyro. + * + */ +int8_t bmi160_set_fifo_down(uint8_t fifo_down, const struct bmi160_dev *dev) +{ + int8_t rslt = 0; + uint8_t data = 0; + uint8_t reg_addr = BMI160_FIFO_DOWN_ADDR; + + /* Check the bmi160_dev structure for NULL address*/ + if (dev == NULL) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + rslt = bmi160_get_regs(reg_addr, &data, BMI160_ONE, dev); + if (rslt == BMI160_OK) + { + data = data | fifo_down; + rslt = bmi160_set_regs(reg_addr, &data, BMI160_ONE, dev); + } + } + + return rslt; +} + +/*! + * @brief This API sets the FIFO watermark level in the sensor. + * + */ +int8_t bmi160_set_fifo_wm(uint8_t fifo_wm, const struct bmi160_dev *dev) +{ + int8_t rslt = 0; + uint8_t data = fifo_wm; + uint8_t reg_addr = BMI160_FIFO_CONFIG_0_ADDR; + + /* Check the bmi160_dev structure for NULL address*/ + if (dev == NULL) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + rslt = bmi160_set_regs(reg_addr, &data, BMI160_ONE, dev); + } + + return rslt; +} + +/*! + * @brief This API parses and extracts the accelerometer frames from + * FIFO data read by the "bmi160_get_fifo_data" API and stores it in + * the "accel_data" structure instance. + */ +int8_t bmi160_extract_accel(struct bmi160_sensor_data *accel_data, uint8_t *accel_length, struct bmi160_dev const *dev) +{ + int8_t rslt = 0; + uint16_t data_index = 0; + uint16_t data_read_length = 0; + uint8_t accel_index = 0; + uint8_t fifo_data_enable = 0; + + if (dev == NULL || dev->fifo == NULL || dev->fifo->data == NULL) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + /* Parsing the FIFO data in header-less mode */ + if (dev->fifo->fifo_header_enable == 0) + { + /* Number of bytes to be parsed from FIFO */ + get_accel_len_to_parse(&data_index, &data_read_length, accel_length, dev); + for (; data_index < data_read_length;) + { + /*Check for the availability of next two bytes of FIFO data */ + check_frame_validity(&data_index, dev); + fifo_data_enable = dev->fifo->fifo_data_enable; + unpack_accel_frame(accel_data, &data_index, &accel_index, fifo_data_enable, dev); + } + + /* update number of accel data read*/ + *accel_length = accel_index; + + /*update the accel byte index*/ + dev->fifo->accel_byte_start_idx = data_index; + } + else + { + /* Parsing the FIFO data in header mode */ + extract_accel_header_mode(accel_data, accel_length, dev); + } + } + + return rslt; +} + +/*! + * @brief This API parses and extracts the gyro frames from + * FIFO data read by the "bmi160_get_fifo_data" API and stores it in + * the "gyro_data" structure instance. + */ +int8_t bmi160_extract_gyro(struct bmi160_sensor_data *gyro_data, uint8_t *gyro_length, struct bmi160_dev const *dev) +{ + int8_t rslt = 0; + uint16_t data_index = 0; + uint16_t data_read_length = 0; + uint8_t gyro_index = 0; + uint8_t fifo_data_enable = 0; + + if (dev == NULL || dev->fifo->data == NULL) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + /* Parsing the FIFO data in header-less mode */ + if (dev->fifo->fifo_header_enable == 0) + { + /* Number of bytes to be parsed from FIFO */ + get_gyro_len_to_parse(&data_index, &data_read_length, gyro_length, dev); + for (; data_index < data_read_length;) + { + /*Check for the availability of next two bytes of FIFO data */ + check_frame_validity(&data_index, dev); + fifo_data_enable = dev->fifo->fifo_data_enable; + unpack_gyro_frame(gyro_data, &data_index, &gyro_index, fifo_data_enable, dev); + } + + /* update number of gyro data read */ + *gyro_length = gyro_index; + + /* update the gyro byte index */ + dev->fifo->gyro_byte_start_idx = data_index; + } + else + { + /* Parsing the FIFO data in header mode */ + extract_gyro_header_mode(gyro_data, gyro_length, dev); + } + } + + return rslt; +} + +/*! + * @brief This API parses and extracts the aux frames from + * FIFO data read by the "bmi160_get_fifo_data" API and stores it in + * the "aux_data" structure instance. + */ +int8_t bmi160_extract_aux(struct bmi160_aux_data *aux_data, uint8_t *aux_len, struct bmi160_dev const *dev) +{ + int8_t rslt = 0; + uint16_t data_index = 0; + uint16_t data_read_length = 0; + uint8_t aux_index = 0; + uint8_t fifo_data_enable = 0; + + if ((dev == NULL) || (dev->fifo->data == NULL) || (aux_data == NULL)) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + /* Parsing the FIFO data in header-less mode */ + if (dev->fifo->fifo_header_enable == 0) + { + /* Number of bytes to be parsed from FIFO */ + get_aux_len_to_parse(&data_index, &data_read_length, aux_len, dev); + for (; data_index < data_read_length;) + { + /* Check for the availability of next two + * bytes of FIFO data */ + check_frame_validity(&data_index, dev); + fifo_data_enable = dev->fifo->fifo_data_enable; + unpack_aux_frame(aux_data, &data_index, &aux_index, fifo_data_enable, dev); + } + + /* update number of aux data read */ + *aux_len = aux_index; + + /* update the aux byte index */ + dev->fifo->aux_byte_start_idx = data_index; + } + else + { + /* Parsing the FIFO data in header mode */ + extract_aux_header_mode(aux_data, aux_len, dev); + } + } + + return rslt; +} + +/*! + * @brief This API starts the FOC of accel and gyro + * + * @note FOC should not be used in low-power mode of sensor + * + * @note Accel FOC targets values of +1g , 0g , -1g + * Gyro FOC always targets value of 0 dps + */ +int8_t bmi160_start_foc(const struct bmi160_foc_conf *foc_conf, + struct bmi160_offsets *offset, + struct bmi160_dev const *dev) +{ + int8_t rslt; + uint8_t data; + + /* Null-pointer check */ + rslt = null_ptr_check(dev); + if (rslt != BMI160_OK) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + /* Set the offset enable bits */ + rslt = configure_offset_enable(foc_conf, dev); + if (rslt == BMI160_OK) + { + /* Read the FOC config from the sensor */ + rslt = bmi160_get_regs(BMI160_FOC_CONF_ADDR, &data, 1, dev); + + /* Set the FOC config for gyro */ + data = BMI160_SET_BITS(data, BMI160_GYRO_FOC_EN, foc_conf->foc_gyr_en); + + /* Set the FOC config for accel xyz axes */ + data = BMI160_SET_BITS(data, BMI160_ACCEL_FOC_X_CONF, foc_conf->foc_acc_x); + data = BMI160_SET_BITS(data, BMI160_ACCEL_FOC_Y_CONF, foc_conf->foc_acc_y); + data = BMI160_SET_BITS_POS_0(data, BMI160_ACCEL_FOC_Z_CONF, foc_conf->foc_acc_z); + if (rslt == BMI160_OK) + { + /* Set the FOC config in the sensor */ + rslt = bmi160_set_regs(BMI160_FOC_CONF_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + /* Procedure to trigger + * FOC and check status */ + rslt = trigger_foc(offset, dev); + } + } + } + } + + return rslt; +} + +/*! + * @brief This API reads and stores the offset values of accel and gyro + */ +int8_t bmi160_get_offsets(struct bmi160_offsets *offset, const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data[7]; + uint8_t lsb, msb; + int16_t offset_msb, offset_lsb; + int16_t offset_data; + + /* Null-pointer check */ + rslt = null_ptr_check(dev); + if (rslt != BMI160_OK) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + /* Read the FOC config from the sensor */ + rslt = bmi160_get_regs(BMI160_OFFSET_ADDR, data, 7, dev); + + /* Accel offsets */ + offset->off_acc_x = (int8_t)data[0]; + offset->off_acc_y = (int8_t)data[1]; + offset->off_acc_z = (int8_t)data[2]; + + /* Gyro x-axis offset */ + lsb = data[3]; + msb = BMI160_GET_BITS_POS_0(data[6], BMI160_GYRO_OFFSET_X); + offset_msb = (int16_t)(msb << 14); + offset_lsb = lsb << 6; + offset_data = offset_msb | offset_lsb; + + /* Divide by 64 to get the Right shift by 6 value */ + offset->off_gyro_x = (int16_t)(offset_data / 64); + + /* Gyro y-axis offset */ + lsb = data[4]; + msb = BMI160_GET_BITS(data[6], BMI160_GYRO_OFFSET_Y); + offset_msb = (int16_t)(msb << 14); + offset_lsb = lsb << 6; + offset_data = offset_msb | offset_lsb; + + /* Divide by 64 to get the Right shift by 6 value */ + offset->off_gyro_y = (int16_t)(offset_data / 64); + + /* Gyro z-axis offset */ + lsb = data[5]; + msb = BMI160_GET_BITS(data[6], BMI160_GYRO_OFFSET_Z); + offset_msb = (int16_t)(msb << 14); + offset_lsb = lsb << 6; + offset_data = offset_msb | offset_lsb; + + /* Divide by 64 to get the Right shift by 6 value */ + offset->off_gyro_z = (int16_t)(offset_data / 64); + } + + return rslt; +} + +/*! + * @brief This API writes the offset values of accel and gyro to + * the sensor but these values will be reset on POR or soft reset. + */ +int8_t bmi160_set_offsets(const struct bmi160_foc_conf *foc_conf, + const struct bmi160_offsets *offset, + struct bmi160_dev const *dev) +{ + int8_t rslt; + uint8_t data[7]; + uint8_t x_msb, y_msb, z_msb; + + /* Null-pointer check */ + rslt = null_ptr_check(dev); + if (rslt != BMI160_OK) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + /* Update the accel offset */ + data[0] = (uint8_t)offset->off_acc_x; + data[1] = (uint8_t)offset->off_acc_y; + data[2] = (uint8_t)offset->off_acc_z; + + /* Update the LSB of gyro offset */ + data[3] = BMI160_GET_LSB(offset->off_gyro_x); + data[4] = BMI160_GET_LSB(offset->off_gyro_y); + data[5] = BMI160_GET_LSB(offset->off_gyro_z); + + /* Update the MSB of gyro offset */ + x_msb = BMI160_GET_BITS(offset->off_gyro_x, BMI160_GYRO_OFFSET); + y_msb = BMI160_GET_BITS(offset->off_gyro_y, BMI160_GYRO_OFFSET); + z_msb = BMI160_GET_BITS(offset->off_gyro_z, BMI160_GYRO_OFFSET); + data[6] = (uint8_t)(z_msb << 4 | y_msb << 2 | x_msb); + + /* Set the offset enable/disable for gyro and accel */ + data[6] = BMI160_SET_BITS(data[6], BMI160_GYRO_OFFSET_EN, foc_conf->gyro_off_en); + data[6] = BMI160_SET_BITS(data[6], BMI160_ACCEL_OFFSET_EN, foc_conf->acc_off_en); + + /* Set the offset config and values in the sensor */ + rslt = bmi160_set_regs(BMI160_OFFSET_ADDR, data, 7, dev); + } + + return rslt; +} + +/*! + * @brief This API writes the image registers values to NVM which is + * stored even after POR or soft reset + */ +int8_t bmi160_update_nvm(struct bmi160_dev const *dev) +{ + int8_t rslt; + uint8_t data; + uint8_t cmd = BMI160_NVM_BACKUP_EN; + + /* Read the nvm_prog_en configuration */ + rslt = bmi160_get_regs(BMI160_CONF_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + data = BMI160_SET_BITS(data, BMI160_NVM_UPDATE, 1); + + /* Set the nvm_prog_en bit in the sensor */ + rslt = bmi160_set_regs(BMI160_CONF_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + /* Update NVM */ + rslt = bmi160_set_regs(BMI160_COMMAND_REG_ADDR, &cmd, 1, dev); + if (rslt == BMI160_OK) + { + /* Check for NVM ready status */ + rslt = bmi160_get_regs(BMI160_STATUS_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + data = BMI160_GET_BITS(data, BMI160_NVM_STATUS); + if (data != BMI160_ENABLE) + { + /* Delay to update NVM */ + dev->delay_ms(25); + } + } + } + } + } + + return rslt; +} + +/*! + * @brief This API gets the interrupt status from the sensor. + */ +int8_t bmi160_get_int_status(enum bmi160_int_status_sel int_status_sel, + union bmi160_int_status *int_status, + struct bmi160_dev const *dev) +{ + int8_t rslt = 0; + + /* To get the status of all interrupts */ + if (int_status_sel == BMI160_INT_STATUS_ALL) + { + rslt = bmi160_get_regs(BMI160_INT_STATUS_ADDR, &int_status->data[0], 4, dev); + } + else + { + if (int_status_sel & BMI160_INT_STATUS_0) + { + rslt = bmi160_get_regs(BMI160_INT_STATUS_ADDR, &int_status->data[0], 1, dev); + } + + if (int_status_sel & BMI160_INT_STATUS_1) + { + rslt = bmi160_get_regs(BMI160_INT_STATUS_ADDR + 1, &int_status->data[1], 1, dev); + } + + if (int_status_sel & BMI160_INT_STATUS_2) + { + rslt = bmi160_get_regs(BMI160_INT_STATUS_ADDR + 2, &int_status->data[2], 1, dev); + } + + if (int_status_sel & BMI160_INT_STATUS_3) + { + rslt = bmi160_get_regs(BMI160_INT_STATUS_ADDR + 3, &int_status->data[3], 1, dev); + } + } + + return rslt; +} + +/*********************** Local function definitions ***************************/ + +/*! + * @brief This API sets the any-motion interrupt of the sensor. + * This interrupt occurs when accel values exceeds preset threshold + * for a certain period of time. + */ +static int8_t set_accel_any_motion_int(struct bmi160_int_settg *int_config, struct bmi160_dev *dev) +{ + int8_t rslt; + + /* Null-pointer check */ + rslt = null_ptr_check(dev); + if ((rslt != BMI160_OK) || (int_config == NULL)) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + /* updating the interrupt structure to local structure */ + struct bmi160_acc_any_mot_int_cfg *any_motion_int_cfg = &(int_config->int_type_cfg.acc_any_motion_int); + rslt = enable_accel_any_motion_int(any_motion_int_cfg, dev); + if (rslt == BMI160_OK) + { + rslt = config_any_motion_int_settg(int_config, any_motion_int_cfg, dev); + } + } + + return rslt; +} + +/*! + * @brief This API sets tap interrupts.Interrupt is fired when + * tap movements happen. + */ +static int8_t set_accel_tap_int(struct bmi160_int_settg *int_config, const struct bmi160_dev *dev) +{ + int8_t rslt; + + /* Null-pointer check */ + rslt = null_ptr_check(dev); + if ((rslt != BMI160_OK) || (int_config == NULL)) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + /* updating the interrupt structure to local structure */ + struct bmi160_acc_tap_int_cfg *tap_int_cfg = &(int_config->int_type_cfg.acc_tap_int); + rslt = enable_tap_int(int_config, tap_int_cfg, dev); + if (rslt == BMI160_OK) + { + /* Configure Interrupt pins */ + rslt = set_intr_pin_config(int_config, dev); + if (rslt == BMI160_OK) + { + rslt = config_tap_int_settg(int_config, tap_int_cfg, dev); + } + } + } + + return rslt; +} + +/*! + * @brief This API sets the data ready interrupt for both accel and gyro. + * This interrupt occurs when new accel and gyro data comes. + */ +static int8_t set_accel_gyro_data_ready_int(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev) +{ + int8_t rslt; + + /* Null-pointer check */ + rslt = null_ptr_check(dev); + if ((rslt != BMI160_OK) || (int_config == NULL)) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + rslt = enable_data_ready_int(dev); + if (rslt == BMI160_OK) + { + /* Configure Interrupt pins */ + rslt = set_intr_pin_config(int_config, dev); + if (rslt == BMI160_OK) + { + rslt = map_hardware_interrupt(int_config, dev); + } + } + } + + return rslt; +} + +/*! + * @brief This API sets the significant motion interrupt of the sensor.This + * interrupt occurs when there is change in user location. + */ +static int8_t set_accel_sig_motion_int(struct bmi160_int_settg *int_config, struct bmi160_dev *dev) +{ + int8_t rslt; + + /* Null-pointer check */ + rslt = null_ptr_check(dev); + if ((rslt != BMI160_OK) || (int_config == NULL)) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + /* updating the interrupt structure to local structure */ + struct bmi160_acc_sig_mot_int_cfg *sig_mot_int_cfg = &(int_config->int_type_cfg.acc_sig_motion_int); + rslt = enable_sig_motion_int(sig_mot_int_cfg, dev); + if (rslt == BMI160_OK) + { + rslt = config_sig_motion_int_settg(int_config, sig_mot_int_cfg, dev); + } + } + + return rslt; +} + +/*! + * @brief This API sets the no motion/slow motion interrupt of the sensor. + * Slow motion is similar to any motion interrupt.No motion interrupt + * occurs when slope bet. two accel values falls below preset threshold + * for preset duration. + */ +static int8_t set_accel_no_motion_int(struct bmi160_int_settg *int_config, const struct bmi160_dev *dev) +{ + int8_t rslt; + + /* Null-pointer check */ + rslt = null_ptr_check(dev); + if ((rslt != BMI160_OK) || (int_config == NULL)) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + /* updating the interrupt structure to local structure */ + struct bmi160_acc_no_motion_int_cfg *no_mot_int_cfg = &(int_config->int_type_cfg.acc_no_motion_int); + rslt = enable_no_motion_int(no_mot_int_cfg, dev); + if (rslt == BMI160_OK) + { + /* Configure the INT PIN settings*/ + rslt = config_no_motion_int_settg(int_config, no_mot_int_cfg, dev); + } + } + + return rslt; +} + +/*! + * @brief This API sets the step detection interrupt.This interrupt + * occurs when the single step causes accel values to go above + * preset threshold. + */ +static int8_t set_accel_step_detect_int(struct bmi160_int_settg *int_config, const struct bmi160_dev *dev) +{ + int8_t rslt; + + /* Null-pointer check */ + rslt = null_ptr_check(dev); + if ((rslt != BMI160_OK) || (int_config == NULL)) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + /* updating the interrupt structure to local structure */ + struct bmi160_acc_step_detect_int_cfg *step_detect_int_cfg = &(int_config->int_type_cfg.acc_step_detect_int); + rslt = enable_step_detect_int(step_detect_int_cfg, dev); + if (rslt == BMI160_OK) + { + /* Configure Interrupt pins */ + rslt = set_intr_pin_config(int_config, dev); + if (rslt == BMI160_OK) + { + rslt = map_feature_interrupt(int_config, dev); + if (rslt == BMI160_OK) + { + rslt = config_step_detect(step_detect_int_cfg, dev); + } + } + } + } + + return rslt; +} + +/*! + * @brief This API sets the orientation interrupt of the sensor.This + * interrupt occurs when there is orientation change in the sensor + * with respect to gravitational field vector g. + */ +static int8_t set_accel_orientation_int(struct bmi160_int_settg *int_config, const struct bmi160_dev *dev) +{ + int8_t rslt; + + /* Null-pointer check */ + rslt = null_ptr_check(dev); + if ((rslt != BMI160_OK) || (int_config == NULL)) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + /* updating the interrupt structure to local structure */ + struct bmi160_acc_orient_int_cfg *orient_int_cfg = &(int_config->int_type_cfg.acc_orient_int); + rslt = enable_orient_int(orient_int_cfg, dev); + if (rslt == BMI160_OK) + { + /* Configure Interrupt pins */ + rslt = set_intr_pin_config(int_config, dev); + if (rslt == BMI160_OK) + { + /* map INT pin to orient interrupt */ + rslt = map_feature_interrupt(int_config, dev); + if (rslt == BMI160_OK) + { + /* configure the + * orientation setting*/ + rslt = config_orient_int_settg(orient_int_cfg, dev); + } + } + } + } + + return rslt; +} + +/*! + * @brief This API sets the flat interrupt of the sensor.This interrupt + * occurs in case of flat orientation + */ +static int8_t set_accel_flat_detect_int(struct bmi160_int_settg *int_config, const struct bmi160_dev *dev) +{ + int8_t rslt; + + /* Null-pointer check */ + rslt = null_ptr_check(dev); + if ((rslt != BMI160_OK) || (int_config == NULL)) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + /* updating the interrupt structure to local structure */ + struct bmi160_acc_flat_detect_int_cfg *flat_detect_int = &(int_config->int_type_cfg.acc_flat_int); + + /* enable the flat interrupt */ + rslt = enable_flat_int(flat_detect_int, dev); + if (rslt == BMI160_OK) + { + /* Configure Interrupt pins */ + rslt = set_intr_pin_config(int_config, dev); + if (rslt == BMI160_OK) + { + /* map INT pin to flat interrupt */ + rslt = map_feature_interrupt(int_config, dev); + if (rslt == BMI160_OK) + { + /* configure the flat setting*/ + rslt = config_flat_int_settg(flat_detect_int, dev); + } + } + } + } + + return rslt; +} + +/*! + * @brief This API sets the low-g interrupt of the sensor.This interrupt + * occurs during free-fall. + */ +static int8_t set_accel_low_g_int(struct bmi160_int_settg *int_config, const struct bmi160_dev *dev) +{ + int8_t rslt; + + /* Null-pointer check */ + rslt = null_ptr_check(dev); + if ((rslt != BMI160_OK) || (int_config == NULL)) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + /* updating the interrupt structure to local structure */ + struct bmi160_acc_low_g_int_cfg *low_g_int = &(int_config->int_type_cfg.acc_low_g_int); + + /* Enable the low-g interrupt*/ + rslt = enable_low_g_int(low_g_int, dev); + if (rslt == BMI160_OK) + { + /* Configure Interrupt pins */ + rslt = set_intr_pin_config(int_config, dev); + if (rslt == BMI160_OK) + { + /* Map INT pin to low-g interrupt */ + rslt = map_feature_interrupt(int_config, dev); + if (rslt == BMI160_OK) + { + /* configure the data source + * for low-g interrupt*/ + rslt = config_low_g_data_src(low_g_int, dev); + if (rslt == BMI160_OK) + { + rslt = config_low_g_int_settg(low_g_int, dev); + } + } + } + } + } + + return rslt; +} + +/*! + * @brief This API sets the high-g interrupt of the sensor.The interrupt + * occurs if the absolute value of acceleration data of any enabled axis + * exceeds the programmed threshold and the sign of the value does not + * change for a preset duration. + */ +static int8_t set_accel_high_g_int(struct bmi160_int_settg *int_config, const struct bmi160_dev *dev) +{ + int8_t rslt; + + /* Null-pointer check */ + rslt = null_ptr_check(dev); + if ((rslt != BMI160_OK) || (int_config == NULL)) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + /* updating the interrupt structure to local structure */ + struct bmi160_acc_high_g_int_cfg *high_g_int_cfg = &(int_config->int_type_cfg.acc_high_g_int); + + /* Enable the high-g interrupt */ + rslt = enable_high_g_int(high_g_int_cfg, dev); + if (rslt == BMI160_OK) + { + /* Configure Interrupt pins */ + rslt = set_intr_pin_config(int_config, dev); + if (rslt == BMI160_OK) + { + /* Map INT pin to high-g interrupt */ + rslt = map_feature_interrupt(int_config, dev); + if (rslt == BMI160_OK) + { + /* configure the data source + * for high-g interrupt*/ + rslt = config_high_g_data_src(high_g_int_cfg, dev); + if (rslt == BMI160_OK) + { + rslt = config_high_g_int_settg(high_g_int_cfg, dev); + } + } + } + } + } + + return rslt; +} + +/*! + * @brief This API configures the pins to fire the + * interrupt signal when it occurs. + */ +static int8_t set_intr_pin_config(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev) +{ + int8_t rslt; + + /* configure the behavioural settings of interrupt pin */ + rslt = config_int_out_ctrl(int_config, dev); + if (rslt == BMI160_OK) + { + rslt = config_int_latch(int_config, dev); + } + + return rslt; +} + +/*! + * @brief This internal API is used to validate the device structure pointer for + * null conditions. + */ +static int8_t null_ptr_check(const struct bmi160_dev *dev) +{ + int8_t rslt; + + if ((dev == NULL) || (dev->read == NULL) || (dev->write == NULL) || (dev->delay_ms == NULL)) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + /* Device structure is fine */ + rslt = BMI160_OK; + } + + return rslt; +} + +/*! + * @brief This API sets the default configuration parameters of accel & gyro. + * Also maintain the previous state of configurations. + */ +static void default_param_settg(struct bmi160_dev *dev) +{ + /* Initializing accel and gyro params with + * default values */ + dev->accel_cfg.bw = BMI160_ACCEL_BW_NORMAL_AVG4; + dev->accel_cfg.odr = BMI160_ACCEL_ODR_100HZ; + dev->accel_cfg.power = BMI160_ACCEL_SUSPEND_MODE; + dev->accel_cfg.range = BMI160_ACCEL_RANGE_2G; + dev->gyro_cfg.bw = BMI160_GYRO_BW_NORMAL_MODE; + dev->gyro_cfg.odr = BMI160_GYRO_ODR_100HZ; + dev->gyro_cfg.power = BMI160_GYRO_SUSPEND_MODE; + dev->gyro_cfg.range = BMI160_GYRO_RANGE_2000_DPS; + + /* To maintain the previous state of accel configuration */ + dev->prev_accel_cfg = dev->accel_cfg; + + /* To maintain the previous state of gyro configuration */ + dev->prev_gyro_cfg = dev->gyro_cfg; +} + +/*! + * @brief This API set the accel configuration. + */ +static int8_t set_accel_conf(struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data[2] = { 0 }; + + rslt = check_accel_config(data, dev); + if (rslt == BMI160_OK) + { + /* Write output data rate and bandwidth */ + rslt = bmi160_set_regs(BMI160_ACCEL_CONFIG_ADDR, &data[0], 1, dev); + if (rslt == BMI160_OK) + { + dev->prev_accel_cfg.odr = dev->accel_cfg.odr; + dev->prev_accel_cfg.bw = dev->accel_cfg.bw; + + /* write accel range */ + rslt = bmi160_set_regs(BMI160_ACCEL_RANGE_ADDR, &data[1], 1, dev); + if (rslt == BMI160_OK) + { + dev->prev_accel_cfg.range = dev->accel_cfg.range; + } + } + } + + return rslt; +} + +/*! + * @brief This API gets the accel configuration. + */ +static int8_t get_accel_conf(struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data[2] = { 0 }; + + /* Get accel configurations */ + rslt = bmi160_get_regs(BMI160_ACCEL_CONFIG_ADDR, data, 2, dev); + if (rslt == BMI160_OK) + { + dev->accel_cfg.odr = (data[0] & BMI160_ACCEL_ODR_MASK); + dev->accel_cfg.bw = (data[0] & BMI160_ACCEL_BW_MASK) >> BMI160_ACCEL_BW_POS; + dev->accel_cfg.range = (data[1] & BMI160_ACCEL_RANGE_MASK); + } + + return rslt; +} + +/*! + * @brief This API check the accel configuration. + */ +static int8_t check_accel_config(uint8_t *data, const struct bmi160_dev *dev) +{ + int8_t rslt; + + /* read accel Output data rate and bandwidth */ + rslt = bmi160_get_regs(BMI160_ACCEL_CONFIG_ADDR, data, 2, dev); + if (rslt == BMI160_OK) + { + rslt = process_accel_odr(&data[0], dev); + if (rslt == BMI160_OK) + { + rslt = process_accel_bw(&data[0], dev); + if (rslt == BMI160_OK) + { + rslt = process_accel_range(&data[1], dev); + } + } + } + + return rslt; +} + +/*! + * @brief This API process the accel odr. + */ +static int8_t process_accel_odr(uint8_t *data, const struct bmi160_dev *dev) +{ + int8_t rslt = 0; + uint8_t temp = 0; + uint8_t odr = 0; + + if (dev->accel_cfg.odr <= BMI160_ACCEL_ODR_1600HZ) + { + if (dev->accel_cfg.odr != dev->prev_accel_cfg.odr) + { + odr = (uint8_t)dev->accel_cfg.odr; + temp = *data & ~BMI160_ACCEL_ODR_MASK; + + /* Adding output data rate */ + *data = temp | (odr & BMI160_ACCEL_ODR_MASK); + } + } + else + { + rslt = BMI160_E_OUT_OF_RANGE; + } + + return rslt; +} + +/*! + * @brief This API process the accel bandwidth. + */ +static int8_t process_accel_bw(uint8_t *data, const struct bmi160_dev *dev) +{ + int8_t rslt = 0; + uint8_t temp = 0; + uint8_t bw = 0; + + if (dev->accel_cfg.bw <= BMI160_ACCEL_BW_RES_AVG128) + { + if (dev->accel_cfg.bw != dev->prev_accel_cfg.bw) + { + bw = (uint8_t)dev->accel_cfg.bw; + temp = *data & ~BMI160_ACCEL_BW_MASK; + + /* Adding bandwidth */ + *data = temp | ((bw << 4) & BMI160_ACCEL_BW_MASK); + } + } + else + { + rslt = BMI160_E_OUT_OF_RANGE; + } + + return rslt; +} + +/*! + * @brief This API process the accel range. + */ +static int8_t process_accel_range(uint8_t *data, const struct bmi160_dev *dev) +{ + int8_t rslt = 0; + uint8_t temp = 0; + uint8_t range = 0; + + if (dev->accel_cfg.range <= BMI160_ACCEL_RANGE_16G) + { + if (dev->accel_cfg.range != dev->prev_accel_cfg.range) + { + range = (uint8_t)dev->accel_cfg.range; + temp = *data & ~BMI160_ACCEL_RANGE_MASK; + + /* Adding range */ + *data = temp | (range & BMI160_ACCEL_RANGE_MASK); + } + } + else + { + rslt = BMI160_E_OUT_OF_RANGE; + } + + return rslt; +} + +/*! + * @brief This API checks the invalid settings for ODR & Bw for + * Accel and Gyro. + */ +static int8_t check_invalid_settg(const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data = 0; + + /* read the error reg */ + rslt = bmi160_get_regs(BMI160_ERROR_REG_ADDR, &data, 1, dev); + data = data >> 1; + data = data & BMI160_ERR_REG_MASK; + if (data == 1) + { + rslt = BMI160_E_ACCEL_ODR_BW_INVALID; + } + else if (data == 2) + { + rslt = BMI160_E_GYRO_ODR_BW_INVALID; + } + else if (data == 3) + { + rslt = BMI160_E_LWP_PRE_FLTR_INT_INVALID; + } + else if (data == 7) + { + rslt = BMI160_E_LWP_PRE_FLTR_INVALID; + } + + return rslt; +} +static int8_t set_gyro_conf(struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data[2] = { 0 }; + + rslt = check_gyro_config(data, dev); + if (rslt == BMI160_OK) + { + /* Write output data rate and bandwidth */ + rslt = bmi160_set_regs(BMI160_GYRO_CONFIG_ADDR, &data[0], 1, dev); + if (rslt == BMI160_OK) + { + dev->prev_gyro_cfg.odr = dev->gyro_cfg.odr; + dev->prev_gyro_cfg.bw = dev->gyro_cfg.bw; + + /* Write gyro range */ + rslt = bmi160_set_regs(BMI160_GYRO_RANGE_ADDR, &data[1], 1, dev); + if (rslt == BMI160_OK) + { + dev->prev_gyro_cfg.range = dev->gyro_cfg.range; + } + } + } + + return rslt; +} + +/*! + * @brief This API gets the gyro configuration. + */ +static int8_t get_gyro_conf(struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data[2] = { 0 }; + + /* Get accel configurations */ + rslt = bmi160_get_regs(BMI160_GYRO_CONFIG_ADDR, data, 2, dev); + if (rslt == BMI160_OK) + { + dev->gyro_cfg.odr = (data[0] & BMI160_GYRO_ODR_MASK); + dev->gyro_cfg.bw = (data[0] & BMI160_GYRO_BW_MASK) >> BMI160_GYRO_BW_POS; + dev->gyro_cfg.range = (data[1] & BMI160_GYRO_RANGE_MASK); + } + + return rslt; +} + +/*! + * @brief This API check the gyro configuration. + */ +static int8_t check_gyro_config(uint8_t *data, const struct bmi160_dev *dev) +{ + int8_t rslt; + + /* read gyro Output data rate and bandwidth */ + rslt = bmi160_get_regs(BMI160_GYRO_CONFIG_ADDR, data, 2, dev); + if (rslt == BMI160_OK) + { + rslt = process_gyro_odr(&data[0], dev); + if (rslt == BMI160_OK) + { + rslt = process_gyro_bw(&data[0], dev); + if (rslt == BMI160_OK) + { + rslt = process_gyro_range(&data[1], dev); + } + } + } + + return rslt; +} + +/*! + * @brief This API process the gyro odr. + */ +static int8_t process_gyro_odr(uint8_t *data, const struct bmi160_dev *dev) +{ + int8_t rslt = 0; + uint8_t temp = 0; + uint8_t odr = 0; + + if (dev->gyro_cfg.odr <= BMI160_GYRO_ODR_3200HZ) + { + if (dev->gyro_cfg.odr != dev->prev_gyro_cfg.odr) + { + odr = (uint8_t)dev->gyro_cfg.odr; + temp = (*data & ~BMI160_GYRO_ODR_MASK); + + /* Adding output data rate */ + *data = temp | (odr & BMI160_GYRO_ODR_MASK); + } + } + else + { + rslt = BMI160_E_OUT_OF_RANGE; + } + + return rslt; +} + +/*! + * @brief This API process the gyro bandwidth. + */ +static int8_t process_gyro_bw(uint8_t *data, const struct bmi160_dev *dev) +{ + int8_t rslt = 0; + uint8_t temp = 0; + uint8_t bw = 0; + + if (dev->gyro_cfg.bw <= BMI160_GYRO_BW_NORMAL_MODE) + { + bw = (uint8_t)dev->gyro_cfg.bw; + temp = *data & ~BMI160_GYRO_BW_MASK; + + /* Adding bandwidth */ + *data = temp | ((bw << 4) & BMI160_GYRO_BW_MASK); + } + else + { + rslt = BMI160_E_OUT_OF_RANGE; + } + + return rslt; +} + +/*! + * @brief This API process the gyro range. + */ +static int8_t process_gyro_range(uint8_t *data, const struct bmi160_dev *dev) +{ + int8_t rslt = 0; + uint8_t temp = 0; + uint8_t range = 0; + + if (dev->gyro_cfg.range <= BMI160_GYRO_RANGE_125_DPS) + { + if (dev->gyro_cfg.range != dev->prev_gyro_cfg.range) + { + range = (uint8_t)dev->gyro_cfg.range; + temp = *data & ~BMI160_GYRO_RANGE_MASK; + + /* Adding range */ + *data = temp | (range & BMI160_GYRO_RANGE_MASK); + } + } + else + { + rslt = BMI160_E_OUT_OF_RANGE; + } + + return rslt; +} + +/*! + * @brief This API sets the accel power. + */ +static int8_t set_accel_pwr(struct bmi160_dev *dev) +{ + int8_t rslt = 0; + uint8_t data = 0; + + if ((dev->accel_cfg.power >= BMI160_ACCEL_SUSPEND_MODE) && (dev->accel_cfg.power <= BMI160_ACCEL_LOWPOWER_MODE)) + { + if (dev->accel_cfg.power != dev->prev_accel_cfg.power) + { + rslt = process_under_sampling(&data, dev); + if (rslt == BMI160_OK) + { + /* Write accel power */ + rslt = bmi160_set_regs(BMI160_COMMAND_REG_ADDR, &dev->accel_cfg.power, 1, dev); + + /* Add delay of 3.8 ms - refer data sheet table 24*/ + if (dev->prev_accel_cfg.power == BMI160_ACCEL_SUSPEND_MODE) + { + dev->delay_ms(BMI160_ACCEL_DELAY_MS); + } + + dev->prev_accel_cfg.power = dev->accel_cfg.power; + } + } + } + else + { + rslt = BMI160_E_INVALID_CONFIG; + } + + return rslt; +} + +/*! + * @brief This API process the undersampling setting of Accel. + */ +static int8_t process_under_sampling(uint8_t *data, const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t temp = 0; + uint8_t pre_filter[2] = { 0 }; + + rslt = bmi160_get_regs(BMI160_ACCEL_CONFIG_ADDR, data, 1, dev); + if (rslt == BMI160_OK) + { + if (dev->accel_cfg.power == BMI160_ACCEL_LOWPOWER_MODE) + { + temp = *data & ~BMI160_ACCEL_UNDERSAMPLING_MASK; + + /* Set under-sampling parameter */ + *data = temp | ((1 << 7) & BMI160_ACCEL_UNDERSAMPLING_MASK); + + /* Write data */ + rslt = bmi160_set_regs(BMI160_ACCEL_CONFIG_ADDR, data, 1, dev); + + /* Disable the pre-filter data in low power mode */ + if (rslt == BMI160_OK) + { + /* Disable the Pre-filter data*/ + rslt = bmi160_set_regs(BMI160_INT_DATA_0_ADDR, pre_filter, 2, dev); + } + } + else if (*data & BMI160_ACCEL_UNDERSAMPLING_MASK) + { + temp = *data & ~BMI160_ACCEL_UNDERSAMPLING_MASK; + + /* Disable under-sampling parameter if already enabled */ + *data = temp; + + /* Write data */ + rslt = bmi160_set_regs(BMI160_ACCEL_CONFIG_ADDR, data, 1, dev); + } + } + + return rslt; +} + +/*! + * @brief This API sets the gyro power mode. + */ +static int8_t set_gyro_pwr(struct bmi160_dev *dev) +{ + int8_t rslt = 0; + + if ((dev->gyro_cfg.power == BMI160_GYRO_SUSPEND_MODE) || (dev->gyro_cfg.power == BMI160_GYRO_NORMAL_MODE) || + (dev->gyro_cfg.power == BMI160_GYRO_FASTSTARTUP_MODE)) + { + if (dev->gyro_cfg.power != dev->prev_gyro_cfg.power) + { + /* Write gyro power */ + rslt = bmi160_set_regs(BMI160_COMMAND_REG_ADDR, &dev->gyro_cfg.power, 1, dev); + if (dev->prev_gyro_cfg.power == BMI160_GYRO_SUSPEND_MODE) + { + /* Delay of 80 ms - datasheet Table 24 */ + dev->delay_ms(BMI160_GYRO_DELAY_MS); + } + else if ((dev->prev_gyro_cfg.power == BMI160_GYRO_FASTSTARTUP_MODE) && + (dev->gyro_cfg.power == BMI160_GYRO_NORMAL_MODE)) + { + /* This delay is required for transition from + * fast-startup mode to normal mode - datasheet Table 3 */ + dev->delay_ms(10); + } + else + { + /* do nothing */ + } + + dev->prev_gyro_cfg.power = dev->gyro_cfg.power; + } + } + else + { + rslt = BMI160_E_INVALID_CONFIG; + } + + return rslt; +} + +/*! + * @brief This API reads accel data along with sensor time if time is requested + * by user. Kindly refer the user guide(README.md) for more info. + */ +static int8_t get_accel_data(uint8_t len, struct bmi160_sensor_data *accel, const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t idx = 0; + uint8_t data_array[9] = { 0 }; + uint8_t time_0 = 0; + uint16_t time_1 = 0; + uint32_t time_2 = 0; + uint8_t lsb; + uint8_t msb; + int16_t msblsb; + + /* read accel sensor data along with time if requested */ + rslt = bmi160_get_regs(BMI160_ACCEL_DATA_ADDR, data_array, 6 + len, dev); + if (rslt == BMI160_OK) + { + /* Accel Data */ + lsb = data_array[idx++]; + msb = data_array[idx++]; + msblsb = (int16_t)((msb << 8) | lsb); + accel->x = msblsb; /* Data in X axis */ + lsb = data_array[idx++]; + msb = data_array[idx++]; + msblsb = (int16_t)((msb << 8) | lsb); + accel->y = msblsb; /* Data in Y axis */ + lsb = data_array[idx++]; + msb = data_array[idx++]; + msblsb = (int16_t)((msb << 8) | lsb); + accel->z = msblsb; /* Data in Z axis */ + if (len == 3) + { + time_0 = data_array[idx++]; + time_1 = (uint16_t)(data_array[idx++] << 8); + time_2 = (uint32_t)(data_array[idx++] << 16); + accel->sensortime = (uint32_t)(time_2 | time_1 | time_0); + } + else + { + accel->sensortime = 0; + } + } + else + { + rslt = BMI160_E_COM_FAIL; + } + + return rslt; +} + +/*! + * @brief This API reads accel data along with sensor time if time is requested + * by user. Kindly refer the user guide(README.md) for more info. + */ +static int8_t get_gyro_data(uint8_t len, struct bmi160_sensor_data *gyro, const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t idx = 0; + uint8_t data_array[15] = { 0 }; + uint8_t time_0 = 0; + uint16_t time_1 = 0; + uint32_t time_2 = 0; + uint8_t lsb; + uint8_t msb; + int16_t msblsb; + + if (len == 0) + { + /* read gyro data only */ + rslt = bmi160_get_regs(BMI160_GYRO_DATA_ADDR, data_array, 6, dev); + if (rslt == BMI160_OK) + { + /* Gyro Data */ + lsb = data_array[idx++]; + msb = data_array[idx++]; + msblsb = (int16_t)((msb << 8) | lsb); + gyro->x = msblsb; /* Data in X axis */ + lsb = data_array[idx++]; + msb = data_array[idx++]; + msblsb = (int16_t)((msb << 8) | lsb); + gyro->y = msblsb; /* Data in Y axis */ + lsb = data_array[idx++]; + msb = data_array[idx++]; + msblsb = (int16_t)((msb << 8) | lsb); + gyro->z = msblsb; /* Data in Z axis */ + gyro->sensortime = 0; + } + else + { + rslt = BMI160_E_COM_FAIL; + } + } + else + { + /* read gyro sensor data along with time */ + rslt = bmi160_get_regs(BMI160_GYRO_DATA_ADDR, data_array, 12 + len, dev); + if (rslt == BMI160_OK) + { + /* Gyro Data */ + lsb = data_array[idx++]; + msb = data_array[idx++]; + msblsb = (int16_t)((msb << 8) | lsb); + gyro->x = msblsb; /* gyro X axis data */ + lsb = data_array[idx++]; + msb = data_array[idx++]; + msblsb = (int16_t)((msb << 8) | lsb); + gyro->y = msblsb; /* gyro Y axis data */ + lsb = data_array[idx++]; + msb = data_array[idx++]; + msblsb = (int16_t)((msb << 8) | lsb); + gyro->z = msblsb; /* gyro Z axis data */ + idx = idx + 6; + time_0 = data_array[idx++]; + time_1 = (uint16_t)(data_array[idx++] << 8); + time_2 = (uint32_t)(data_array[idx++] << 16); + gyro->sensortime = (uint32_t)(time_2 | time_1 | time_0); + } + else + { + rslt = BMI160_E_COM_FAIL; + } + } + + return rslt; +} + +/*! + * @brief This API reads accel and gyro data along with sensor time + * if time is requested by user. + * Kindly refer the user guide(README.md) for more info. + */ +static int8_t get_accel_gyro_data(uint8_t len, + struct bmi160_sensor_data *accel, + struct bmi160_sensor_data *gyro, + const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t idx = 0; + uint8_t data_array[15] = { 0 }; + uint8_t time_0 = 0; + uint16_t time_1 = 0; + uint32_t time_2 = 0; + uint8_t lsb; + uint8_t msb; + int16_t msblsb; + + /* read both accel and gyro sensor data + * along with time if requested */ + rslt = bmi160_get_regs(BMI160_GYRO_DATA_ADDR, data_array, 12 + len, dev); + if (rslt == BMI160_OK) + { + /* Gyro Data */ + lsb = data_array[idx++]; + msb = data_array[idx++]; + msblsb = (int16_t)((msb << 8) | lsb); + gyro->x = msblsb; /* gyro X axis data */ + lsb = data_array[idx++]; + msb = data_array[idx++]; + msblsb = (int16_t)((msb << 8) | lsb); + gyro->y = msblsb; /* gyro Y axis data */ + lsb = data_array[idx++]; + msb = data_array[idx++]; + msblsb = (int16_t)((msb << 8) | lsb); + gyro->z = msblsb; /* gyro Z axis data */ + /* Accel Data */ + lsb = data_array[idx++]; + msb = data_array[idx++]; + msblsb = (int16_t)((msb << 8) | lsb); + accel->x = (int16_t)msblsb; /* accel X axis data */ + lsb = data_array[idx++]; + msb = data_array[idx++]; + msblsb = (int16_t)((msb << 8) | lsb); + accel->y = (int16_t)msblsb; /* accel Y axis data */ + lsb = data_array[idx++]; + msb = data_array[idx++]; + msblsb = (int16_t)((msb << 8) | lsb); + accel->z = (int16_t)msblsb; /* accel Z axis data */ + if (len == 3) + { + time_0 = data_array[idx++]; + time_1 = (uint16_t)(data_array[idx++] << 8); + time_2 = (uint32_t)(data_array[idx++] << 16); + accel->sensortime = (uint32_t)(time_2 | time_1 | time_0); + gyro->sensortime = (uint32_t)(time_2 | time_1 | time_0); + } + else + { + accel->sensortime = 0; + gyro->sensortime = 0; + } + } + else + { + rslt = BMI160_E_COM_FAIL; + } + + return rslt; +} + +/*! + * @brief This API enables the any-motion interrupt for accel. + */ +static int8_t enable_accel_any_motion_int(const struct bmi160_acc_any_mot_int_cfg *any_motion_int_cfg, + struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data = 0; + uint8_t temp = 0; + + /* Enable any motion x, any motion y, any motion z + * in Int Enable 0 register */ + rslt = bmi160_get_regs(BMI160_INT_ENABLE_0_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + if (any_motion_int_cfg->anymotion_en == BMI160_ENABLE) + { + temp = data & ~BMI160_ANY_MOTION_X_INT_EN_MASK; + + /* Adding Any_motion x axis */ + data = temp | (any_motion_int_cfg->anymotion_x & BMI160_ANY_MOTION_X_INT_EN_MASK); + temp = data & ~BMI160_ANY_MOTION_Y_INT_EN_MASK; + + /* Adding Any_motion y axis */ + data = temp | ((any_motion_int_cfg->anymotion_y << 1) & BMI160_ANY_MOTION_Y_INT_EN_MASK); + temp = data & ~BMI160_ANY_MOTION_Z_INT_EN_MASK; + + /* Adding Any_motion z axis */ + data = temp | ((any_motion_int_cfg->anymotion_z << 2) & BMI160_ANY_MOTION_Z_INT_EN_MASK); + + /* any-motion feature selected*/ + dev->any_sig_sel = BMI160_ANY_MOTION_ENABLED; + } + else + { + data = data & ~BMI160_ANY_MOTION_ALL_INT_EN_MASK; + + /* neither any-motion feature nor sig-motion selected */ + dev->any_sig_sel = BMI160_BOTH_ANY_SIG_MOTION_DISABLED; + } + + /* write data to Int Enable 0 register */ + rslt = bmi160_set_regs(BMI160_INT_ENABLE_0_ADDR, &data, 1, dev); + } + + return rslt; +} + +/*! + * @brief This API disable the sig-motion interrupt. + */ +static int8_t disable_sig_motion_int(const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data = 0; + uint8_t temp = 0; + + /* Disabling Significant motion interrupt if enabled */ + rslt = bmi160_get_regs(BMI160_INT_MOTION_3_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + temp = (data & BMI160_SIG_MOTION_SEL_MASK); + if (temp) + { + temp = data & ~BMI160_SIG_MOTION_SEL_MASK; + data = temp; + + /* Write data to register */ + rslt = bmi160_set_regs(BMI160_INT_MOTION_3_ADDR, &data, 1, dev); + } + } + + return rslt; +} + +/*! + * @brief This API is used to map/unmap the Any/Sig motion, Step det/Low-g, + * Double tap, Single tap, Orientation, Flat, High-G, Nomotion interrupt pins. + */ +static int8_t map_feature_interrupt(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data[3] = { 0, 0, 0 }; + uint8_t temp[3] = { 0, 0, 0 }; + + rslt = bmi160_get_regs(BMI160_INT_MAP_0_ADDR, data, 3, dev); + if (rslt == BMI160_OK) + { + temp[0] = data[0] & ~int_mask_lookup_table[int_config->int_type]; + temp[2] = data[2] & ~int_mask_lookup_table[int_config->int_type]; + switch (int_config->int_channel) + { + case BMI160_INT_CHANNEL_NONE: + data[0] = temp[0]; + data[2] = temp[2]; + break; + case BMI160_INT_CHANNEL_1: + data[0] = temp[0] | int_mask_lookup_table[int_config->int_type]; + data[2] = temp[2]; + break; + case BMI160_INT_CHANNEL_2: + data[2] = temp[2] | int_mask_lookup_table[int_config->int_type]; + data[0] = temp[0]; + break; + case BMI160_INT_CHANNEL_BOTH: + data[0] = temp[0] | int_mask_lookup_table[int_config->int_type]; + data[2] = temp[2] | int_mask_lookup_table[int_config->int_type]; + break; + default: + rslt = BMI160_E_OUT_OF_RANGE; + } + if (rslt == BMI160_OK) + { + rslt = bmi160_set_regs(BMI160_INT_MAP_0_ADDR, data, 3, dev); + } + } + + return rslt; +} + +/*! + * @brief This API is used to map/unmap the Dataready(Accel & Gyro), FIFO full + * and FIFO watermark interrupt. + */ +static int8_t map_hardware_interrupt(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data = 0; + uint8_t temp = 0; + + rslt = bmi160_get_regs(BMI160_INT_MAP_1_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + temp = data & ~int_mask_lookup_table[int_config->int_type]; + temp = temp & ~((uint8_t)(int_mask_lookup_table[int_config->int_type] << 4)); + switch (int_config->int_channel) + { + case BMI160_INT_CHANNEL_NONE: + data = temp; + break; + case BMI160_INT_CHANNEL_1: + data = temp | (uint8_t)((int_mask_lookup_table[int_config->int_type]) << 4); + break; + case BMI160_INT_CHANNEL_2: + data = temp | int_mask_lookup_table[int_config->int_type]; + break; + case BMI160_INT_CHANNEL_BOTH: + data = temp | int_mask_lookup_table[int_config->int_type]; + data = data | (uint8_t)((int_mask_lookup_table[int_config->int_type]) << 4); + break; + default: + rslt = BMI160_E_OUT_OF_RANGE; + } + if (rslt == BMI160_OK) + { + rslt = bmi160_set_regs(BMI160_INT_MAP_1_ADDR, &data, 1, dev); + } + } + + return rslt; +} + +/*! + * @brief This API configure the source of data(filter & pre-filter) + * for any-motion interrupt. + */ +static int8_t config_any_motion_src(const struct bmi160_acc_any_mot_int_cfg *any_motion_int_cfg, + const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data = 0; + uint8_t temp = 0; + + /* Configure Int data 1 register to add source of interrupt */ + rslt = bmi160_get_regs(BMI160_INT_DATA_1_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + temp = data & ~BMI160_MOTION_SRC_INT_MASK; + data = temp | ((any_motion_int_cfg->anymotion_data_src << 7) & BMI160_MOTION_SRC_INT_MASK); + + /* Write data to DATA 1 address */ + rslt = bmi160_set_regs(BMI160_INT_DATA_1_ADDR, &data, 1, dev); + } + + return rslt; +} + +/*! + * @brief This API configure the duration and threshold of + * any-motion interrupt. + */ +static int8_t config_any_dur_threshold(const struct bmi160_acc_any_mot_int_cfg *any_motion_int_cfg, + const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data = 0; + uint8_t temp = 0; + uint8_t data_array[2] = { 0 }; + uint8_t dur; + + /* Configure Int Motion 0 register */ + rslt = bmi160_get_regs(BMI160_INT_MOTION_0_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + /* slope duration */ + dur = (uint8_t)any_motion_int_cfg->anymotion_dur; + temp = data & ~BMI160_SLOPE_INT_DUR_MASK; + data = temp | (dur & BMI160_MOTION_SRC_INT_MASK); + data_array[0] = data; + + /* add slope threshold */ + data_array[1] = any_motion_int_cfg->anymotion_thr; + + /* INT MOTION 0 and INT MOTION 1 address lie consecutively, + * hence writing data to respective registers at one go */ + + /* Writing to Int_motion 0 and + * Int_motion 1 Address simultaneously */ + rslt = bmi160_set_regs(BMI160_INT_MOTION_0_ADDR, data_array, 2, dev); + } + + return rslt; +} + +/*! + * @brief This API configure necessary setting of any-motion interrupt. + */ +static int8_t config_any_motion_int_settg(const struct bmi160_int_settg *int_config, + const struct bmi160_acc_any_mot_int_cfg *any_motion_int_cfg, + const struct bmi160_dev *dev) +{ + int8_t rslt; + + /* Configure Interrupt pins */ + rslt = set_intr_pin_config(int_config, dev); + if (rslt == BMI160_OK) + { + rslt = disable_sig_motion_int(dev); + if (rslt == BMI160_OK) + { + rslt = map_feature_interrupt(int_config, dev); + if (rslt == BMI160_OK) + { + rslt = config_any_motion_src(any_motion_int_cfg, dev); + if (rslt == BMI160_OK) + { + rslt = config_any_dur_threshold(any_motion_int_cfg, dev); + } + } + } + } + + return rslt; +} + +/*! + * @brief This API enable the data ready interrupt. + */ +static int8_t enable_data_ready_int(const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data = 0; + uint8_t temp = 0; + + /* Enable data ready interrupt in Int Enable 1 register */ + rslt = bmi160_get_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + temp = data & ~BMI160_DATA_RDY_INT_EN_MASK; + data = temp | ((1 << 4) & BMI160_DATA_RDY_INT_EN_MASK); + + /* Writing data to INT ENABLE 1 Address */ + rslt = bmi160_set_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev); + } + + return rslt; +} + +/*! + * @brief This API enables the no motion/slow motion interrupt. + */ +static int8_t enable_no_motion_int(const struct bmi160_acc_no_motion_int_cfg *no_mot_int_cfg, + const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data = 0; + uint8_t temp = 0; + + /* Enable no motion x, no motion y, no motion z + * in Int Enable 2 register */ + rslt = bmi160_get_regs(BMI160_INT_ENABLE_2_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + if (no_mot_int_cfg->no_motion_x == 1) + { + temp = data & ~BMI160_NO_MOTION_X_INT_EN_MASK; + + /* Adding No_motion x axis */ + data = temp | (1 & BMI160_NO_MOTION_X_INT_EN_MASK); + } + + if (no_mot_int_cfg->no_motion_y == 1) + { + temp = data & ~BMI160_NO_MOTION_Y_INT_EN_MASK; + + /* Adding No_motion x axis */ + data = temp | ((1 << 1) & BMI160_NO_MOTION_Y_INT_EN_MASK); + } + + if (no_mot_int_cfg->no_motion_z == 1) + { + temp = data & ~BMI160_NO_MOTION_Z_INT_EN_MASK; + + /* Adding No_motion x axis */ + data = temp | ((1 << 2) & BMI160_NO_MOTION_Z_INT_EN_MASK); + } + + /* write data to Int Enable 2 register */ + rslt = bmi160_set_regs(BMI160_INT_ENABLE_2_ADDR, &data, 1, dev); + } + + return rslt; +} + +/*! + * @brief This API configure the interrupt PIN setting for + * no motion/slow motion interrupt. + */ +static int8_t config_no_motion_int_settg(const struct bmi160_int_settg *int_config, + const struct bmi160_acc_no_motion_int_cfg *no_mot_int_cfg, + const struct bmi160_dev *dev) +{ + int8_t rslt; + + /* Configure Interrupt pins */ + rslt = set_intr_pin_config(int_config, dev); + if (rslt == BMI160_OK) + { + rslt = map_feature_interrupt(int_config, dev); + if (rslt == BMI160_OK) + { + rslt = config_no_motion_data_src(no_mot_int_cfg, dev); + if (rslt == BMI160_OK) + { + rslt = config_no_motion_dur_thr(no_mot_int_cfg, dev); + } + } + } + + return rslt; +} + +/*! + * @brief This API configure the source of interrupt for no motion. + */ +static int8_t config_no_motion_data_src(const struct bmi160_acc_no_motion_int_cfg *no_mot_int_cfg, + const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data = 0; + uint8_t temp = 0; + + /* Configure Int data 1 register to add source of interrupt */ + rslt = bmi160_get_regs(BMI160_INT_DATA_1_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + temp = data & ~BMI160_MOTION_SRC_INT_MASK; + data = temp | ((no_mot_int_cfg->no_motion_src << 7) & BMI160_MOTION_SRC_INT_MASK); + + /* Write data to DATA 1 address */ + rslt = bmi160_set_regs(BMI160_INT_DATA_1_ADDR, &data, 1, dev); + } + + return rslt; +} + +/*! + * @brief This API configure the duration and threshold of + * no motion/slow motion interrupt along with selection of no/slow motion. + */ +static int8_t config_no_motion_dur_thr(const struct bmi160_acc_no_motion_int_cfg *no_mot_int_cfg, + const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data = 0; + uint8_t temp = 0; + uint8_t temp_1 = 0; + uint8_t reg_addr; + uint8_t data_array[2] = { 0 }; + + /* Configuring INT_MOTION register */ + reg_addr = BMI160_INT_MOTION_0_ADDR; + rslt = bmi160_get_regs(reg_addr, &data, 1, dev); + if (rslt == BMI160_OK) + { + temp = data & ~BMI160_NO_MOTION_INT_DUR_MASK; + + /* Adding no_motion duration */ + data = temp | ((no_mot_int_cfg->no_motion_dur << 2) & BMI160_NO_MOTION_INT_DUR_MASK); + + /* Write data to NO_MOTION 0 address */ + rslt = bmi160_set_regs(reg_addr, &data, 1, dev); + if (rslt == BMI160_OK) + { + reg_addr = BMI160_INT_MOTION_3_ADDR; + rslt = bmi160_get_regs(reg_addr, &data, 1, dev); + if (rslt == BMI160_OK) + { + temp = data & ~BMI160_NO_MOTION_SEL_BIT_MASK; + + /* Adding no_motion_sel bit */ + temp_1 = (no_mot_int_cfg->no_motion_sel & BMI160_NO_MOTION_SEL_BIT_MASK); + data = (temp | temp_1); + data_array[1] = data; + + /* Adding no motion threshold */ + data_array[0] = no_mot_int_cfg->no_motion_thres; + reg_addr = BMI160_INT_MOTION_2_ADDR; + + /* writing data to INT_MOTION 2 and INT_MOTION 3 + * address simultaneously */ + rslt = bmi160_set_regs(reg_addr, data_array, 2, dev); + } + } + } + + return rslt; +} + +/*! + * @brief This API enables the sig-motion motion interrupt. + */ +static int8_t enable_sig_motion_int(const struct bmi160_acc_sig_mot_int_cfg *sig_mot_int_cfg, struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data = 0; + uint8_t temp = 0; + + /* For significant motion,enable any motion x,any motion y, + * any motion z in Int Enable 0 register */ + rslt = bmi160_get_regs(BMI160_INT_ENABLE_0_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + if (sig_mot_int_cfg->sig_en == BMI160_ENABLE) + { + temp = data & ~BMI160_SIG_MOTION_INT_EN_MASK; + data = temp | (7 & BMI160_SIG_MOTION_INT_EN_MASK); + + /* sig-motion feature selected*/ + dev->any_sig_sel = BMI160_SIG_MOTION_ENABLED; + } + else + { + data = data & ~BMI160_SIG_MOTION_INT_EN_MASK; + + /* neither any-motion feature nor sig-motion selected */ + dev->any_sig_sel = BMI160_BOTH_ANY_SIG_MOTION_DISABLED; + } + + /* write data to Int Enable 0 register */ + rslt = bmi160_set_regs(BMI160_INT_ENABLE_0_ADDR, &data, 1, dev); + } + + return rslt; +} + +/*! + * @brief This API configure the interrupt PIN setting for + * significant motion interrupt. + */ +static int8_t config_sig_motion_int_settg(const struct bmi160_int_settg *int_config, + const struct bmi160_acc_sig_mot_int_cfg *sig_mot_int_cfg, + const struct bmi160_dev *dev) +{ + int8_t rslt; + + /* Configure Interrupt pins */ + rslt = set_intr_pin_config(int_config, dev); + if (rslt == BMI160_OK) + { + rslt = map_feature_interrupt(int_config, dev); + if (rslt == BMI160_OK) + { + rslt = config_sig_motion_data_src(sig_mot_int_cfg, dev); + if (rslt == BMI160_OK) + { + rslt = config_sig_dur_threshold(sig_mot_int_cfg, dev); + } + } + } + + return rslt; +} + +/*! + * @brief This API configure the source of data(filter & pre-filter) + * for sig motion interrupt. + */ +static int8_t config_sig_motion_data_src(const struct bmi160_acc_sig_mot_int_cfg *sig_mot_int_cfg, + const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data = 0; + uint8_t temp = 0; + + /* Configure Int data 1 register to add source of interrupt */ + rslt = bmi160_get_regs(BMI160_INT_DATA_1_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + temp = data & ~BMI160_MOTION_SRC_INT_MASK; + data = temp | ((sig_mot_int_cfg->sig_data_src << 7) & BMI160_MOTION_SRC_INT_MASK); + + /* Write data to DATA 1 address */ + rslt = bmi160_set_regs(BMI160_INT_DATA_1_ADDR, &data, 1, dev); + } + + return rslt; +} + +/*! + * @brief This API configure the threshold, skip and proof time of + * sig motion interrupt. + */ +static int8_t config_sig_dur_threshold(const struct bmi160_acc_sig_mot_int_cfg *sig_mot_int_cfg, + const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data; + uint8_t temp = 0; + + /* Configuring INT_MOTION registers */ + + /* Write significant motion threshold. + * This threshold is same as any motion threshold */ + data = sig_mot_int_cfg->sig_mot_thres; + + /* Write data to INT_MOTION 1 address */ + rslt = bmi160_set_regs(BMI160_INT_MOTION_1_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + rslt = bmi160_get_regs(BMI160_INT_MOTION_3_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + temp = data & ~BMI160_SIG_MOTION_SKIP_MASK; + + /* adding skip time of sig_motion interrupt*/ + data = temp | ((sig_mot_int_cfg->sig_mot_skip << 2) & BMI160_SIG_MOTION_SKIP_MASK); + temp = data & ~BMI160_SIG_MOTION_PROOF_MASK; + + /* adding proof time of sig_motion interrupt */ + data = temp | ((sig_mot_int_cfg->sig_mot_proof << 4) & BMI160_SIG_MOTION_PROOF_MASK); + + /* configure the int_sig_mot_sel bit to select + * significant motion interrupt */ + temp = data & ~BMI160_SIG_MOTION_SEL_MASK; + data = temp | ((sig_mot_int_cfg->sig_en << 1) & BMI160_SIG_MOTION_SEL_MASK); + rslt = bmi160_set_regs(BMI160_INT_MOTION_3_ADDR, &data, 1, dev); + } + } + + return rslt; +} + +/*! + * @brief This API enables the step detector interrupt. + */ +static int8_t enable_step_detect_int(const struct bmi160_acc_step_detect_int_cfg *step_detect_int_cfg, + const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data = 0; + uint8_t temp = 0; + + /* Enable data ready interrupt in Int Enable 2 register */ + rslt = bmi160_get_regs(BMI160_INT_ENABLE_2_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + temp = data & ~BMI160_STEP_DETECT_INT_EN_MASK; + data = temp | ((step_detect_int_cfg->step_detector_en << 3) & BMI160_STEP_DETECT_INT_EN_MASK); + + /* Writing data to INT ENABLE 2 Address */ + rslt = bmi160_set_regs(BMI160_INT_ENABLE_2_ADDR, &data, 1, dev); + } + + return rslt; +} + +/*! + * @brief This API configure the step detector parameter. + */ +static int8_t config_step_detect(const struct bmi160_acc_step_detect_int_cfg *step_detect_int_cfg, + const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t temp = 0; + uint8_t data_array[2] = { 0 }; + + if (step_detect_int_cfg->step_detector_mode == BMI160_STEP_DETECT_NORMAL) + { + /* Normal mode setting */ + data_array[0] = 0x15; + data_array[1] = 0x03; + } + else if (step_detect_int_cfg->step_detector_mode == BMI160_STEP_DETECT_SENSITIVE) + { + /* Sensitive mode setting */ + data_array[0] = 0x2D; + data_array[1] = 0x00; + } + else if (step_detect_int_cfg->step_detector_mode == BMI160_STEP_DETECT_ROBUST) + { + /* Robust mode setting */ + data_array[0] = 0x1D; + data_array[1] = 0x07; + } + else if (step_detect_int_cfg->step_detector_mode == BMI160_STEP_DETECT_USER_DEFINE) + { + /* Non recommended User defined setting */ + /* Configuring STEP_CONFIG register */ + rslt = bmi160_get_regs(BMI160_INT_STEP_CONFIG_0_ADDR, &data_array[0], 2, dev); + if (rslt == BMI160_OK) + { + temp = data_array[0] & ~BMI160_STEP_DETECT_MIN_THRES_MASK; + + /* Adding min_threshold */ + data_array[0] = temp | ((step_detect_int_cfg->min_threshold << 3) & BMI160_STEP_DETECT_MIN_THRES_MASK); + temp = data_array[0] & ~BMI160_STEP_DETECT_STEPTIME_MIN_MASK; + + /* Adding steptime_min */ + data_array[0] = temp | ((step_detect_int_cfg->steptime_min) & BMI160_STEP_DETECT_STEPTIME_MIN_MASK); + temp = data_array[1] & ~BMI160_STEP_MIN_BUF_MASK; + + /* Adding steptime_min */ + data_array[1] = temp | ((step_detect_int_cfg->step_min_buf) & BMI160_STEP_MIN_BUF_MASK); + } + } + + /* Write data to STEP_CONFIG register */ + rslt = bmi160_set_regs(BMI160_INT_STEP_CONFIG_0_ADDR, data_array, 2, dev); + + return rslt; +} + +/*! + * @brief This API enables the single/double tap interrupt. + */ +static int8_t enable_tap_int(const struct bmi160_int_settg *int_config, + const struct bmi160_acc_tap_int_cfg *tap_int_cfg, + const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data = 0; + uint8_t temp = 0; + + /* Enable single tap or double tap interrupt in Int Enable 0 register */ + rslt = bmi160_get_regs(BMI160_INT_ENABLE_0_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + if (int_config->int_type == BMI160_ACC_SINGLE_TAP_INT) + { + temp = data & ~BMI160_SINGLE_TAP_INT_EN_MASK; + data = temp | ((tap_int_cfg->tap_en << 5) & BMI160_SINGLE_TAP_INT_EN_MASK); + } + else + { + temp = data & ~BMI160_DOUBLE_TAP_INT_EN_MASK; + data = temp | ((tap_int_cfg->tap_en << 4) & BMI160_DOUBLE_TAP_INT_EN_MASK); + } + + /* Write to Enable 0 Address */ + rslt = bmi160_set_regs(BMI160_INT_ENABLE_0_ADDR, &data, 1, dev); + } + + return rslt; +} + +/*! + * @brief This API configure the interrupt PIN setting for + * tap interrupt. + */ +static int8_t config_tap_int_settg(const struct bmi160_int_settg *int_config, + const struct bmi160_acc_tap_int_cfg *tap_int_cfg, + const struct bmi160_dev *dev) +{ + int8_t rslt; + + /* Configure Interrupt pins */ + rslt = set_intr_pin_config(int_config, dev); + if (rslt == BMI160_OK) + { + rslt = map_feature_interrupt(int_config, dev); + if (rslt == BMI160_OK) + { + rslt = config_tap_data_src(tap_int_cfg, dev); + if (rslt == BMI160_OK) + { + rslt = config_tap_param(int_config, tap_int_cfg, dev); + } + } + } + + return rslt; +} + +/*! + * @brief This API configure the source of data(filter & pre-filter) + * for tap interrupt. + */ +static int8_t config_tap_data_src(const struct bmi160_acc_tap_int_cfg *tap_int_cfg, const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data = 0; + uint8_t temp = 0; + + /* Configure Int data 0 register to add source of interrupt */ + rslt = bmi160_get_regs(BMI160_INT_DATA_0_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + temp = data & ~BMI160_TAP_SRC_INT_MASK; + data = temp | ((tap_int_cfg->tap_data_src << 3) & BMI160_TAP_SRC_INT_MASK); + + /* Write data to Data 0 address */ + rslt = bmi160_set_regs(BMI160_INT_DATA_0_ADDR, &data, 1, dev); + } + + return rslt; +} + +/*! + * @brief This API configure the parameters of tap interrupt. + * Threshold, quite, shock, and duration. + */ +static int8_t config_tap_param(const struct bmi160_int_settg *int_config, + const struct bmi160_acc_tap_int_cfg *tap_int_cfg, + const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t temp = 0; + uint8_t data = 0; + uint8_t data_array[2] = { 0 }; + uint8_t count = 0; + uint8_t dur, shock, quiet, thres; + + /* Configure tap 0 register for tap shock,tap quiet duration + * in case of single tap interrupt */ + rslt = bmi160_get_regs(BMI160_INT_TAP_0_ADDR, data_array, 2, dev); + if (rslt == BMI160_OK) + { + data = data_array[count]; + if (int_config->int_type == BMI160_ACC_DOUBLE_TAP_INT) + { + dur = (uint8_t)tap_int_cfg->tap_dur; + temp = (data & ~BMI160_TAP_DUR_MASK); + + /* Add tap duration data in case of + * double tap interrupt */ + data = temp | (dur & BMI160_TAP_DUR_MASK); + } + + shock = (uint8_t)tap_int_cfg->tap_shock; + temp = data & ~BMI160_TAP_SHOCK_DUR_MASK; + data = temp | ((shock << 6) & BMI160_TAP_SHOCK_DUR_MASK); + quiet = (uint8_t)tap_int_cfg->tap_quiet; + temp = data & ~BMI160_TAP_QUIET_DUR_MASK; + data = temp | ((quiet << 7) & BMI160_TAP_QUIET_DUR_MASK); + data_array[count++] = data; + data = data_array[count]; + thres = (uint8_t)tap_int_cfg->tap_thr; + temp = data & ~BMI160_TAP_THRES_MASK; + data = temp | (thres & BMI160_TAP_THRES_MASK); + data_array[count++] = data; + + /* TAP 0 and TAP 1 address lie consecutively, + * hence writing data to respective registers at one go */ + + /* Writing to Tap 0 and Tap 1 Address simultaneously */ + rslt = bmi160_set_regs(BMI160_INT_TAP_0_ADDR, data_array, count, dev); + } + + return rslt; +} + +/*! + * @brief This API configure the secondary interface. + */ +static int8_t config_sec_if(const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t if_conf = 0; + uint8_t cmd = BMI160_AUX_NORMAL_MODE; + + /* set the aux power mode to normal*/ + rslt = bmi160_set_regs(BMI160_COMMAND_REG_ADDR, &cmd, 1, dev); + if (rslt == BMI160_OK) + { + /* 0.5ms delay - refer datasheet table 24*/ + dev->delay_ms(1); + rslt = bmi160_get_regs(BMI160_IF_CONF_ADDR, &if_conf, 1, dev); + if_conf |= (uint8_t)(1 << 5); + if (rslt == BMI160_OK) + { + /*enable the secondary interface also*/ + rslt = bmi160_set_regs(BMI160_IF_CONF_ADDR, &if_conf, 1, dev); + } + } + + return rslt; +} + +/*! + * @brief This API configure the ODR of the auxiliary sensor. + */ +static int8_t config_aux_odr(const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t aux_odr; + + rslt = bmi160_get_regs(BMI160_AUX_ODR_ADDR, &aux_odr, 1, dev); + if (rslt == BMI160_OK) + { + aux_odr = (uint8_t)(dev->aux_cfg.aux_odr); + + /* Set the secondary interface ODR + * i.e polling rate of secondary sensor */ + rslt = bmi160_set_regs(BMI160_AUX_ODR_ADDR, &aux_odr, 1, dev); + dev->delay_ms(BMI160_AUX_COM_DELAY); + } + + return rslt; +} + +/*! + * @brief This API maps the actual burst read length set by user. + */ +static int8_t map_read_len(uint16_t *len, const struct bmi160_dev *dev) +{ + int8_t rslt = BMI160_OK; + + switch (dev->aux_cfg.aux_rd_burst_len) + { + case BMI160_AUX_READ_LEN_0: + *len = 1; + break; + case BMI160_AUX_READ_LEN_1: + *len = 2; + break; + case BMI160_AUX_READ_LEN_2: + *len = 6; + break; + case BMI160_AUX_READ_LEN_3: + *len = 8; + break; + default: + rslt = BMI160_E_INVALID_INPUT; + break; + } + + return rslt; +} + +/*! + * @brief This API configure the settings of auxiliary sensor. + */ +static int8_t config_aux_settg(const struct bmi160_dev *dev) +{ + int8_t rslt; + + rslt = config_sec_if(dev); + if (rslt == BMI160_OK) + { + /* Configures the auxiliary interface settings */ + rslt = bmi160_config_aux_mode(dev); + } + + return rslt; +} + +/*! + * @brief This API extract the read data from auxiliary sensor. + */ +static int8_t extract_aux_read(uint16_t map_len, + uint8_t reg_addr, + uint8_t *aux_data, + uint16_t len, + const struct bmi160_dev *dev) +{ + int8_t rslt = BMI160_OK; + uint8_t data[8] = { 0, }; + uint8_t read_addr = BMI160_AUX_DATA_ADDR; + uint8_t count = 0; + uint8_t read_count; + uint8_t read_len = (uint8_t)map_len; + + for (; count < len;) + { + /* set address to read */ + rslt = bmi160_set_regs(BMI160_AUX_IF_2_ADDR, ®_addr, 1, dev); + dev->delay_ms(BMI160_AUX_COM_DELAY); + if (rslt == BMI160_OK) + { + rslt = bmi160_get_regs(read_addr, data, map_len, dev); + if (rslt == BMI160_OK) + { + read_count = 0; + + /* if read len is less the burst read len + * mention by user*/ + if (len < map_len) + { + read_len = (uint8_t)len; + } + else if ((len - count) < map_len) + { + read_len = (uint8_t)(len - count); + } + + for (; read_count < read_len; read_count++) + { + aux_data[count + read_count] = data[read_count]; + } + + reg_addr += (uint8_t)map_len; + count += (uint8_t)map_len; + } + else + { + rslt = BMI160_E_COM_FAIL; + break; + } + } + } + + return rslt; +} + +/*! + * @brief This API enables the orient interrupt. + */ +static int8_t enable_orient_int(const struct bmi160_acc_orient_int_cfg *orient_int_cfg, const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data = 0; + uint8_t temp = 0; + + /* Enable data ready interrupt in Int Enable 0 register */ + rslt = bmi160_get_regs(BMI160_INT_ENABLE_0_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + temp = data & ~BMI160_ORIENT_INT_EN_MASK; + data = temp | ((orient_int_cfg->orient_en << 6) & BMI160_ORIENT_INT_EN_MASK); + + /* write data to Int Enable 0 register */ + rslt = bmi160_set_regs(BMI160_INT_ENABLE_0_ADDR, &data, 1, dev); + } + + return rslt; +} + +/*! + * @brief This API configure the necessary setting of orientation interrupt. + */ +static int8_t config_orient_int_settg(const struct bmi160_acc_orient_int_cfg *orient_int_cfg, + const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data = 0; + uint8_t temp = 0; + uint8_t data_array[2] = { 0, 0 }; + + /* Configuring INT_ORIENT registers */ + rslt = bmi160_get_regs(BMI160_INT_ORIENT_0_ADDR, data_array, 2, dev); + if (rslt == BMI160_OK) + { + data = data_array[0]; + temp = data & ~BMI160_ORIENT_MODE_MASK; + + /* Adding Orientation mode */ + data = temp | ((orient_int_cfg->orient_mode) & BMI160_ORIENT_MODE_MASK); + temp = data & ~BMI160_ORIENT_BLOCK_MASK; + + /* Adding Orientation blocking */ + data = temp | ((orient_int_cfg->orient_blocking << 2) & BMI160_ORIENT_BLOCK_MASK); + temp = data & ~BMI160_ORIENT_HYST_MASK; + + /* Adding Orientation hysteresis */ + data = temp | ((orient_int_cfg->orient_hyst << 4) & BMI160_ORIENT_HYST_MASK); + data_array[0] = data; + data = data_array[1]; + temp = data & ~BMI160_ORIENT_THETA_MASK; + + /* Adding Orientation threshold */ + data = temp | ((orient_int_cfg->orient_theta) & BMI160_ORIENT_THETA_MASK); + temp = data & ~BMI160_ORIENT_UD_ENABLE; + + /* Adding Orient_ud_en */ + data = temp | ((orient_int_cfg->orient_ud_en << 6) & BMI160_ORIENT_UD_ENABLE); + temp = data & ~BMI160_AXES_EN_MASK; + + /* Adding axes_en */ + data = temp | ((orient_int_cfg->axes_ex << 7) & BMI160_AXES_EN_MASK); + data_array[1] = data; + + /* Writing data to INT_ORIENT 0 and INT_ORIENT 1 + * registers simultaneously */ + rslt = bmi160_set_regs(BMI160_INT_ORIENT_0_ADDR, data_array, 2, dev); + } + + return rslt; +} + +/*! + * @brief This API enables the flat interrupt. + */ +static int8_t enable_flat_int(const struct bmi160_acc_flat_detect_int_cfg *flat_int, const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data = 0; + uint8_t temp = 0; + + /* Enable flat interrupt in Int Enable 0 register */ + rslt = bmi160_get_regs(BMI160_INT_ENABLE_0_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + temp = data & ~BMI160_FLAT_INT_EN_MASK; + data = temp | ((flat_int->flat_en << 7) & BMI160_FLAT_INT_EN_MASK); + + /* write data to Int Enable 0 register */ + rslt = bmi160_set_regs(BMI160_INT_ENABLE_0_ADDR, &data, 1, dev); + } + + return rslt; +} + +/*! + * @brief This API configure the necessary setting of flat interrupt. + */ +static int8_t config_flat_int_settg(const struct bmi160_acc_flat_detect_int_cfg *flat_int, const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data = 0; + uint8_t temp = 0; + uint8_t data_array[2] = { 0, 0 }; + + /* Configuring INT_FLAT register */ + rslt = bmi160_get_regs(BMI160_INT_FLAT_0_ADDR, data_array, 2, dev); + if (rslt == BMI160_OK) + { + data = data_array[0]; + temp = data & ~BMI160_FLAT_THRES_MASK; + + /* Adding flat theta */ + data = temp | ((flat_int->flat_theta) & BMI160_FLAT_THRES_MASK); + data_array[0] = data; + data = data_array[1]; + temp = data & ~BMI160_FLAT_HOLD_TIME_MASK; + + /* Adding flat hold time */ + data = temp | ((flat_int->flat_hold_time << 4) & BMI160_FLAT_HOLD_TIME_MASK); + temp = data & ~BMI160_FLAT_HYST_MASK; + + /* Adding flat hysteresis */ + data = temp | ((flat_int->flat_hy) & BMI160_FLAT_HYST_MASK); + data_array[1] = data; + + /* Writing data to INT_FLAT 0 and INT_FLAT 1 + * registers simultaneously */ + rslt = bmi160_set_regs(BMI160_INT_FLAT_0_ADDR, data_array, 2, dev); + } + + return rslt; +} + +/*! + * @brief This API enables the Low-g interrupt. + */ +static int8_t enable_low_g_int(const struct bmi160_acc_low_g_int_cfg *low_g_int, const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data = 0; + uint8_t temp = 0; + + /* Enable low-g interrupt in Int Enable 1 register */ + rslt = bmi160_get_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + temp = data & ~BMI160_LOW_G_INT_EN_MASK; + data = temp | ((low_g_int->low_en << 3) & BMI160_LOW_G_INT_EN_MASK); + + /* write data to Int Enable 0 register */ + rslt = bmi160_set_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev); + } + + return rslt; +} + +/*! + * @brief This API configure the source of data(filter & pre-filter) + * for low-g interrupt. + */ +static int8_t config_low_g_data_src(const struct bmi160_acc_low_g_int_cfg *low_g_int, const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data = 0; + uint8_t temp = 0; + + /* Configure Int data 0 register to add source of interrupt */ + rslt = bmi160_get_regs(BMI160_INT_DATA_0_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + temp = data & ~BMI160_LOW_HIGH_SRC_INT_MASK; + data = temp | ((low_g_int->low_data_src << 7) & BMI160_LOW_HIGH_SRC_INT_MASK); + + /* Write data to Data 0 address */ + rslt = bmi160_set_regs(BMI160_INT_DATA_0_ADDR, &data, 1, dev); + } + + return rslt; +} + +/*! + * @brief This API configure the necessary setting of low-g interrupt. + */ +static int8_t config_low_g_int_settg(const struct bmi160_acc_low_g_int_cfg *low_g_int, const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t temp = 0; + uint8_t data_array[3] = { 0, 0, 0 }; + + /* Configuring INT_LOWHIGH register for low-g interrupt */ + rslt = bmi160_get_regs(BMI160_INT_LOWHIGH_2_ADDR, &data_array[2], 1, dev); + if (rslt == BMI160_OK) + { + temp = data_array[2] & ~BMI160_LOW_G_HYST_MASK; + + /* Adding low-g hysteresis */ + data_array[2] = temp | (low_g_int->low_hyst & BMI160_LOW_G_HYST_MASK); + temp = data_array[2] & ~BMI160_LOW_G_LOW_MODE_MASK; + + /* Adding low-mode */ + data_array[2] = temp | ((low_g_int->low_mode << 2) & BMI160_LOW_G_LOW_MODE_MASK); + + /* Adding low-g threshold */ + data_array[1] = low_g_int->low_thres; + + /* Adding low-g interrupt delay */ + data_array[0] = low_g_int->low_dur; + + /* Writing data to INT_LOWHIGH 0,1,2 registers simultaneously*/ + rslt = bmi160_set_regs(BMI160_INT_LOWHIGH_0_ADDR, data_array, 3, dev); + } + + return rslt; +} + +/*! + * @brief This API enables the high-g interrupt. + */ +static int8_t enable_high_g_int(const struct bmi160_acc_high_g_int_cfg *high_g_int_cfg, const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data = 0; + uint8_t temp = 0; + + /* Enable low-g interrupt in Int Enable 1 register */ + rslt = bmi160_get_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + /* Adding high-g X-axis */ + temp = data & ~BMI160_HIGH_G_X_INT_EN_MASK; + data = temp | (high_g_int_cfg->high_g_x & BMI160_HIGH_G_X_INT_EN_MASK); + + /* Adding high-g Y-axis */ + temp = data & ~BMI160_HIGH_G_Y_INT_EN_MASK; + data = temp | ((high_g_int_cfg->high_g_y << 1) & BMI160_HIGH_G_Y_INT_EN_MASK); + + /* Adding high-g Z-axis */ + temp = data & ~BMI160_HIGH_G_Z_INT_EN_MASK; + data = temp | ((high_g_int_cfg->high_g_z << 2) & BMI160_HIGH_G_Z_INT_EN_MASK); + + /* write data to Int Enable 0 register */ + rslt = bmi160_set_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev); + } + + return rslt; +} + +/*! + * @brief This API configure the source of data(filter & pre-filter) + * for high-g interrupt. + */ +static int8_t config_high_g_data_src(const struct bmi160_acc_high_g_int_cfg *high_g_int_cfg, + const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data = 0; + uint8_t temp = 0; + + /* Configure Int data 0 register to add source of interrupt */ + rslt = bmi160_get_regs(BMI160_INT_DATA_0_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + temp = data & ~BMI160_LOW_HIGH_SRC_INT_MASK; + data = temp | ((high_g_int_cfg->high_data_src << 7) & BMI160_LOW_HIGH_SRC_INT_MASK); + + /* Write data to Data 0 address */ + rslt = bmi160_set_regs(BMI160_INT_DATA_0_ADDR, &data, 1, dev); + } + + return rslt; +} + +/*! + * @brief This API configure the necessary setting of high-g interrupt. + */ +static int8_t config_high_g_int_settg(const struct bmi160_acc_high_g_int_cfg *high_g_int_cfg, + const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t temp = 0; + uint8_t data_array[3] = { 0, 0, 0 }; + + rslt = bmi160_get_regs(BMI160_INT_LOWHIGH_2_ADDR, &data_array[0], 1, dev); + if (rslt == BMI160_OK) + { + temp = data_array[0] & ~BMI160_HIGH_G_HYST_MASK; + + /* Adding high-g hysteresis */ + data_array[0] = temp | ((high_g_int_cfg->high_hy << 6) & BMI160_HIGH_G_HYST_MASK); + + /* Adding high-g duration */ + data_array[1] = high_g_int_cfg->high_dur; + + /* Adding high-g threshold */ + data_array[2] = high_g_int_cfg->high_thres; + rslt = bmi160_set_regs(BMI160_INT_LOWHIGH_2_ADDR, data_array, 3, dev); + } + + return rslt; +} + +/*! + * @brief This API configure the behavioural setting of interrupt pin. + */ +static int8_t config_int_out_ctrl(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t temp = 0; + uint8_t data = 0; + + /* Configuration of output interrupt signals on pins INT1 and INT2 are + * done in BMI160_INT_OUT_CTRL_ADDR register*/ + rslt = bmi160_get_regs(BMI160_INT_OUT_CTRL_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + /* updating the interrupt pin structure to local structure */ + const struct bmi160_int_pin_settg *intr_pin_sett = &(int_config->int_pin_settg); + + /* Configuring channel 1 */ + if (int_config->int_channel == BMI160_INT_CHANNEL_1) + { + /* Output enable */ + temp = data & ~BMI160_INT1_OUTPUT_EN_MASK; + data = temp | ((intr_pin_sett->output_en << 3) & BMI160_INT1_OUTPUT_EN_MASK); + + /* Output mode */ + temp = data & ~BMI160_INT1_OUTPUT_MODE_MASK; + data = temp | ((intr_pin_sett->output_mode << 2) & BMI160_INT1_OUTPUT_MODE_MASK); + + /* Output type */ + temp = data & ~BMI160_INT1_OUTPUT_TYPE_MASK; + data = temp | ((intr_pin_sett->output_type << 1) & BMI160_INT1_OUTPUT_TYPE_MASK); + + /* edge control */ + temp = data & ~BMI160_INT1_EDGE_CTRL_MASK; + data = temp | ((intr_pin_sett->edge_ctrl) & BMI160_INT1_EDGE_CTRL_MASK); + } + else + { + /* Configuring channel 2 */ + /* Output enable */ + temp = data & ~BMI160_INT2_OUTPUT_EN_MASK; + data = temp | ((intr_pin_sett->output_en << 7) & BMI160_INT2_OUTPUT_EN_MASK); + + /* Output mode */ + temp = data & ~BMI160_INT2_OUTPUT_MODE_MASK; + data = temp | ((intr_pin_sett->output_mode << 6) & BMI160_INT2_OUTPUT_MODE_MASK); + + /* Output type */ + temp = data & ~BMI160_INT2_OUTPUT_TYPE_MASK; + data = temp | ((intr_pin_sett->output_type << 5) & BMI160_INT2_OUTPUT_TYPE_MASK); + + /* edge control */ + temp = data & ~BMI160_INT2_EDGE_CTRL_MASK; + data = temp | ((intr_pin_sett->edge_ctrl << 4) & BMI160_INT2_EDGE_CTRL_MASK); + } + + rslt = bmi160_set_regs(BMI160_INT_OUT_CTRL_ADDR, &data, 1, dev); + } + + return rslt; +} + +/*! + * @brief This API configure the mode(input enable, latch or non-latch) of interrupt pin. + */ +static int8_t config_int_latch(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t temp = 0; + uint8_t data = 0; + + /* Configuration of latch on pins INT1 and INT2 are done in + * BMI160_INT_LATCH_ADDR register*/ + rslt = bmi160_get_regs(BMI160_INT_LATCH_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + /* updating the interrupt pin structure to local structure */ + const struct bmi160_int_pin_settg *intr_pin_sett = &(int_config->int_pin_settg); + if (int_config->int_channel == BMI160_INT_CHANNEL_1) + { + /* Configuring channel 1 */ + /* Input enable */ + temp = data & ~BMI160_INT1_INPUT_EN_MASK; + data = temp | ((intr_pin_sett->input_en << 4) & BMI160_INT1_INPUT_EN_MASK); + } + else + { + /* Configuring channel 2 */ + /* Input enable */ + temp = data & ~BMI160_INT2_INPUT_EN_MASK; + data = temp | ((intr_pin_sett->input_en << 5) & BMI160_INT2_INPUT_EN_MASK); + } + + /* In case of latch interrupt,update the latch duration */ + + /* Latching holds the interrupt for the amount of latch + * duration time */ + temp = data & ~BMI160_INT_LATCH_MASK; + data = temp | (intr_pin_sett->latch_dur & BMI160_INT_LATCH_MASK); + + /* OUT_CTRL_INT and LATCH_INT address lie consecutively, + * hence writing data to respective registers at one go */ + rslt = bmi160_set_regs(BMI160_INT_LATCH_ADDR, &data, 1, dev); + } + + return rslt; +} + +/*! + * @brief This API performs the self test for accelerometer of BMI160 + */ +static int8_t perform_accel_self_test(struct bmi160_dev *dev) +{ + int8_t rslt; + struct bmi160_sensor_data accel_pos, accel_neg; + + /* Enable Gyro self test bit */ + rslt = enable_accel_self_test(dev); + if (rslt == BMI160_OK) + { + /* Perform accel self test with positive excitation */ + rslt = accel_self_test_positive_excitation(&accel_pos, dev); + if (rslt == BMI160_OK) + { + /* Perform accel self test with negative excitation */ + rslt = accel_self_test_negative_excitation(&accel_neg, dev); + if (rslt == BMI160_OK) + { + /* Validate the self test result */ + rslt = validate_accel_self_test(&accel_pos, &accel_neg); + } + } + } + + return rslt; +} + +/*! + * @brief This API enables to perform the accel self test by setting proper + * configurations to facilitate accel self test + */ +static int8_t enable_accel_self_test(struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t reg_data; + + /* Set the Accel power mode as normal mode */ + dev->accel_cfg.power = BMI160_ACCEL_NORMAL_MODE; + + /* Set the sensor range configuration as 8G */ + dev->accel_cfg.range = BMI160_ACCEL_RANGE_8G; + rslt = bmi160_set_sens_conf(dev); + if (rslt == BMI160_OK) + { + /* Accel configurations are set to facilitate self test + * acc_odr - 1600Hz ; acc_bwp = 2 ; acc_us = 0 */ + reg_data = BMI160_ACCEL_SELF_TEST_CONFIG; + rslt = bmi160_set_regs(BMI160_ACCEL_CONFIG_ADDR, ®_data, 1, dev); + } + + return rslt; +} + +/*! + * @brief This API performs accel self test with positive excitation + */ +static int8_t accel_self_test_positive_excitation(struct bmi160_sensor_data *accel_pos, const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t reg_data; + + /* Enable accel self test with positive self-test excitation + * and with amplitude of deflection set as high */ + reg_data = BMI160_ACCEL_SELF_TEST_POSITIVE_EN; + rslt = bmi160_set_regs(BMI160_SELF_TEST_ADDR, ®_data, 1, dev); + if (rslt == BMI160_OK) + { + /* Read the data after a delay of 50ms - refer datasheet 2.8.1 accel self test*/ + dev->delay_ms(BMI160_ACCEL_SELF_TEST_DELAY); + rslt = bmi160_get_sensor_data(BMI160_ACCEL_ONLY, accel_pos, NULL, dev); + } + + return rslt; +} + +/*! + * @brief This API performs accel self test with negative excitation + */ +static int8_t accel_self_test_negative_excitation(struct bmi160_sensor_data *accel_neg, const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t reg_data; + + /* Enable accel self test with negative self-test excitation + * and with amplitude of deflection set as high */ + reg_data = BMI160_ACCEL_SELF_TEST_NEGATIVE_EN; + rslt = bmi160_set_regs(BMI160_SELF_TEST_ADDR, ®_data, 1, dev); + if (rslt == BMI160_OK) + { + /* Read the data after a delay of 50ms */ + dev->delay_ms(BMI160_ACCEL_SELF_TEST_DELAY); + rslt = bmi160_get_sensor_data(BMI160_ACCEL_ONLY, accel_neg, NULL, dev); + } + + return rslt; +} + +/*! + * @brief This API validates the accel self test results + */ +static int8_t validate_accel_self_test(const struct bmi160_sensor_data *accel_pos, + const struct bmi160_sensor_data *accel_neg) +{ + int8_t rslt; + + /* Validate the results of self test */ + if (((accel_neg->x - accel_pos->x) > BMI160_ACCEL_SELF_TEST_LIMIT) && + ((accel_neg->y - accel_pos->y) > BMI160_ACCEL_SELF_TEST_LIMIT) && + ((accel_neg->z - accel_pos->z) > BMI160_ACCEL_SELF_TEST_LIMIT)) + { + /* Self test pass condition */ + rslt = BMI160_OK; + } + else + { + rslt = BMI160_W_ACCEl_SELF_TEST_FAIL; + } + + return rslt; +} + +/*! + * @brief This API performs the self test for gyroscope of BMI160 + */ +static int8_t perform_gyro_self_test(const struct bmi160_dev *dev) +{ + int8_t rslt; + + /* Enable Gyro self test bit */ + rslt = enable_gyro_self_test(dev); + if (rslt == BMI160_OK) + { + /* Validate the gyro self test a delay of 50ms */ + dev->delay_ms(50); + + /* Validate the gyro self test results */ + rslt = validate_gyro_self_test(dev); + } + + return rslt; +} + +/*! + * @brief This API enables the self test bit to trigger self test for Gyro + */ +static int8_t enable_gyro_self_test(const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t reg_data; + + /* Enable the Gyro self test bit to trigger the self test */ + rslt = bmi160_get_regs(BMI160_SELF_TEST_ADDR, ®_data, 1, dev); + if (rslt == BMI160_OK) + { + reg_data = BMI160_SET_BITS(reg_data, BMI160_GYRO_SELF_TEST, 1); + rslt = bmi160_set_regs(BMI160_SELF_TEST_ADDR, ®_data, 1, dev); + if (rslt == BMI160_OK) + { + /* Delay to enable gyro self test */ + dev->delay_ms(15); + } + } + + return rslt; +} + +/*! + * @brief This API validates the self test results of Gyro + */ +static int8_t validate_gyro_self_test(const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t reg_data; + + /* Validate the Gyro self test result */ + rslt = bmi160_get_regs(BMI160_STATUS_ADDR, ®_data, 1, dev); + if (rslt == BMI160_OK) + { + + reg_data = BMI160_GET_BITS(reg_data, BMI160_GYRO_SELF_TEST_STATUS); + if (reg_data == BMI160_ENABLE) + { + /* Gyro self test success case */ + rslt = BMI160_OK; + } + else + { + rslt = BMI160_W_GYRO_SELF_TEST_FAIL; + } + } + + return rslt; +} + +/*! + * @brief This API sets FIFO full interrupt of the sensor.This interrupt + * occurs when the FIFO is full and the next full data sample would cause + * a FIFO overflow, which may delete the old samples. + */ +static int8_t set_fifo_full_int(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev) +{ + int8_t rslt = BMI160_OK; + + /* Null-pointer check */ + if ((dev == NULL) || (dev->delay_ms == NULL)) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + /*enable the fifo full interrupt */ + rslt = enable_fifo_full_int(int_config, dev); + if (rslt == BMI160_OK) + { + /* Configure Interrupt pins */ + rslt = set_intr_pin_config(int_config, dev); + if (rslt == BMI160_OK) + { + rslt = map_hardware_interrupt(int_config, dev); + } + } + } + + return rslt; +} + +/*! + * @brief This enable the FIFO full interrupt engine. + */ +static int8_t enable_fifo_full_int(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data = 0; + + rslt = bmi160_get_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + data = BMI160_SET_BITS(data, BMI160_FIFO_FULL_INT, int_config->fifo_full_int_en); + + /* Writing data to INT ENABLE 1 Address */ + rslt = bmi160_set_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev); + } + + return rslt; +} + +/*! + * @brief This API sets FIFO watermark interrupt of the sensor.The FIFO + * watermark interrupt is fired, when the FIFO fill level is above a fifo + * watermark. + */ +static int8_t set_fifo_watermark_int(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev) +{ + int8_t rslt = BMI160_OK; + + if ((dev == NULL) || (dev->delay_ms == NULL)) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + /* Enable fifo-watermark interrupt in Int Enable 1 register */ + rslt = enable_fifo_wtm_int(int_config, dev); + if (rslt == BMI160_OK) + { + /* Configure Interrupt pins */ + rslt = set_intr_pin_config(int_config, dev); + if (rslt == BMI160_OK) + { + rslt = map_hardware_interrupt(int_config, dev); + } + } + } + + return rslt; +} + +/*! + * @brief This enable the FIFO watermark interrupt engine. + */ +static int8_t enable_fifo_wtm_int(const struct bmi160_int_settg *int_config, const struct bmi160_dev *dev) +{ + int8_t rslt; + uint8_t data = 0; + + rslt = bmi160_get_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + data = BMI160_SET_BITS(data, BMI160_FIFO_WTM_INT, int_config->fifo_wtm_int_en); + + /* Writing data to INT ENABLE 1 Address */ + rslt = bmi160_set_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev); + } + + return rslt; +} + +/*! + * @brief This API is used to reset the FIFO related configurations + * in the fifo_frame structure. + */ +static void reset_fifo_data_structure(const struct bmi160_dev *dev) +{ + /*Prepare for next FIFO read by resetting FIFO's + * internal data structures*/ + dev->fifo->accel_byte_start_idx = 0; + dev->fifo->gyro_byte_start_idx = 0; + dev->fifo->aux_byte_start_idx = 0; + dev->fifo->sensor_time = 0; + dev->fifo->skipped_frame_count = 0; +} + +/*! + * @brief This API is used to read fifo_byte_counter value (i.e) + * current fill-level in Fifo buffer. + */ +static int8_t get_fifo_byte_counter(uint16_t *bytes_to_read, struct bmi160_dev const *dev) +{ + int8_t rslt = 0; + uint8_t data[2]; + uint8_t addr = BMI160_FIFO_LENGTH_ADDR; + + rslt |= bmi160_get_regs(addr, data, 2, dev); + data[1] = data[1] & BMI160_FIFO_BYTE_COUNTER_MASK; + + /* Available data in FIFO is stored in bytes_to_read*/ + *bytes_to_read = (((uint16_t)data[1] << 8) | ((uint16_t)data[0])); + + return rslt; +} + +/*! + * @brief This API is used to compute the number of bytes of accel FIFO data + * which is to be parsed in header-less mode + */ +static void get_accel_len_to_parse(uint16_t *data_index, + uint16_t *data_read_length, + const uint8_t *acc_frame_count, + const struct bmi160_dev *dev) +{ + /* Data start index */ + *data_index = dev->fifo->accel_byte_start_idx; + if (dev->fifo->fifo_data_enable == BMI160_FIFO_A_ENABLE) + { + *data_read_length = (*acc_frame_count) * BMI160_FIFO_A_LENGTH; + } + else if (dev->fifo->fifo_data_enable == BMI160_FIFO_G_A_ENABLE) + { + *data_read_length = (*acc_frame_count) * BMI160_FIFO_GA_LENGTH; + } + else if (dev->fifo->fifo_data_enable == BMI160_FIFO_M_A_ENABLE) + { + *data_read_length = (*acc_frame_count) * BMI160_FIFO_MA_LENGTH; + } + else if (dev->fifo->fifo_data_enable == BMI160_FIFO_M_G_A_ENABLE) + { + *data_read_length = (*acc_frame_count) * BMI160_FIFO_MGA_LENGTH; + } + else + { + /* When accel is not enabled ,there will be no accel data. + * so we update the data index as complete */ + *data_index = dev->fifo->length; + } + + if (*data_read_length > dev->fifo->length) + { + /* Handling the case where more data is requested + * than that is available*/ + *data_read_length = dev->fifo->length; + } +} + +/*! + * @brief This API is used to parse the accelerometer data from the + * FIFO data in both header mode and header-less mode. + * It updates the idx value which is used to store the index of + * the current data byte which is parsed. + */ +static void unpack_accel_frame(struct bmi160_sensor_data *acc, + uint16_t *idx, + uint8_t *acc_idx, + uint8_t frame_info, + const struct bmi160_dev *dev) +{ + switch (frame_info) + { + case BMI160_FIFO_HEAD_A: + case BMI160_FIFO_A_ENABLE: + + /*Partial read, then skip the data*/ + if ((*idx + BMI160_FIFO_A_LENGTH) > dev->fifo->length) + { + /*Update the data index as complete*/ + *idx = dev->fifo->length; + break; + } + + /*Unpack the data array into the structure instance "acc" */ + unpack_accel_data(&acc[*acc_idx], *idx, dev); + + /*Move the data index*/ + *idx = *idx + BMI160_FIFO_A_LENGTH; + (*acc_idx)++; + break; + case BMI160_FIFO_HEAD_G_A: + case BMI160_FIFO_G_A_ENABLE: + + /*Partial read, then skip the data*/ + if ((*idx + BMI160_FIFO_GA_LENGTH) > dev->fifo->length) + { + /*Update the data index as complete*/ + *idx = dev->fifo->length; + break; + } + + /*Unpack the data array into structure instance "acc"*/ + unpack_accel_data(&acc[*acc_idx], *idx + BMI160_FIFO_G_LENGTH, dev); + + /*Move the data index*/ + *idx = *idx + BMI160_FIFO_GA_LENGTH; + (*acc_idx)++; + break; + case BMI160_FIFO_HEAD_M_A: + case BMI160_FIFO_M_A_ENABLE: + + /*Partial read, then skip the data*/ + if ((*idx + BMI160_FIFO_MA_LENGTH) > dev->fifo->length) + { + /*Update the data index as complete*/ + *idx = dev->fifo->length; + break; + } + + /*Unpack the data array into structure instance "acc"*/ + unpack_accel_data(&acc[*acc_idx], *idx + BMI160_FIFO_M_LENGTH, dev); + + /*Move the data index*/ + *idx = *idx + BMI160_FIFO_MA_LENGTH; + (*acc_idx)++; + break; + case BMI160_FIFO_HEAD_M_G_A: + case BMI160_FIFO_M_G_A_ENABLE: + + /*Partial read, then skip the data*/ + if ((*idx + BMI160_FIFO_MGA_LENGTH) > dev->fifo->length) + { + /*Update the data index as complete*/ + *idx = dev->fifo->length; + break; + } + + /*Unpack the data array into structure instance "acc"*/ + unpack_accel_data(&acc[*acc_idx], *idx + BMI160_FIFO_MG_LENGTH, dev); + + /*Move the data index*/ + *idx = *idx + BMI160_FIFO_MGA_LENGTH; + (*acc_idx)++; + break; + case BMI160_FIFO_HEAD_M: + case BMI160_FIFO_M_ENABLE: + (*idx) = (*idx) + BMI160_FIFO_M_LENGTH; + break; + case BMI160_FIFO_HEAD_G: + case BMI160_FIFO_G_ENABLE: + (*idx) = (*idx) + BMI160_FIFO_G_LENGTH; + break; + case BMI160_FIFO_HEAD_M_G: + case BMI160_FIFO_M_G_ENABLE: + (*idx) = (*idx) + BMI160_FIFO_MG_LENGTH; + break; + default: + break; + } +} + +/*! + * @brief This API is used to parse the accelerometer data from the + * FIFO data and store it in the instance of the structure bmi160_sensor_data. + */ +static void unpack_accel_data(struct bmi160_sensor_data *accel_data, + uint16_t data_start_index, + const struct bmi160_dev *dev) +{ + uint16_t data_lsb; + uint16_t data_msb; + + /* Accel raw x data */ + data_lsb = dev->fifo->data[data_start_index++]; + data_msb = dev->fifo->data[data_start_index++]; + accel_data->x = (int16_t)((data_msb << 8) | data_lsb); + + /* Accel raw y data */ + data_lsb = dev->fifo->data[data_start_index++]; + data_msb = dev->fifo->data[data_start_index++]; + accel_data->y = (int16_t)((data_msb << 8) | data_lsb); + + /* Accel raw z data */ + data_lsb = dev->fifo->data[data_start_index++]; + data_msb = dev->fifo->data[data_start_index++]; + accel_data->z = (int16_t)((data_msb << 8) | data_lsb); +} + +/*! + * @brief This API is used to parse the accelerometer data from the + * FIFO data in header mode. + */ +static void extract_accel_header_mode(struct bmi160_sensor_data *accel_data, + uint8_t *accel_length, + const struct bmi160_dev *dev) +{ + uint8_t frame_header = 0; + uint16_t data_index; + uint8_t accel_index = 0; + + for (data_index = dev->fifo->accel_byte_start_idx; data_index < dev->fifo->length;) + { + /* extracting Frame header */ + frame_header = (dev->fifo->data[data_index] & BMI160_FIFO_TAG_INTR_MASK); + + /*Index is moved to next byte where the data is starting*/ + data_index++; + switch (frame_header) + { + /* Accel frame */ + case BMI160_FIFO_HEAD_A: + case BMI160_FIFO_HEAD_M_A: + case BMI160_FIFO_HEAD_G_A: + case BMI160_FIFO_HEAD_M_G_A: + unpack_accel_frame(accel_data, &data_index, &accel_index, frame_header, dev); + break; + case BMI160_FIFO_HEAD_M: + move_next_frame(&data_index, BMI160_FIFO_M_LENGTH, dev); + break; + case BMI160_FIFO_HEAD_G: + move_next_frame(&data_index, BMI160_FIFO_G_LENGTH, dev); + break; + case BMI160_FIFO_HEAD_M_G: + move_next_frame(&data_index, BMI160_FIFO_MG_LENGTH, dev); + break; + + /* Sensor time frame */ + case BMI160_FIFO_HEAD_SENSOR_TIME: + unpack_sensortime_frame(&data_index, dev); + break; + + /* Skip frame */ + case BMI160_FIFO_HEAD_SKIP_FRAME: + unpack_skipped_frame(&data_index, dev); + break; + + /* Input config frame */ + case BMI160_FIFO_HEAD_INPUT_CONFIG: + move_next_frame(&data_index, 1, dev); + break; + case BMI160_FIFO_HEAD_OVER_READ: + + /* Update the data index as complete in case of Over read */ + data_index = dev->fifo->length; + break; + default: + break; + } + if (*accel_length == accel_index) + { + /* Number of frames to read completed */ + break; + } + } + + /*Update number of accel data read*/ + *accel_length = accel_index; + + /*Update the accel frame index*/ + dev->fifo->accel_byte_start_idx = data_index; +} + +/*! + * @brief This API computes the number of bytes of gyro FIFO data + * which is to be parsed in header-less mode + */ +static void get_gyro_len_to_parse(uint16_t *data_index, + uint16_t *data_read_length, + const uint8_t *gyro_frame_count, + const struct bmi160_dev *dev) +{ + /* Data start index */ + *data_index = dev->fifo->gyro_byte_start_idx; + if (dev->fifo->fifo_data_enable == BMI160_FIFO_G_ENABLE) + { + *data_read_length = (*gyro_frame_count) * BMI160_FIFO_G_LENGTH; + } + else if (dev->fifo->fifo_data_enable == BMI160_FIFO_G_A_ENABLE) + { + *data_read_length = (*gyro_frame_count) * BMI160_FIFO_GA_LENGTH; + } + else if (dev->fifo->fifo_data_enable == BMI160_FIFO_M_G_ENABLE) + { + *data_read_length = (*gyro_frame_count) * BMI160_FIFO_MG_LENGTH; + } + else if (dev->fifo->fifo_data_enable == BMI160_FIFO_M_G_A_ENABLE) + { + *data_read_length = (*gyro_frame_count) * BMI160_FIFO_MGA_LENGTH; + } + else + { + /* When gyro is not enabled ,there will be no gyro data. + * so we update the data index as complete */ + *data_index = dev->fifo->length; + } + + if (*data_read_length > dev->fifo->length) + { + /* Handling the case where more data is requested + * than that is available*/ + *data_read_length = dev->fifo->length; + } +} + +/*! + * @brief This API is used to parse the gyroscope's data from the + * FIFO data in both header mode and header-less mode. + * It updates the idx value which is used to store the index of + * the current data byte which is parsed. + */ +static void unpack_gyro_frame(struct bmi160_sensor_data *gyro, + uint16_t *idx, + uint8_t *gyro_idx, + uint8_t frame_info, + const struct bmi160_dev *dev) +{ + switch (frame_info) + { + case BMI160_FIFO_HEAD_G: + case BMI160_FIFO_G_ENABLE: + + /*Partial read, then skip the data*/ + if ((*idx + BMI160_FIFO_G_LENGTH) > dev->fifo->length) + { + /*Update the data index as complete*/ + *idx = dev->fifo->length; + break; + } + + /*Unpack the data array into structure instance "gyro"*/ + unpack_gyro_data(&gyro[*gyro_idx], *idx, dev); + + /*Move the data index*/ + (*idx) = (*idx) + BMI160_FIFO_G_LENGTH; + (*gyro_idx)++; + break; + case BMI160_FIFO_HEAD_G_A: + case BMI160_FIFO_G_A_ENABLE: + + /*Partial read, then skip the data*/ + if ((*idx + BMI160_FIFO_GA_LENGTH) > dev->fifo->length) + { + /*Update the data index as complete*/ + *idx = dev->fifo->length; + break; + } + + /* Unpack the data array into structure instance "gyro" */ + unpack_gyro_data(&gyro[*gyro_idx], *idx, dev); + + /* Move the data index */ + *idx = *idx + BMI160_FIFO_GA_LENGTH; + (*gyro_idx)++; + break; + case BMI160_FIFO_HEAD_M_G_A: + case BMI160_FIFO_M_G_A_ENABLE: + + /*Partial read, then skip the data*/ + if ((*idx + BMI160_FIFO_MGA_LENGTH) > dev->fifo->length) + { + /*Update the data index as complete*/ + *idx = dev->fifo->length; + break; + } + + /*Unpack the data array into structure instance "gyro"*/ + unpack_gyro_data(&gyro[*gyro_idx], *idx + BMI160_FIFO_M_LENGTH, dev); + + /*Move the data index*/ + *idx = *idx + BMI160_FIFO_MGA_LENGTH; + (*gyro_idx)++; + break; + case BMI160_FIFO_HEAD_M_A: + case BMI160_FIFO_M_A_ENABLE: + + /* Move the data index */ + *idx = *idx + BMI160_FIFO_MA_LENGTH; + break; + case BMI160_FIFO_HEAD_M: + case BMI160_FIFO_M_ENABLE: + (*idx) = (*idx) + BMI160_FIFO_M_LENGTH; + break; + case BMI160_FIFO_HEAD_M_G: + case BMI160_FIFO_M_G_ENABLE: + + /*Partial read, then skip the data*/ + if ((*idx + BMI160_FIFO_MG_LENGTH) > dev->fifo->length) + { + /*Update the data index as complete*/ + *idx = dev->fifo->length; + break; + } + + /*Unpack the data array into structure instance "gyro"*/ + unpack_gyro_data(&gyro[*gyro_idx], *idx + BMI160_FIFO_M_LENGTH, dev); + + /*Move the data index*/ + (*idx) = (*idx) + BMI160_FIFO_MG_LENGTH; + (*gyro_idx)++; + break; + case BMI160_FIFO_HEAD_A: + case BMI160_FIFO_A_ENABLE: + + /*Move the data index*/ + *idx = *idx + BMI160_FIFO_A_LENGTH; + break; + default: + break; + } +} + +/*! + * @brief This API is used to parse the gyro data from the + * FIFO data and store it in the instance of the structure bmi160_sensor_data. + */ +static void unpack_gyro_data(struct bmi160_sensor_data *gyro_data, + uint16_t data_start_index, + const struct bmi160_dev *dev) +{ + uint16_t data_lsb; + uint16_t data_msb; + + /* Gyro raw x data */ + data_lsb = dev->fifo->data[data_start_index++]; + data_msb = dev->fifo->data[data_start_index++]; + gyro_data->x = (int16_t)((data_msb << 8) | data_lsb); + + /* Gyro raw y data */ + data_lsb = dev->fifo->data[data_start_index++]; + data_msb = dev->fifo->data[data_start_index++]; + gyro_data->y = (int16_t)((data_msb << 8) | data_lsb); + + /* Gyro raw z data */ + data_lsb = dev->fifo->data[data_start_index++]; + data_msb = dev->fifo->data[data_start_index++]; + gyro_data->z = (int16_t)((data_msb << 8) | data_lsb); +} + +/*! + * @brief This API is used to parse the gyro data from the + * FIFO data in header mode. + */ +static void extract_gyro_header_mode(struct bmi160_sensor_data *gyro_data, + uint8_t *gyro_length, + const struct bmi160_dev *dev) +{ + uint8_t frame_header = 0; + uint16_t data_index; + uint8_t gyro_index = 0; + + for (data_index = dev->fifo->gyro_byte_start_idx; data_index < dev->fifo->length;) + { + /* extracting Frame header */ + frame_header = (dev->fifo->data[data_index] & BMI160_FIFO_TAG_INTR_MASK); + + /*Index is moved to next byte where the data is starting*/ + data_index++; + switch (frame_header) + { + /* GYRO frame */ + case BMI160_FIFO_HEAD_G: + case BMI160_FIFO_HEAD_G_A: + case BMI160_FIFO_HEAD_M_G: + case BMI160_FIFO_HEAD_M_G_A: + unpack_gyro_frame(gyro_data, &data_index, &gyro_index, frame_header, dev); + break; + case BMI160_FIFO_HEAD_A: + move_next_frame(&data_index, BMI160_FIFO_A_LENGTH, dev); + break; + case BMI160_FIFO_HEAD_M: + move_next_frame(&data_index, BMI160_FIFO_M_LENGTH, dev); + break; + case BMI160_FIFO_HEAD_M_A: + move_next_frame(&data_index, BMI160_FIFO_M_LENGTH, dev); + break; + + /* Sensor time frame */ + case BMI160_FIFO_HEAD_SENSOR_TIME: + unpack_sensortime_frame(&data_index, dev); + break; + + /* Skip frame */ + case BMI160_FIFO_HEAD_SKIP_FRAME: + unpack_skipped_frame(&data_index, dev); + break; + + /* Input config frame */ + case BMI160_FIFO_HEAD_INPUT_CONFIG: + move_next_frame(&data_index, 1, dev); + break; + case BMI160_FIFO_HEAD_OVER_READ: + + /* Update the data index as complete in case of over read */ + data_index = dev->fifo->length; + break; + default: + break; + } + if (*gyro_length == gyro_index) + { + /*Number of frames to read completed*/ + break; + } + } + + /*Update number of gyro data read*/ + *gyro_length = gyro_index; + + /*Update the gyro frame index*/ + dev->fifo->gyro_byte_start_idx = data_index; +} + +/*! + * @brief This API computes the number of bytes of aux FIFO data + * which is to be parsed in header-less mode + */ +static void get_aux_len_to_parse(uint16_t *data_index, + uint16_t *data_read_length, + const uint8_t *aux_frame_count, + const struct bmi160_dev *dev) +{ + /* Data start index */ + *data_index = dev->fifo->gyro_byte_start_idx; + if (dev->fifo->fifo_data_enable == BMI160_FIFO_M_ENABLE) + { + *data_read_length = (*aux_frame_count) * BMI160_FIFO_M_LENGTH; + } + else if (dev->fifo->fifo_data_enable == BMI160_FIFO_M_A_ENABLE) + { + *data_read_length = (*aux_frame_count) * BMI160_FIFO_MA_LENGTH; + } + else if (dev->fifo->fifo_data_enable == BMI160_FIFO_M_G_ENABLE) + { + *data_read_length = (*aux_frame_count) * BMI160_FIFO_MG_LENGTH; + } + else if (dev->fifo->fifo_data_enable == BMI160_FIFO_M_G_A_ENABLE) + { + *data_read_length = (*aux_frame_count) * BMI160_FIFO_MGA_LENGTH; + } + else + { + /* When aux is not enabled ,there will be no aux data. + * so we update the data index as complete */ + *data_index = dev->fifo->length; + } + + if (*data_read_length > dev->fifo->length) + { + /* Handling the case where more data is requested + * than that is available */ + *data_read_length = dev->fifo->length; + } +} + +/*! + * @brief This API is used to parse the aux's data from the + * FIFO data in both header mode and header-less mode. + * It updates the idx value which is used to store the index of + * the current data byte which is parsed + */ +static void unpack_aux_frame(struct bmi160_aux_data *aux_data, + uint16_t *idx, + uint8_t *aux_index, + uint8_t frame_info, + const struct bmi160_dev *dev) +{ + switch (frame_info) + { + case BMI160_FIFO_HEAD_M: + case BMI160_FIFO_M_ENABLE: + + /* Partial read, then skip the data */ + if ((*idx + BMI160_FIFO_M_LENGTH) > dev->fifo->length) + { + /* Update the data index as complete */ + *idx = dev->fifo->length; + break; + } + + /* Unpack the data array into structure instance */ + unpack_aux_data(&aux_data[*aux_index], *idx, dev); + + /* Move the data index */ + *idx = *idx + BMI160_FIFO_M_LENGTH; + (*aux_index)++; + break; + case BMI160_FIFO_HEAD_M_A: + case BMI160_FIFO_M_A_ENABLE: + + /* Partial read, then skip the data */ + if ((*idx + BMI160_FIFO_MA_LENGTH) > dev->fifo->length) + { + /* Update the data index as complete */ + *idx = dev->fifo->length; + break; + } + + /* Unpack the data array into structure instance */ + unpack_aux_data(&aux_data[*aux_index], *idx, dev); + + /* Move the data index */ + *idx = *idx + BMI160_FIFO_MA_LENGTH; + (*aux_index)++; + break; + case BMI160_FIFO_HEAD_M_G: + case BMI160_FIFO_M_G_ENABLE: + + /* Partial read, then skip the data */ + if ((*idx + BMI160_FIFO_MG_LENGTH) > dev->fifo->length) + { + /* Update the data index as complete */ + *idx = dev->fifo->length; + break; + } + + /* Unpack the data array into structure instance */ + unpack_aux_data(&aux_data[*aux_index], *idx, dev); + + /* Move the data index */ + (*idx) = (*idx) + BMI160_FIFO_MG_LENGTH; + (*aux_index)++; + break; + case BMI160_FIFO_HEAD_M_G_A: + case BMI160_FIFO_M_G_A_ENABLE: + + /*Partial read, then skip the data*/ + if ((*idx + BMI160_FIFO_MGA_LENGTH) > dev->fifo->length) + { + /* Update the data index as complete */ + *idx = dev->fifo->length; + break; + } + + /* Unpack the data array into structure instance */ + unpack_aux_data(&aux_data[*aux_index], *idx, dev); + + /*Move the data index*/ + *idx = *idx + BMI160_FIFO_MGA_LENGTH; + (*aux_index)++; + break; + case BMI160_FIFO_HEAD_G: + case BMI160_FIFO_G_ENABLE: + + /* Move the data index */ + (*idx) = (*idx) + BMI160_FIFO_G_LENGTH; + break; + case BMI160_FIFO_HEAD_G_A: + case BMI160_FIFO_G_A_ENABLE: + + /* Move the data index */ + *idx = *idx + BMI160_FIFO_GA_LENGTH; + break; + case BMI160_FIFO_HEAD_A: + case BMI160_FIFO_A_ENABLE: + + /* Move the data index */ + *idx = *idx + BMI160_FIFO_A_LENGTH; + break; + default: + break; + } +} + +/*! + * @brief This API is used to parse the aux data from the + * FIFO data and store it in the instance of the structure bmi160_aux_data. + */ +static void unpack_aux_data(struct bmi160_aux_data *aux_data, uint16_t data_start_index, const struct bmi160_dev *dev) +{ + /* Aux data bytes */ + aux_data->data[0] = dev->fifo->data[data_start_index++]; + aux_data->data[1] = dev->fifo->data[data_start_index++]; + aux_data->data[2] = dev->fifo->data[data_start_index++]; + aux_data->data[3] = dev->fifo->data[data_start_index++]; + aux_data->data[4] = dev->fifo->data[data_start_index++]; + aux_data->data[5] = dev->fifo->data[data_start_index++]; + aux_data->data[6] = dev->fifo->data[data_start_index++]; + aux_data->data[7] = dev->fifo->data[data_start_index++]; +} + +/*! + * @brief This API is used to parse the aux data from the + * FIFO data in header mode. + */ +static void extract_aux_header_mode(struct bmi160_aux_data *aux_data, uint8_t *aux_length, const struct bmi160_dev *dev) +{ + uint8_t frame_header = 0; + uint16_t data_index; + uint8_t aux_index = 0; + + for (data_index = dev->fifo->aux_byte_start_idx; data_index < dev->fifo->length;) + { + /* extracting Frame header */ + frame_header = (dev->fifo->data[data_index] & BMI160_FIFO_TAG_INTR_MASK); + + /*Index is moved to next byte where the data is starting*/ + data_index++; + switch (frame_header) + { + /* Aux frame */ + case BMI160_FIFO_HEAD_M: + case BMI160_FIFO_HEAD_M_A: + case BMI160_FIFO_HEAD_M_G: + case BMI160_FIFO_HEAD_M_G_A: + unpack_aux_frame(aux_data, &data_index, &aux_index, frame_header, dev); + break; + case BMI160_FIFO_HEAD_G: + move_next_frame(&data_index, BMI160_FIFO_G_LENGTH, dev); + break; + case BMI160_FIFO_HEAD_G_A: + move_next_frame(&data_index, BMI160_FIFO_GA_LENGTH, dev); + break; + case BMI160_FIFO_HEAD_A: + move_next_frame(&data_index, BMI160_FIFO_A_LENGTH, dev); + break; + + /* Sensor time frame */ + case BMI160_FIFO_HEAD_SENSOR_TIME: + unpack_sensortime_frame(&data_index, dev); + break; + + /* Skip frame */ + case BMI160_FIFO_HEAD_SKIP_FRAME: + unpack_skipped_frame(&data_index, dev); + break; + + /* Input config frame */ + case BMI160_FIFO_HEAD_INPUT_CONFIG: + move_next_frame(&data_index, 1, dev); + break; + case BMI160_FIFO_HEAD_OVER_READ: + + /* Update the data index as complete in case + * of over read */ + data_index = dev->fifo->length; + break; + default: + + /* Update the data index as complete in case of + * getting other headers like 0x00 */ + data_index = dev->fifo->length; + break; + } + if (*aux_length == aux_index) + { + /*Number of frames to read completed*/ + break; + } + } + + /* Update number of aux data read */ + *aux_length = aux_index; + + /* Update the aux frame index */ + dev->fifo->aux_byte_start_idx = data_index; +} + +/*! + * @brief This API checks the presence of non-valid frames in the read fifo data. + */ +static void check_frame_validity(uint16_t *data_index, const struct bmi160_dev *dev) +{ + if ((*data_index + 2) < dev->fifo->length) + { + /* Check if FIFO is empty */ + if ((dev->fifo->data[*data_index] == FIFO_CONFIG_MSB_CHECK) && + (dev->fifo->data[*data_index + 1] == FIFO_CONFIG_LSB_CHECK)) + { + /*Update the data index as complete*/ + *data_index = dev->fifo->length; + } + } +} + +/*! + * @brief This API is used to move the data index ahead of the + * current_frame_length parameter when unnecessary FIFO data appears while + * extracting the user specified data. + */ +static void move_next_frame(uint16_t *data_index, uint8_t current_frame_length, const struct bmi160_dev *dev) +{ + /*Partial read, then move the data index to last data*/ + if ((*data_index + current_frame_length) > dev->fifo->length) + { + /*Update the data index as complete*/ + *data_index = dev->fifo->length; + } + else + { + /*Move the data index to next frame*/ + *data_index = *data_index + current_frame_length; + } +} + +/*! + * @brief This API is used to parse and store the sensor time from the + * FIFO data in the structure instance dev. + */ +static void unpack_sensortime_frame(uint16_t *data_index, const struct bmi160_dev *dev) +{ + uint32_t sensor_time_byte3 = 0; + uint16_t sensor_time_byte2 = 0; + uint8_t sensor_time_byte1 = 0; + + /*Partial read, then move the data index to last data*/ + if ((*data_index + BMI160_SENSOR_TIME_LENGTH) > dev->fifo->length) + { + /*Update the data index as complete*/ + *data_index = dev->fifo->length; + } + else + { + sensor_time_byte3 = dev->fifo->data[(*data_index) + BMI160_SENSOR_TIME_MSB_BYTE] << 16; + sensor_time_byte2 = dev->fifo->data[(*data_index) + BMI160_SENSOR_TIME_XLSB_BYTE] << 8; + sensor_time_byte1 = dev->fifo->data[(*data_index)]; + + /* Sensor time */ + dev->fifo->sensor_time = (uint32_t)(sensor_time_byte3 | sensor_time_byte2 | sensor_time_byte1); + *data_index = (*data_index) + BMI160_SENSOR_TIME_LENGTH; + } +} + +/*! + * @brief This API is used to parse and store the skipped_frame_count from + * the FIFO data in the structure instance dev. + */ +static void unpack_skipped_frame(uint16_t *data_index, const struct bmi160_dev *dev) +{ + /*Partial read, then move the data index to last data*/ + if (*data_index >= dev->fifo->length) + { + /*Update the data index as complete*/ + *data_index = dev->fifo->length; + } + else + { + dev->fifo->skipped_frame_count = dev->fifo->data[*data_index]; + + /*Move the data index*/ + *data_index = (*data_index) + 1; + } +} + +/*! + * @brief This API is used to get the FOC status from the sensor + */ +static int8_t get_foc_status(uint8_t *foc_status, struct bmi160_dev const *dev) +{ + int8_t rslt; + uint8_t data; + + /* Read the FOC status from sensor */ + rslt = bmi160_get_regs(BMI160_STATUS_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + /* Get the foc_status bit */ + *foc_status = BMI160_GET_BITS(data, BMI160_FOC_STATUS); + } + + return rslt; +} + +/*! + * @brief This API is used to configure the offset enable bits in the sensor + */ +static int8_t configure_offset_enable(const struct bmi160_foc_conf *foc_conf, struct bmi160_dev const *dev) +{ + int8_t rslt; + uint8_t data; + + /* Null-pointer check */ + rslt = null_ptr_check(dev); + if (rslt != BMI160_OK) + { + rslt = BMI160_E_NULL_PTR; + } + else + { + /* Read the FOC config from the sensor */ + rslt = bmi160_get_regs(BMI160_OFFSET_CONF_ADDR, &data, 1, dev); + if (rslt == BMI160_OK) + { + /* Set the offset enable/disable for gyro */ + data = BMI160_SET_BITS(data, BMI160_GYRO_OFFSET_EN, foc_conf->gyro_off_en); + + /* Set the offset enable/disable for accel */ + data = BMI160_SET_BITS(data, BMI160_ACCEL_OFFSET_EN, foc_conf->acc_off_en); + + /* Set the offset config in the sensor */ + rslt = bmi160_set_regs(BMI160_OFFSET_CONF_ADDR, &data, 1, dev); + } + } + + return rslt; +} + +static int8_t trigger_foc(struct bmi160_offsets *offset, struct bmi160_dev const *dev) +{ + int8_t rslt; + uint8_t foc_status = BMI160_ENABLE; + uint8_t cmd = BMI160_START_FOC_CMD; + uint8_t timeout = 0; + uint8_t data_array[20]; + + /* Start the FOC process */ + rslt = bmi160_set_regs(BMI160_COMMAND_REG_ADDR, &cmd, 1, dev); + if (rslt == BMI160_OK) + { + /* Check the FOC status*/ + rslt = get_foc_status(&foc_status, dev); + + if ((rslt != BMI160_OK) || (foc_status != BMI160_ENABLE)) + { + while ((foc_status != BMI160_ENABLE) && (timeout < 11)) + { + /* Maximum time of 250ms is given in 10 + * steps of 25ms each - 250ms refer datasheet 2.9.1 */ + dev->delay_ms(25); + + /* Check the FOC status*/ + rslt = get_foc_status(&foc_status, dev); + timeout++; + } + + if ((rslt == BMI160_OK) && (foc_status == BMI160_ENABLE)) + { + /* Get offset values from sensor */ + rslt = bmi160_get_offsets(offset, dev); + } + else + { + /* FOC failure case */ + rslt = BMI160_E_FOC_FAILURE; + } + } + + if (rslt == BMI160_OK) + { + /* Read registers 0x04-0x17 */ + rslt = bmi160_get_regs(BMI160_GYRO_DATA_ADDR, data_array, 20, dev); + } + } + + return rslt; +} diff --git a/airmouse/tracking/imu/bmi160.h b/airmouse/lib/bmi160-api/bmi160.h similarity index 89% rename from airmouse/tracking/imu/bmi160.h rename to airmouse/lib/bmi160-api/bmi160.h index d4d98094cf3..d30978f22b9 100644 --- a/airmouse/tracking/imu/bmi160.h +++ b/airmouse/lib/bmi160-api/bmi160.h @@ -1,992 +1,969 @@ -/** -* Copyright (c) 2021 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 bmi160.h -* @date 2021-10-05 -* @version v3.9.2 -* -*/ - -/*! - * @defgroup bmi160 BMI160 - */ - -#ifndef BMI160_H_ -#define BMI160_H_ - -/*************************** C++ guard macro *****************************/ -#ifdef __cplusplus -extern "C" { -#endif - -#include "bmi160_defs.h" -#ifdef __KERNEL__ -#include -#else -#include -#include -#include -#endif - -/*********************** User function prototypes ************************/ - -/** - * \ingroup bmi160 - * \defgroup bmi160ApiInit Initialization - * @brief Initialize the sensor and device structure - */ - -/*! - * \ingroup bmi160ApiInit - * \page bmi160_api_bmi160_init bmi160_init - * \code - * int8_t bmi160_init(struct bmi160_dev *dev); - * \endcode - * @details This API is the entry point for sensor.It performs - * the selection of I2C/SPI read mechanism according to the - * selected interface and reads the chip-id of bmi160 sensor. - * - * @param[in,out] dev : Structure instance of bmi160_dev - * @note : Refer user guide for detailed info. - * - * @return Result of API execution status - * @retval Zero Success - * @retval Negative Error - */ -int8_t bmi160_init(struct bmi160_dev* dev); - -/** - * \ingroup bmi160 - * \defgroup bmi160ApiRegs Registers - * @brief Read data from the given register address of sensor - */ - -/*! - * \ingroup bmi160ApiRegs - * \page bmi160_api_bmi160_get_regs bmi160_get_regs - * \code - * int8_t bmi160_get_regs(uint8_t reg_addr, uint8_t *data, uint16_t len, const struct bmi160_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] 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 bmi160_dev. - * - * @note For most of the registers auto address increment applies, with the - * exception of a few special registers, which trap the address. For e.g., - * Register address - 0x24(BMI160_FIFO_DATA_ADDR) - * - * @return Result of API execution status - * @retval Zero Success - * @retval Negative Error - */ -int8_t - bmi160_get_regs(uint8_t reg_addr, uint8_t* data, uint16_t len, const struct bmi160_dev* dev); - -/*! - * \ingroup bmi160ApiRegs - * \page bmi160_api_bmi160_set_regs bmi160_set_regs - * \code - * int8_t bmi160_set_regs(uint8_t reg_addr, uint8_t *data, uint16_t len, const struct bmi160_dev *dev); - * \endcode - * @details This API writes the given data to the register address - * of sensor. - * - * @param[in] reg_addr : Register address from where the data to be written. - * @param[in] data : Pointer to data buffer which is to be written - * in the sensor. - * @param[in] len : No of bytes of data to write.. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval Zero Success - * @retval Negative Error - */ -int8_t - bmi160_set_regs(uint8_t reg_addr, uint8_t* data, uint16_t len, const struct bmi160_dev* dev); - -/** - * \ingroup bmi160 - * \defgroup bmi160ApiSoftreset Soft reset - * @brief Perform soft reset of the sensor - */ - -/*! - * \ingroup bmi160ApiSoftreset - * \page bmi160_api_bmi160_soft_reset bmi160_soft_reset - * \code - * int8_t bmi160_soft_reset(struct bmi160_dev *dev); - * \endcode - * @details This API resets and restarts the device. - * All register values are overwritten with default parameters. - * - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval Zero Success - * @retval Negative Error - */ -int8_t bmi160_soft_reset(struct bmi160_dev* dev); - -/** - * \ingroup bmi160 - * \defgroup bmi160ApiConfig Configuration - * @brief Configuration of the sensor - */ - -/*! - * \ingroup bmi160ApiConfig - * \page bmi160_api_bmi160_set_sens_conf bmi160_set_sens_conf - * \code - * int8_t bmi160_set_sens_conf(struct bmi160_dev *dev); - * \endcode - * @details This API configures the power mode, range and bandwidth - * of sensor. - * - * @param[in] dev : Structure instance of bmi160_dev. - * @note : Refer user guide for detailed info. - * - * @return Result of API execution status - * @retval Zero Success - * @retval Negative Error - */ -int8_t bmi160_set_sens_conf(struct bmi160_dev* dev); - -/*! - * \ingroup bmi160ApiConfig - * \page bmi160_api_bmi160_get_sens_conf bmi160_get_sens_conf - * \code - * int8_t bmi160_get_sens_conf(struct bmi160_dev *dev); - * \endcode - * @details This API gets accel and gyro configurations. - * - * @param[out] dev : Structure instance of bmi160_dev. - * @note : Refer user guide for detailed info. - * - * @return Result of API execution status - * @retval Zero Success - * @retval Negative Error - */ -int8_t bmi160_get_sens_conf(struct bmi160_dev* dev); - -/** - * \ingroup bmi160 - * \defgroup bmi160ApiPowermode Power mode - * @brief Set / Get power mode of the sensor - */ - -/*! - * \ingroup bmi160ApiPowermode - * \page bmi160_api_bmi160_set_power_mode bmi160_set_power_mode - * \code - * int8_t bmi160_set_power_mode(struct bmi160_dev *dev); - * \endcode - * @details This API sets the power mode of the sensor. - * - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval Zero Success - * @retval Negative Error - */ -int8_t bmi160_set_power_mode(struct bmi160_dev* dev); - -/*! - * \ingroup bmi160ApiPowermode - * \page bmi160_api_bmi160_get_power_mode bmi160_get_power_mode - * \code - * int8_t bmi160_get_power_mode(struct bmi160_dev *dev); - * \endcode - * @details This API gets the power mode of the sensor. - * - * @param[in] dev : Structure instance of bmi160_dev - * - * @return Result of API execution status - * @retval Zero Success - * @retval Negative Error - */ -int8_t bmi160_get_power_mode(struct bmi160_dev* dev); - -/** - * \ingroup bmi160 - * \defgroup bmi160ApiData Sensor Data - * @brief Read sensor data - */ - -/*! - * \ingroup bmi160ApiData - * \page bmi160_api_bmi160_get_sensor_data bmi160_get_sensor_data - * \code - * int8_t bmi160_get_sensor_data(uint8_t select_sensor, - * struct bmi160_sensor_data *accel, - * struct bmi160_sensor_data *gyro, - * const struct bmi160_dev *dev); - * - * \endcode - * @details This API reads sensor data, stores it in - * the bmi160_sensor_data structure pointer passed by the user. - * The user can ask for accel data ,gyro data or both sensor - * data using bmi160_select_sensor enum - * - * @param[in] select_sensor : enum to choose accel,gyro or both sensor data - * @param[out] accel : Structure pointer to store accel data - * @param[out] gyro : Structure pointer to store gyro data - * @param[in] dev : Structure instance of bmi160_dev. - * @note : Refer user guide for detailed info. - * - * @return Result of API execution status - * @retval Zero Success - * @retval Negative Error - */ -int8_t bmi160_get_sensor_data( - uint8_t select_sensor, - struct bmi160_sensor_data* accel, - struct bmi160_sensor_data* gyro, - const struct bmi160_dev* dev); - -/** - * \ingroup bmi160 - * \defgroup bmi160ApiInt Interrupt configuration - * @brief Set interrupt configuration of the sensor - */ - -/*! - * \ingroup bmi160ApiInt - * \page bmi160_api_bmi160_set_int_config bmi160_set_int_config - * \code - * int8_t bmi160_set_int_config(struct bmi160_int_settg *int_config, struct bmi160_dev *dev); - * \endcode - * @details This API configures the necessary interrupt based on - * the user settings in the bmi160_int_settg structure instance. - * - * @param[in] int_config : Structure instance of bmi160_int_settg. - * @param[in] dev : Structure instance of bmi160_dev. - * @note : Refer user guide for detailed info. - * - * @return Result of API execution status - * @retval Zero Success - * @retval Negative Error - */ -int8_t bmi160_set_int_config(struct bmi160_int_settg* int_config, struct bmi160_dev* dev); - -/** - * \ingroup bmi160 - * \defgroup bmi160ApiStepC Step counter - * @brief Step counter operations - */ - -/*! - * \ingroup bmi160ApiStepC - * \page bmi160_api_bmi160_set_step_counter bmi160_set_step_counter - * \code - * int8_t bmi160_set_step_counter(uint8_t step_cnt_enable, const struct bmi160_dev *dev); - * \endcode - * @details This API enables the step counter feature. - * - * @param[in] step_cnt_enable : value to enable or disable - * @param[in] dev : Structure instance of bmi160_dev. - * @note : Refer user guide for detailed info. - * - * @return Result of API execution status - * @retval Zero Success - * @retval Negative Error - */ -int8_t bmi160_set_step_counter(uint8_t step_cnt_enable, const struct bmi160_dev* dev); - -/*! - * \ingroup bmi160ApiStepC - * \page bmi160_api_bmi160_read_step_counter bmi160_read_step_counter - * \code - * int8_t bmi160_read_step_counter(uint16_t *step_val, const struct bmi160_dev *dev); - * \endcode - * @details This API reads the step counter value. - * - * @param[in] step_val : Pointer to store the step counter value. - * @param[in] dev : Structure instance of bmi160_dev. - * @note : Refer user guide for detailed info. - * - * @return Result of API execution status - * @retval Zero Success - * @retval Negative Error - */ -int8_t bmi160_read_step_counter(uint16_t* step_val, const struct bmi160_dev* dev); - -/** - * \ingroup bmi160 - * \defgroup bmi160ApiAux Auxiliary sensor - * @brief Auxiliary sensor operations - */ - -/*! - * \ingroup bmi160ApiAux - * \page bmi160_api_bmi160_aux_read bmi160_aux_read - * \code - * int8_t bmi160_aux_read(uint8_t reg_addr, uint8_t *aux_data, uint16_t len, const struct bmi160_dev *dev); - * \endcode - * @details This API reads the mention no of byte of data from the given - * register address of auxiliary sensor. - * - * @param[in] reg_addr : Address of register to read. - * @param[in] aux_data : Pointer to store the read data. - * @param[in] len : No of bytes to read. - * @param[in] dev : Structure instance of bmi160_dev. - * @note : Refer user guide for detailed info. - * - * @return Result of API execution status - * @retval Zero Success - * @retval Negative Error - */ -int8_t bmi160_aux_read( - uint8_t reg_addr, - uint8_t* aux_data, - uint16_t len, - const struct bmi160_dev* dev); - -/*! - * \ingroup bmi160ApiAux - * \page bmi160_api_bmi160_aux_write bmi160_aux_write - * \code - * int8_t bmi160_aux_write(uint8_t reg_addr, uint8_t *aux_data, uint16_t len, const struct bmi160_dev *dev); - * \endcode - * @details This API writes the mention no of byte of data to the given - * register address of auxiliary sensor. - * - * @param[in] reg_addr : Address of register to write. - * @param[in] aux_data : Pointer to write data. - * @param[in] len : No of bytes to write. - * @param[in] dev : Structure instance of bmi160_dev. - * @note : Refer user guide for detailed info. - * - * @return Result of API execution status - * @retval Zero Success - * @retval Negative Error - */ -int8_t bmi160_aux_write( - uint8_t reg_addr, - uint8_t* aux_data, - uint16_t len, - const struct bmi160_dev* dev); - -/*! - * \ingroup bmi160ApiAux - * \page bmi160_api_bmi160_aux_init bmi160_aux_init - * \code - * int8_t bmi160_aux_init(const struct bmi160_dev *dev); - * \endcode - * @details This API initialize the auxiliary sensor - * in order to access it. - * - * @param[in] dev : Structure instance of bmi160_dev. - * @note : Refer user guide for detailed info. - * - * @return Result of API execution status - * @retval Zero Success - * @retval Negative Error - */ -int8_t bmi160_aux_init(const struct bmi160_dev* dev); - -/*! - * \ingroup bmi160ApiAux - * \page bmi160_api_bmi160_set_aux_auto_mode bmi160_set_aux_auto_mode - * \code - * int8_t bmi160_set_aux_auto_mode(uint8_t *data_addr, struct bmi160_dev *dev); - * \endcode - * @details This API is used to setup the auxiliary sensor of bmi160 in auto mode - * Thus enabling the auto update of 8 bytes of data from auxiliary sensor - * to BMI160 register address 0x04 to 0x0B - * - * @param[in] data_addr : Starting address of aux. sensor's data register - * (BMI160 registers 0x04 to 0x0B will be updated - * with 8 bytes of data from auxiliary sensor - * starting from this register address.) - * @param[in] dev : Structure instance of bmi160_dev. - * - * @note : Set the value of auxiliary polling rate by setting - * dev->aux_cfg.aux_odr to the required value from the table - * before calling this API - * - *@verbatim - * dev->aux_cfg.aux_odr | Auxiliary ODR (Hz) - * -----------------------|----------------------- - * BMI160_AUX_ODR_0_78HZ | 25/32 - * BMI160_AUX_ODR_1_56HZ | 25/16 - * BMI160_AUX_ODR_3_12HZ | 25/8 - * BMI160_AUX_ODR_6_25HZ | 25/4 - * BMI160_AUX_ODR_12_5HZ | 25/2 - * BMI160_AUX_ODR_25HZ | 25 - * BMI160_AUX_ODR_50HZ | 50 - * BMI160_AUX_ODR_100HZ | 100 - * BMI160_AUX_ODR_200HZ | 200 - * BMI160_AUX_ODR_400HZ | 400 - * BMI160_AUX_ODR_800HZ | 800 - *@endverbatim - * - * @note : Other values of dev->aux_cfg.aux_odr are reserved and not for use - * - * @return Result of API execution status - * @retval Zero Success - * @retval Negative Error - */ -int8_t bmi160_set_aux_auto_mode(uint8_t* data_addr, struct bmi160_dev* dev); - -/*! - * \ingroup bmi160ApiAux - * \page bmi160_api_bmi160_config_aux_mode bmi160_config_aux_mode - * \code - * int8_t bmi160_config_aux_mode(const struct bmi160_dev *dev); - * \endcode - * @details This API configures the 0x4C register and settings like - * Auxiliary sensor manual enable/ disable and aux burst read length. - * - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval Zero Success - * @retval Negative Error - */ -int8_t bmi160_config_aux_mode(const struct bmi160_dev* dev); - -/*! - * \ingroup bmi160ApiAux - * \page bmi160_api_bmi160_read_aux_data_auto_mode bmi160_read_aux_data_auto_mode - * \code - * int8_t bmi160_read_aux_data_auto_mode(uint8_t *aux_data, const struct bmi160_dev *dev); - * \endcode - * @details This API is used to read the raw uncompensated auxiliary sensor - * data of 8 bytes from BMI160 register address 0x04 to 0x0B - * - * @param[in] aux_data : Pointer to user array of length 8 bytes - * Ensure that the aux_data array is of - * length 8 bytes - * @param[in] dev : Structure instance of bmi160_dev - * - * @retval zero -> Success / -ve value -> Error - * @retval Zero Success - * @retval Negative Error - */ -int8_t bmi160_read_aux_data_auto_mode(uint8_t* aux_data, const struct bmi160_dev* dev); - -/** - * \ingroup bmi160 - * \defgroup bmi160ApiSelfTest Self test - * @brief Perform self test of the sensor - */ - -/*! - * \ingroup bmi160ApiSelfTest - * \page bmi160_api_bmi160_perform_self_test bmi160_perform_self_test - * \code - * int8_t bmi160_perform_self_test(uint8_t select_sensor, struct bmi160_dev *dev); - * \endcode - * @details This is used to perform self test of accel/gyro of the BMI160 sensor - * - * @param[in] select_sensor : enum to choose accel or gyro for self test - * @param[in] dev : Structure instance of bmi160_dev - * - * @note self test can be performed either for accel/gyro at any instant. - * - *@verbatim - * value of select_sensor | Inference - *----------------------------------|-------------------------------- - * BMI160_ACCEL_ONLY | Accel self test enabled - * BMI160_GYRO_ONLY | Gyro self test enabled - * BMI160_BOTH_ACCEL_AND_GYRO | NOT TO BE USED - *@endverbatim - * - * @note The return value of this API gives us the result of self test. - * - * @note Performing self test does soft reset of the sensor, User can - * set the desired settings after performing the self test. - * - * @return Result of API execution status - * @retval BMI160_OK Self test success - * @retval BMI160_W_GYRO_SELF_TEST_FAIL Gyro self test fail - * @retval BMI160_W_ACCEl_SELF_TEST_FAIL Accel self test fail - */ -int8_t bmi160_perform_self_test(uint8_t select_sensor, struct bmi160_dev* dev); - -/** - * \ingroup bmi160 - * \defgroup bmi160ApiFIFO FIFO - * @brief FIFO operations of the sensor - */ - -/*! - * \ingroup bmi160ApiFIFO - * \page bmi160_api_bmi160_get_fifo_data bmi160_get_fifo_data - * \code - * int8_t bmi160_get_fifo_data(struct bmi160_dev const *dev); - * \endcode - * @details This API reads data from the fifo buffer. - * - * @note User has to allocate the FIFO buffer along with - * corresponding fifo length from his side before calling this API - * as mentioned in the readme.md - * - * @note User must specify the number of bytes to read from the FIFO in - * dev->fifo->length , It will be updated by the number of bytes actually - * read from FIFO after calling this API - * - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval Zero Success - * @retval Negative Error - */ -int8_t bmi160_get_fifo_data(struct bmi160_dev const* dev); - -/*! - * \ingroup bmi160ApiFIFO - * \page bmi160_api_bmi160_set_fifo_flush bmi160_set_fifo_flush - * \code - * int8_t bmi160_set_fifo_flush(const struct bmi160_dev *dev); - * \endcode - * @details This API writes fifo_flush command to command register.This - * action clears all data in the Fifo without changing fifo configuration - * settings. - * - * @param[in] dev : Structure instance of bmi160_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -int8_t bmi160_set_fifo_flush(const struct bmi160_dev* dev); - -/*! - * \ingroup bmi160ApiFIFO - * \page bmi160_api_bmi160_set_fifo_config bmi160_set_fifo_config - * \code - * int8_t bmi160_set_fifo_config(uint8_t config, uint8_t enable, struct bmi160_dev const *dev); - * \endcode - * @details This API sets the FIFO configuration in the sensor. - * - * @param[in] config : variable used to specify the FIFO - * configurations which are to be enabled or disabled in the sensor. - * - * @note : User can set either set one or more or all FIFO configurations - * by ORing the below mentioned macros. - * - *@verbatim - * config | Value - * ------------------------|--------------------------- - * BMI160_FIFO_TIME | 0x02 - * BMI160_FIFO_TAG_INT2 | 0x04 - * BMI160_FIFO_TAG_INT1 | 0x08 - * BMI160_FIFO_HEADER | 0x10 - * BMI160_FIFO_AUX | 0x20 - * BMI160_FIFO_ACCEL | 0x40 - * BMI160_FIFO_GYRO | 0x80 - *@endverbatim - * - * @param[in] enable : Parameter used to enable or disable the above - * FIFO configuration - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return status of bus communication result - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -int8_t bmi160_set_fifo_config(uint8_t config, uint8_t enable, struct bmi160_dev const* dev); - -/*! - * \ingroup bmi160ApiFIFO - * \page bmi160_api_bmi160_set_fifo_down bmi160_set_fifo_down - * \code - * int8_t bmi160_set_fifo_down(uint8_t fifo_down, const struct bmi160_dev *dev); - * \endcode - * @details This API is used to configure the down sampling ratios of - * the accel and gyro data for FIFO.Also, it configures filtered or - * pre-filtered data for the fifo for accel and gyro. - * - * @param[in] fifo_down : variable used to specify the FIFO down - * configurations which are to be enabled or disabled in the sensor. - * - * @note The user must select one among the following macros to - * select down-sampling ratio for accel - * - *@verbatim - * config | Value - * -------------------------------------|--------------------------- - * BMI160_ACCEL_FIFO_DOWN_ZERO | 0x00 - * BMI160_ACCEL_FIFO_DOWN_ONE | 0x10 - * BMI160_ACCEL_FIFO_DOWN_TWO | 0x20 - * BMI160_ACCEL_FIFO_DOWN_THREE | 0x30 - * BMI160_ACCEL_FIFO_DOWN_FOUR | 0x40 - * BMI160_ACCEL_FIFO_DOWN_FIVE | 0x50 - * BMI160_ACCEL_FIFO_DOWN_SIX | 0x60 - * BMI160_ACCEL_FIFO_DOWN_SEVEN | 0x70 - *@endverbatim - * - * @note The user must select one among the following macros to - * select down-sampling ratio for gyro - * - *@verbatim - * config | Value - * -------------------------------------|--------------------------- - * BMI160_GYRO_FIFO_DOWN_ZERO | 0x00 - * BMI160_GYRO_FIFO_DOWN_ONE | 0x01 - * BMI160_GYRO_FIFO_DOWN_TWO | 0x02 - * BMI160_GYRO_FIFO_DOWN_THREE | 0x03 - * BMI160_GYRO_FIFO_DOWN_FOUR | 0x04 - * BMI160_GYRO_FIFO_DOWN_FIVE | 0x05 - * BMI160_GYRO_FIFO_DOWN_SIX | 0x06 - * BMI160_GYRO_FIFO_DOWN_SEVEN | 0x07 - *@endverbatim - * - * @note The user can enable filtered accel data by the following macro - * - *@verbatim - * config | Value - * -------------------------------------|--------------------------- - * BMI160_ACCEL_FIFO_FILT_EN | 0x80 - *@endverbatim - * - * @note The user can enable filtered gyro data by the following macro - * - *@verbatim - * config | Value - * -------------------------------------|--------------------------- - * BMI160_GYRO_FIFO_FILT_EN | 0x08 - *@endverbatim - * - * @note : By ORing the above mentioned macros, the user can select - * the required FIFO down config settings - * - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return status of bus communication result - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -int8_t bmi160_set_fifo_down(uint8_t fifo_down, const struct bmi160_dev* dev); - -/*! - * \ingroup bmi160ApiFIFO - * \page bmi160_api_bmi160_set_fifo_wm bmi160_set_fifo_wm - * \code - * int8_t bmi160_set_fifo_wm(uint8_t fifo_wm, const struct bmi160_dev *dev); - * \endcode - * @details This API sets the FIFO watermark level in the sensor. - * - * @note The FIFO watermark is issued when the FIFO fill level is - * equal or above the watermark level and units of watermark is 4 bytes. - * - * @param[in] fifo_wm : Variable used to set the FIFO water mark level - * @param[in] dev : Structure instance of bmi160_dev - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -int8_t bmi160_set_fifo_wm(uint8_t fifo_wm, const struct bmi160_dev* dev); - -/*! - * \ingroup bmi160ApiFIFO - * \page bmi160_api_bmi160_extract_accel bmi160_extract_accel - * \code - * int8_t bmi160_extract_accel(struct bmi160_sensor_data *accel_data, uint8_t *accel_length, struct bmi160_dev const - **dev); - * \endcode - * @details This API parses and extracts the accelerometer frames from - * FIFO data read by the "bmi160_get_fifo_data" API and stores it in - * the "accel_data" structure instance. - * - * @note The bmi160_extract_accel API should be called only after - * reading the FIFO data by calling the bmi160_get_fifo_data() API. - * - * @param[out] accel_data : Structure instance of bmi160_sensor_data - * where the accelerometer data in FIFO is stored. - * @param[in,out] accel_length : Number of valid accelerometer frames - * (x,y,z axes data) read out from fifo. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @note accel_length is updated with the number of valid accelerometer - * frames extracted from fifo (1 accel frame = 6 bytes) at the end of - * execution of this API. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -int8_t bmi160_extract_accel( - struct bmi160_sensor_data* accel_data, - uint8_t* accel_length, - struct bmi160_dev const* dev); - -/*! - * \ingroup bmi160ApiFIFO - * \page bmi160_api_bmi160_extract_gyro bmi160_extract_gyro - * \code - * int8_t bmi160_extract_gyro(struct bmi160_sensor_data *gyro_data, uint8_t *gyro_length, struct bmi160_dev const *dev); - * \endcode - * @details This API parses and extracts the gyro frames from - * FIFO data read by the "bmi160_get_fifo_data" API and stores it in - * the "gyro_data" structure instance. - * - * @note The bmi160_extract_gyro API should be called only after - * reading the FIFO data by calling the bmi160_get_fifo_data() API. - * - * @param[out] gyro_data : Structure instance of bmi160_sensor_data - * where the gyro data in FIFO is stored. - * @param[in,out] gyro_length : Number of valid gyro frames - * (x,y,z axes data) read out from fifo. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @note gyro_length is updated with the number of valid gyro - * frames extracted from fifo (1 gyro frame = 6 bytes) at the end of - * execution of this API. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -int8_t bmi160_extract_gyro( - struct bmi160_sensor_data* gyro_data, - uint8_t* gyro_length, - struct bmi160_dev const* dev); - -/*! - * \ingroup bmi160ApiFIFO - * \page bmi160_api_bmi160_extract_aux bmi160_extract_aux - * \code - * int8_t bmi160_extract_aux(struct bmi160_aux_data *aux_data, uint8_t *aux_len, struct bmi160_dev const *dev); - * \endcode - * @details This API parses and extracts the aux frames from - * FIFO data read by the "bmi160_get_fifo_data" API and stores it in - * the bmi160_aux_data structure instance. - * - * @note The bmi160_extract_aux API should be called only after - * reading the FIFO data by calling the bmi160_get_fifo_data() API. - * - * @param[out] aux_data : Structure instance of bmi160_aux_data - * where the aux data in FIFO is stored. - * @param[in,out] aux_len : Number of valid aux frames (8bytes) - * read out from FIFO. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @note aux_len is updated with the number of valid aux - * frames extracted from fifo (1 aux frame = 8 bytes) at the end of - * execution of this API. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - * - */ -int8_t bmi160_extract_aux( - struct bmi160_aux_data* aux_data, - uint8_t* aux_len, - struct bmi160_dev const* dev); - -/** - * \ingroup bmi160 - * \defgroup bmi160ApiFOC FOC - * @brief Start FOC of accel and gyro sensors - */ - -/*! - * \ingroup bmi160ApiFOC - * \page bmi160_api_bmi160_start_foc bmi160_start_foc - * \code - * int8_t bmi160_start_foc(const struct bmi160_foc_conf *foc_conf, - * \endcode - * @details This API starts the FOC of accel and gyro - * - * @note FOC should not be used in low-power mode of sensor - * - * @note Accel FOC targets values of +1g , 0g , -1g - * Gyro FOC always targets value of 0 dps - * - * @param[in] foc_conf : Structure instance of bmi160_foc_conf which - * has the FOC configuration - * @param[in,out] offset : Structure instance to store Offset - * values read from sensor - * @param[in] dev : Structure instance of bmi160_dev. - * - * @note Pre-requisites for triggering FOC in accel , Set the following, - * Enable the acc_off_en - * Ex : foc_conf.acc_off_en = BMI160_ENABLE; - * - * Set the desired target values of FOC to each axes (x,y,z) by using the - * following macros - * - BMI160_FOC_ACCEL_DISABLED - * - BMI160_FOC_ACCEL_POSITIVE_G - * - BMI160_FOC_ACCEL_NEGATIVE_G - * - BMI160_FOC_ACCEL_0G - * - * Ex : foc_conf.foc_acc_x = BMI160_FOC_ACCEL_0G; - * foc_conf.foc_acc_y = BMI160_FOC_ACCEL_0G; - * foc_conf.foc_acc_z = BMI160_FOC_ACCEL_POSITIVE_G; - * - * @note Pre-requisites for triggering FOC in gyro , - * Set the following parameters, - * - * Ex : foc_conf.foc_gyr_en = BMI160_ENABLE; - * foc_conf.gyro_off_en = BMI160_ENABLE; - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -int8_t bmi160_start_foc( - const struct bmi160_foc_conf* foc_conf, - struct bmi160_offsets* offset, - struct bmi160_dev const* dev); - -/** - * \ingroup bmi160 - * \defgroup bmi160ApiOffsets Offsets - * @brief Set / Get offset values of accel and gyro sensors - */ - -/*! - * \ingroup bmi160ApiOffsets - * \page bmi160_api_bmi160_get_offsets bmi160_get_offsets - * \code - * int8_t bmi160_get_offsets(struct bmi160_offsets *offset, const struct bmi160_dev *dev); - * \endcode - * @details This API reads and stores the offset values of accel and gyro - * - * @param[in,out] offset : Structure instance of bmi160_offsets in which - * the offset values are read and stored - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -int8_t bmi160_get_offsets(struct bmi160_offsets* offset, const struct bmi160_dev* dev); - -/*! - * \ingroup bmi160ApiOffsets - * \page bmi160_api_bmi160_set_offsets bmi160_set_offsets - * \code - * int8_t bmi160_set_offsets(const struct bmi160_foc_conf *foc_conf, - * const struct bmi160_offsets *offset, - * struct bmi160_dev const *dev); - * \endcode - * @details This API writes the offset values of accel and gyro to - * the sensor but these values will be reset on POR or soft reset. - * - * @param[in] foc_conf : Structure instance of bmi160_foc_conf which - * has the FOC configuration - * @param[in] offset : Structure instance in which user updates offset - * values which are to be written in the sensor - * @param[in] dev : Structure instance of bmi160_dev. - * - * @note Offsets can be set by user like offset->off_acc_x = 10; - * where 1LSB = 3.9mg and for gyro 1LSB = 0.061degrees/second - * - * @note BMI160 offset values for xyz axes of accel should be within range of - * BMI160_ACCEL_MIN_OFFSET (-128) to BMI160_ACCEL_MAX_OFFSET (127) - * - * @note BMI160 offset values for xyz axes of gyro should be within range of - * BMI160_GYRO_MIN_OFFSET (-512) to BMI160_GYRO_MAX_OFFSET (511) - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -int8_t bmi160_set_offsets( - const struct bmi160_foc_conf* foc_conf, - const struct bmi160_offsets* offset, - struct bmi160_dev const* dev); - -/** - * \ingroup bmi160 - * \defgroup bmi160ApiNVM NVM - * @brief Write image registers values to NVM - */ - -/*! - * \ingroup bmi160ApiNVM - * \page bmi160_api_bmi160_update_nvm bmi160_update_nvm - * \code - * int8_t bmi160_update_nvm(struct bmi160_dev const *dev); - * \endcode - * @details This API writes the image registers values to NVM which is - * stored even after POR or soft reset - * - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -int8_t bmi160_update_nvm(struct bmi160_dev const* dev); - -/** - * \ingroup bmi160 - * \defgroup bmi160ApiInts Interrupt status - * @brief Read interrupt status from the sensor - */ - -/*! - * \ingroup bmi160ApiInts - * \page bmi160_api_bmi160_get_int_status bmi160_get_int_status - * \code - * int8_t bmi160_get_int_status(enum bmi160_int_status_sel int_status_sel, - * union bmi160_int_status *int_status, - * struct bmi160_dev const *dev); - * \endcode - * @details This API gets the interrupt status from the sensor. - * - * @param[in] int_status_sel : Enum variable to select either individual or all the - * interrupt status bits. - * @param[in] int_status : pointer variable to get the interrupt status - * from the sensor. - * param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval 0 -> Success - * @retval Any non zero value -> Fail - */ -int8_t bmi160_get_int_status( - enum bmi160_int_status_sel int_status_sel, - union bmi160_int_status* int_status, - struct bmi160_dev const* dev); - -/*************************** C++ guard macro *****************************/ -#ifdef __cplusplus -} -#endif - -#endif /* BMI160_H_ */ +/** +* Copyright (c) 2021 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 bmi160.h +* @date 2021-10-05 +* @version v3.9.2 +* +*/ + +/*! + * @defgroup bmi160 BMI160 + */ + +#ifndef BMI160_H_ +#define BMI160_H_ + +/*************************** C++ guard macro *****************************/ +#ifdef __cplusplus +extern "C" { +#endif + +#include "bmi160_defs.h" +#ifdef __KERNEL__ +#include +#else +#include +#include +#include +#endif + +/*********************** User function prototypes ************************/ + +/** + * \ingroup bmi160 + * \defgroup bmi160ApiInit Initialization + * @brief Initialize the sensor and device structure + */ + +/*! + * \ingroup bmi160ApiInit + * \page bmi160_api_bmi160_init bmi160_init + * \code + * int8_t bmi160_init(struct bmi160_dev *dev); + * \endcode + * @details This API is the entry point for sensor.It performs + * the selection of I2C/SPI read mechanism according to the + * selected interface and reads the chip-id of bmi160 sensor. + * + * @param[in,out] dev : Structure instance of bmi160_dev + * @note : Refer user guide for detailed info. + * + * @return Result of API execution status + * @retval Zero Success + * @retval Negative Error + */ +int8_t bmi160_init(struct bmi160_dev *dev); + +/** + * \ingroup bmi160 + * \defgroup bmi160ApiRegs Registers + * @brief Read data from the given register address of sensor + */ + +/*! + * \ingroup bmi160ApiRegs + * \page bmi160_api_bmi160_get_regs bmi160_get_regs + * \code + * int8_t bmi160_get_regs(uint8_t reg_addr, uint8_t *data, uint16_t len, const struct bmi160_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] 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 bmi160_dev. + * + * @note For most of the registers auto address increment applies, with the + * exception of a few special registers, which trap the address. For e.g., + * Register address - 0x24(BMI160_FIFO_DATA_ADDR) + * + * @return Result of API execution status + * @retval Zero Success + * @retval Negative Error + */ +int8_t bmi160_get_regs(uint8_t reg_addr, uint8_t *data, uint16_t len, const struct bmi160_dev *dev); + +/*! + * \ingroup bmi160ApiRegs + * \page bmi160_api_bmi160_set_regs bmi160_set_regs + * \code + * int8_t bmi160_set_regs(uint8_t reg_addr, uint8_t *data, uint16_t len, const struct bmi160_dev *dev); + * \endcode + * @details This API writes the given data to the register address + * of sensor. + * + * @param[in] reg_addr : Register address from where the data to be written. + * @param[in] data : Pointer to data buffer which is to be written + * in the sensor. + * @param[in] len : No of bytes of data to write.. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval Zero Success + * @retval Negative Error + */ +int8_t bmi160_set_regs(uint8_t reg_addr, uint8_t *data, uint16_t len, const struct bmi160_dev *dev); + +/** + * \ingroup bmi160 + * \defgroup bmi160ApiSoftreset Soft reset + * @brief Perform soft reset of the sensor + */ + +/*! + * \ingroup bmi160ApiSoftreset + * \page bmi160_api_bmi160_soft_reset bmi160_soft_reset + * \code + * int8_t bmi160_soft_reset(struct bmi160_dev *dev); + * \endcode + * @details This API resets and restarts the device. + * All register values are overwritten with default parameters. + * + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval Zero Success + * @retval Negative Error + */ +int8_t bmi160_soft_reset(struct bmi160_dev *dev); + +/** + * \ingroup bmi160 + * \defgroup bmi160ApiConfig Configuration + * @brief Configuration of the sensor + */ + +/*! + * \ingroup bmi160ApiConfig + * \page bmi160_api_bmi160_set_sens_conf bmi160_set_sens_conf + * \code + * int8_t bmi160_set_sens_conf(struct bmi160_dev *dev); + * \endcode + * @details This API configures the power mode, range and bandwidth + * of sensor. + * + * @param[in] dev : Structure instance of bmi160_dev. + * @note : Refer user guide for detailed info. + * + * @return Result of API execution status + * @retval Zero Success + * @retval Negative Error + */ +int8_t bmi160_set_sens_conf(struct bmi160_dev *dev); + +/*! + * \ingroup bmi160ApiConfig + * \page bmi160_api_bmi160_get_sens_conf bmi160_get_sens_conf + * \code + * int8_t bmi160_get_sens_conf(struct bmi160_dev *dev); + * \endcode + * @details This API gets accel and gyro configurations. + * + * @param[out] dev : Structure instance of bmi160_dev. + * @note : Refer user guide for detailed info. + * + * @return Result of API execution status + * @retval Zero Success + * @retval Negative Error + */ +int8_t bmi160_get_sens_conf(struct bmi160_dev *dev); + +/** + * \ingroup bmi160 + * \defgroup bmi160ApiPowermode Power mode + * @brief Set / Get power mode of the sensor + */ + +/*! + * \ingroup bmi160ApiPowermode + * \page bmi160_api_bmi160_set_power_mode bmi160_set_power_mode + * \code + * int8_t bmi160_set_power_mode(struct bmi160_dev *dev); + * \endcode + * @details This API sets the power mode of the sensor. + * + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval Zero Success + * @retval Negative Error + */ +int8_t bmi160_set_power_mode(struct bmi160_dev *dev); + +/*! + * \ingroup bmi160ApiPowermode + * \page bmi160_api_bmi160_get_power_mode bmi160_get_power_mode + * \code + * int8_t bmi160_get_power_mode(struct bmi160_dev *dev); + * \endcode + * @details This API gets the power mode of the sensor. + * + * @param[in] dev : Structure instance of bmi160_dev + * + * @return Result of API execution status + * @retval Zero Success + * @retval Negative Error + */ +int8_t bmi160_get_power_mode(struct bmi160_dev *dev); + +/** + * \ingroup bmi160 + * \defgroup bmi160ApiData Sensor Data + * @brief Read sensor data + */ + +/*! + * \ingroup bmi160ApiData + * \page bmi160_api_bmi160_get_sensor_data bmi160_get_sensor_data + * \code + * int8_t bmi160_get_sensor_data(uint8_t select_sensor, + * struct bmi160_sensor_data *accel, + * struct bmi160_sensor_data *gyro, + * const struct bmi160_dev *dev); + * + * \endcode + * @details This API reads sensor data, stores it in + * the bmi160_sensor_data structure pointer passed by the user. + * The user can ask for accel data ,gyro data or both sensor + * data using bmi160_select_sensor enum + * + * @param[in] select_sensor : enum to choose accel,gyro or both sensor data + * @param[out] accel : Structure pointer to store accel data + * @param[out] gyro : Structure pointer to store gyro data + * @param[in] dev : Structure instance of bmi160_dev. + * @note : Refer user guide for detailed info. + * + * @return Result of API execution status + * @retval Zero Success + * @retval Negative Error + */ +int8_t bmi160_get_sensor_data(uint8_t select_sensor, + struct bmi160_sensor_data *accel, + struct bmi160_sensor_data *gyro, + const struct bmi160_dev *dev); + +/** + * \ingroup bmi160 + * \defgroup bmi160ApiInt Interrupt configuration + * @brief Set interrupt configuration of the sensor + */ + +/*! + * \ingroup bmi160ApiInt + * \page bmi160_api_bmi160_set_int_config bmi160_set_int_config + * \code + * int8_t bmi160_set_int_config(struct bmi160_int_settg *int_config, struct bmi160_dev *dev); + * \endcode + * @details This API configures the necessary interrupt based on + * the user settings in the bmi160_int_settg structure instance. + * + * @param[in] int_config : Structure instance of bmi160_int_settg. + * @param[in] dev : Structure instance of bmi160_dev. + * @note : Refer user guide for detailed info. + * + * @return Result of API execution status + * @retval Zero Success + * @retval Negative Error + */ +int8_t bmi160_set_int_config(struct bmi160_int_settg *int_config, struct bmi160_dev *dev); + +/** + * \ingroup bmi160 + * \defgroup bmi160ApiStepC Step counter + * @brief Step counter operations + */ + +/*! + * \ingroup bmi160ApiStepC + * \page bmi160_api_bmi160_set_step_counter bmi160_set_step_counter + * \code + * int8_t bmi160_set_step_counter(uint8_t step_cnt_enable, const struct bmi160_dev *dev); + * \endcode + * @details This API enables the step counter feature. + * + * @param[in] step_cnt_enable : value to enable or disable + * @param[in] dev : Structure instance of bmi160_dev. + * @note : Refer user guide for detailed info. + * + * @return Result of API execution status + * @retval Zero Success + * @retval Negative Error + */ +int8_t bmi160_set_step_counter(uint8_t step_cnt_enable, const struct bmi160_dev *dev); + +/*! + * \ingroup bmi160ApiStepC + * \page bmi160_api_bmi160_read_step_counter bmi160_read_step_counter + * \code + * int8_t bmi160_read_step_counter(uint16_t *step_val, const struct bmi160_dev *dev); + * \endcode + * @details This API reads the step counter value. + * + * @param[in] step_val : Pointer to store the step counter value. + * @param[in] dev : Structure instance of bmi160_dev. + * @note : Refer user guide for detailed info. + * + * @return Result of API execution status + * @retval Zero Success + * @retval Negative Error + */ +int8_t bmi160_read_step_counter(uint16_t *step_val, const struct bmi160_dev *dev); + +/** + * \ingroup bmi160 + * \defgroup bmi160ApiAux Auxiliary sensor + * @brief Auxiliary sensor operations + */ + +/*! + * \ingroup bmi160ApiAux + * \page bmi160_api_bmi160_aux_read bmi160_aux_read + * \code + * int8_t bmi160_aux_read(uint8_t reg_addr, uint8_t *aux_data, uint16_t len, const struct bmi160_dev *dev); + * \endcode + * @details This API reads the mention no of byte of data from the given + * register address of auxiliary sensor. + * + * @param[in] reg_addr : Address of register to read. + * @param[in] aux_data : Pointer to store the read data. + * @param[in] len : No of bytes to read. + * @param[in] dev : Structure instance of bmi160_dev. + * @note : Refer user guide for detailed info. + * + * @return Result of API execution status + * @retval Zero Success + * @retval Negative Error + */ +int8_t bmi160_aux_read(uint8_t reg_addr, uint8_t *aux_data, uint16_t len, const struct bmi160_dev *dev); + +/*! + * \ingroup bmi160ApiAux + * \page bmi160_api_bmi160_aux_write bmi160_aux_write + * \code + * int8_t bmi160_aux_write(uint8_t reg_addr, uint8_t *aux_data, uint16_t len, const struct bmi160_dev *dev); + * \endcode + * @details This API writes the mention no of byte of data to the given + * register address of auxiliary sensor. + * + * @param[in] reg_addr : Address of register to write. + * @param[in] aux_data : Pointer to write data. + * @param[in] len : No of bytes to write. + * @param[in] dev : Structure instance of bmi160_dev. + * @note : Refer user guide for detailed info. + * + * @return Result of API execution status + * @retval Zero Success + * @retval Negative Error + */ +int8_t bmi160_aux_write(uint8_t reg_addr, uint8_t *aux_data, uint16_t len, const struct bmi160_dev *dev); + +/*! + * \ingroup bmi160ApiAux + * \page bmi160_api_bmi160_aux_init bmi160_aux_init + * \code + * int8_t bmi160_aux_init(const struct bmi160_dev *dev); + * \endcode + * @details This API initialize the auxiliary sensor + * in order to access it. + * + * @param[in] dev : Structure instance of bmi160_dev. + * @note : Refer user guide for detailed info. + * + * @return Result of API execution status + * @retval Zero Success + * @retval Negative Error + */ +int8_t bmi160_aux_init(const struct bmi160_dev *dev); + +/*! + * \ingroup bmi160ApiAux + * \page bmi160_api_bmi160_set_aux_auto_mode bmi160_set_aux_auto_mode + * \code + * int8_t bmi160_set_aux_auto_mode(uint8_t *data_addr, struct bmi160_dev *dev); + * \endcode + * @details This API is used to setup the auxiliary sensor of bmi160 in auto mode + * Thus enabling the auto update of 8 bytes of data from auxiliary sensor + * to BMI160 register address 0x04 to 0x0B + * + * @param[in] data_addr : Starting address of aux. sensor's data register + * (BMI160 registers 0x04 to 0x0B will be updated + * with 8 bytes of data from auxiliary sensor + * starting from this register address.) + * @param[in] dev : Structure instance of bmi160_dev. + * + * @note : Set the value of auxiliary polling rate by setting + * dev->aux_cfg.aux_odr to the required value from the table + * before calling this API + * + *@verbatim + * dev->aux_cfg.aux_odr | Auxiliary ODR (Hz) + * -----------------------|----------------------- + * BMI160_AUX_ODR_0_78HZ | 25/32 + * BMI160_AUX_ODR_1_56HZ | 25/16 + * BMI160_AUX_ODR_3_12HZ | 25/8 + * BMI160_AUX_ODR_6_25HZ | 25/4 + * BMI160_AUX_ODR_12_5HZ | 25/2 + * BMI160_AUX_ODR_25HZ | 25 + * BMI160_AUX_ODR_50HZ | 50 + * BMI160_AUX_ODR_100HZ | 100 + * BMI160_AUX_ODR_200HZ | 200 + * BMI160_AUX_ODR_400HZ | 400 + * BMI160_AUX_ODR_800HZ | 800 + *@endverbatim + * + * @note : Other values of dev->aux_cfg.aux_odr are reserved and not for use + * + * @return Result of API execution status + * @retval Zero Success + * @retval Negative Error + */ +int8_t bmi160_set_aux_auto_mode(uint8_t *data_addr, struct bmi160_dev *dev); + +/*! + * \ingroup bmi160ApiAux + * \page bmi160_api_bmi160_config_aux_mode bmi160_config_aux_mode + * \code + * int8_t bmi160_config_aux_mode(const struct bmi160_dev *dev); + * \endcode + * @details This API configures the 0x4C register and settings like + * Auxiliary sensor manual enable/ disable and aux burst read length. + * + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval Zero Success + * @retval Negative Error + */ +int8_t bmi160_config_aux_mode(const struct bmi160_dev *dev); + +/*! + * \ingroup bmi160ApiAux + * \page bmi160_api_bmi160_read_aux_data_auto_mode bmi160_read_aux_data_auto_mode + * \code + * int8_t bmi160_read_aux_data_auto_mode(uint8_t *aux_data, const struct bmi160_dev *dev); + * \endcode + * @details This API is used to read the raw uncompensated auxiliary sensor + * data of 8 bytes from BMI160 register address 0x04 to 0x0B + * + * @param[in] aux_data : Pointer to user array of length 8 bytes + * Ensure that the aux_data array is of + * length 8 bytes + * @param[in] dev : Structure instance of bmi160_dev + * + * @retval zero -> Success / -ve value -> Error + * @retval Zero Success + * @retval Negative Error + */ +int8_t bmi160_read_aux_data_auto_mode(uint8_t *aux_data, const struct bmi160_dev *dev); + +/** + * \ingroup bmi160 + * \defgroup bmi160ApiSelfTest Self test + * @brief Perform self test of the sensor + */ + +/*! + * \ingroup bmi160ApiSelfTest + * \page bmi160_api_bmi160_perform_self_test bmi160_perform_self_test + * \code + * int8_t bmi160_perform_self_test(uint8_t select_sensor, struct bmi160_dev *dev); + * \endcode + * @details This is used to perform self test of accel/gyro of the BMI160 sensor + * + * @param[in] select_sensor : enum to choose accel or gyro for self test + * @param[in] dev : Structure instance of bmi160_dev + * + * @note self test can be performed either for accel/gyro at any instant. + * + *@verbatim + * value of select_sensor | Inference + *----------------------------------|-------------------------------- + * BMI160_ACCEL_ONLY | Accel self test enabled + * BMI160_GYRO_ONLY | Gyro self test enabled + * BMI160_BOTH_ACCEL_AND_GYRO | NOT TO BE USED + *@endverbatim + * + * @note The return value of this API gives us the result of self test. + * + * @note Performing self test does soft reset of the sensor, User can + * set the desired settings after performing the self test. + * + * @return Result of API execution status + * @retval BMI160_OK Self test success + * @retval BMI160_W_GYRO_SELF_TEST_FAIL Gyro self test fail + * @retval BMI160_W_ACCEl_SELF_TEST_FAIL Accel self test fail + */ +int8_t bmi160_perform_self_test(uint8_t select_sensor, struct bmi160_dev *dev); + +/** + * \ingroup bmi160 + * \defgroup bmi160ApiFIFO FIFO + * @brief FIFO operations of the sensor + */ + +/*! + * \ingroup bmi160ApiFIFO + * \page bmi160_api_bmi160_get_fifo_data bmi160_get_fifo_data + * \code + * int8_t bmi160_get_fifo_data(struct bmi160_dev const *dev); + * \endcode + * @details This API reads data from the fifo buffer. + * + * @note User has to allocate the FIFO buffer along with + * corresponding fifo length from his side before calling this API + * as mentioned in the readme.md + * + * @note User must specify the number of bytes to read from the FIFO in + * dev->fifo->length , It will be updated by the number of bytes actually + * read from FIFO after calling this API + * + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval Zero Success + * @retval Negative Error + */ +int8_t bmi160_get_fifo_data(struct bmi160_dev const *dev); + +/*! + * \ingroup bmi160ApiFIFO + * \page bmi160_api_bmi160_set_fifo_flush bmi160_set_fifo_flush + * \code + * int8_t bmi160_set_fifo_flush(const struct bmi160_dev *dev); + * \endcode + * @details This API writes fifo_flush command to command register.This + * action clears all data in the Fifo without changing fifo configuration + * settings. + * + * @param[in] dev : Structure instance of bmi160_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +int8_t bmi160_set_fifo_flush(const struct bmi160_dev *dev); + +/*! + * \ingroup bmi160ApiFIFO + * \page bmi160_api_bmi160_set_fifo_config bmi160_set_fifo_config + * \code + * int8_t bmi160_set_fifo_config(uint8_t config, uint8_t enable, struct bmi160_dev const *dev); + * \endcode + * @details This API sets the FIFO configuration in the sensor. + * + * @param[in] config : variable used to specify the FIFO + * configurations which are to be enabled or disabled in the sensor. + * + * @note : User can set either set one or more or all FIFO configurations + * by ORing the below mentioned macros. + * + *@verbatim + * config | Value + * ------------------------|--------------------------- + * BMI160_FIFO_TIME | 0x02 + * BMI160_FIFO_TAG_INT2 | 0x04 + * BMI160_FIFO_TAG_INT1 | 0x08 + * BMI160_FIFO_HEADER | 0x10 + * BMI160_FIFO_AUX | 0x20 + * BMI160_FIFO_ACCEL | 0x40 + * BMI160_FIFO_GYRO | 0x80 + *@endverbatim + * + * @param[in] enable : Parameter used to enable or disable the above + * FIFO configuration + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return status of bus communication result + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +int8_t bmi160_set_fifo_config(uint8_t config, uint8_t enable, struct bmi160_dev const *dev); + +/*! + * \ingroup bmi160ApiFIFO + * \page bmi160_api_bmi160_set_fifo_down bmi160_set_fifo_down + * \code + * int8_t bmi160_set_fifo_down(uint8_t fifo_down, const struct bmi160_dev *dev); + * \endcode + * @details This API is used to configure the down sampling ratios of + * the accel and gyro data for FIFO.Also, it configures filtered or + * pre-filtered data for the fifo for accel and gyro. + * + * @param[in] fifo_down : variable used to specify the FIFO down + * configurations which are to be enabled or disabled in the sensor. + * + * @note The user must select one among the following macros to + * select down-sampling ratio for accel + * + *@verbatim + * config | Value + * -------------------------------------|--------------------------- + * BMI160_ACCEL_FIFO_DOWN_ZERO | 0x00 + * BMI160_ACCEL_FIFO_DOWN_ONE | 0x10 + * BMI160_ACCEL_FIFO_DOWN_TWO | 0x20 + * BMI160_ACCEL_FIFO_DOWN_THREE | 0x30 + * BMI160_ACCEL_FIFO_DOWN_FOUR | 0x40 + * BMI160_ACCEL_FIFO_DOWN_FIVE | 0x50 + * BMI160_ACCEL_FIFO_DOWN_SIX | 0x60 + * BMI160_ACCEL_FIFO_DOWN_SEVEN | 0x70 + *@endverbatim + * + * @note The user must select one among the following macros to + * select down-sampling ratio for gyro + * + *@verbatim + * config | Value + * -------------------------------------|--------------------------- + * BMI160_GYRO_FIFO_DOWN_ZERO | 0x00 + * BMI160_GYRO_FIFO_DOWN_ONE | 0x01 + * BMI160_GYRO_FIFO_DOWN_TWO | 0x02 + * BMI160_GYRO_FIFO_DOWN_THREE | 0x03 + * BMI160_GYRO_FIFO_DOWN_FOUR | 0x04 + * BMI160_GYRO_FIFO_DOWN_FIVE | 0x05 + * BMI160_GYRO_FIFO_DOWN_SIX | 0x06 + * BMI160_GYRO_FIFO_DOWN_SEVEN | 0x07 + *@endverbatim + * + * @note The user can enable filtered accel data by the following macro + * + *@verbatim + * config | Value + * -------------------------------------|--------------------------- + * BMI160_ACCEL_FIFO_FILT_EN | 0x80 + *@endverbatim + * + * @note The user can enable filtered gyro data by the following macro + * + *@verbatim + * config | Value + * -------------------------------------|--------------------------- + * BMI160_GYRO_FIFO_FILT_EN | 0x08 + *@endverbatim + * + * @note : By ORing the above mentioned macros, the user can select + * the required FIFO down config settings + * + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return status of bus communication result + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +int8_t bmi160_set_fifo_down(uint8_t fifo_down, const struct bmi160_dev *dev); + +/*! + * \ingroup bmi160ApiFIFO + * \page bmi160_api_bmi160_set_fifo_wm bmi160_set_fifo_wm + * \code + * int8_t bmi160_set_fifo_wm(uint8_t fifo_wm, const struct bmi160_dev *dev); + * \endcode + * @details This API sets the FIFO watermark level in the sensor. + * + * @note The FIFO watermark is issued when the FIFO fill level is + * equal or above the watermark level and units of watermark is 4 bytes. + * + * @param[in] fifo_wm : Variable used to set the FIFO water mark level + * @param[in] dev : Structure instance of bmi160_dev + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +int8_t bmi160_set_fifo_wm(uint8_t fifo_wm, const struct bmi160_dev *dev); + +/*! + * \ingroup bmi160ApiFIFO + * \page bmi160_api_bmi160_extract_accel bmi160_extract_accel + * \code + * int8_t bmi160_extract_accel(struct bmi160_sensor_data *accel_data, uint8_t *accel_length, struct bmi160_dev const + **dev); + * \endcode + * @details This API parses and extracts the accelerometer frames from + * FIFO data read by the "bmi160_get_fifo_data" API and stores it in + * the "accel_data" structure instance. + * + * @note The bmi160_extract_accel API should be called only after + * reading the FIFO data by calling the bmi160_get_fifo_data() API. + * + * @param[out] accel_data : Structure instance of bmi160_sensor_data + * where the accelerometer data in FIFO is stored. + * @param[in,out] accel_length : Number of valid accelerometer frames + * (x,y,z axes data) read out from fifo. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @note accel_length is updated with the number of valid accelerometer + * frames extracted from fifo (1 accel frame = 6 bytes) at the end of + * execution of this API. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +int8_t bmi160_extract_accel(struct bmi160_sensor_data *accel_data, uint8_t *accel_length, struct bmi160_dev const *dev); + +/*! + * \ingroup bmi160ApiFIFO + * \page bmi160_api_bmi160_extract_gyro bmi160_extract_gyro + * \code + * int8_t bmi160_extract_gyro(struct bmi160_sensor_data *gyro_data, uint8_t *gyro_length, struct bmi160_dev const *dev); + * \endcode + * @details This API parses and extracts the gyro frames from + * FIFO data read by the "bmi160_get_fifo_data" API and stores it in + * the "gyro_data" structure instance. + * + * @note The bmi160_extract_gyro API should be called only after + * reading the FIFO data by calling the bmi160_get_fifo_data() API. + * + * @param[out] gyro_data : Structure instance of bmi160_sensor_data + * where the gyro data in FIFO is stored. + * @param[in,out] gyro_length : Number of valid gyro frames + * (x,y,z axes data) read out from fifo. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @note gyro_length is updated with the number of valid gyro + * frames extracted from fifo (1 gyro frame = 6 bytes) at the end of + * execution of this API. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +int8_t bmi160_extract_gyro(struct bmi160_sensor_data *gyro_data, uint8_t *gyro_length, struct bmi160_dev const *dev); + +/*! + * \ingroup bmi160ApiFIFO + * \page bmi160_api_bmi160_extract_aux bmi160_extract_aux + * \code + * int8_t bmi160_extract_aux(struct bmi160_aux_data *aux_data, uint8_t *aux_len, struct bmi160_dev const *dev); + * \endcode + * @details This API parses and extracts the aux frames from + * FIFO data read by the "bmi160_get_fifo_data" API and stores it in + * the bmi160_aux_data structure instance. + * + * @note The bmi160_extract_aux API should be called only after + * reading the FIFO data by calling the bmi160_get_fifo_data() API. + * + * @param[out] aux_data : Structure instance of bmi160_aux_data + * where the aux data in FIFO is stored. + * @param[in,out] aux_len : Number of valid aux frames (8bytes) + * read out from FIFO. + * @param[in] dev : Structure instance of bmi160_dev. + * + * @note aux_len is updated with the number of valid aux + * frames extracted from fifo (1 aux frame = 8 bytes) at the end of + * execution of this API. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + * + */ +int8_t bmi160_extract_aux(struct bmi160_aux_data *aux_data, uint8_t *aux_len, struct bmi160_dev const *dev); + +/** + * \ingroup bmi160 + * \defgroup bmi160ApiFOC FOC + * @brief Start FOC of accel and gyro sensors + */ + +/*! + * \ingroup bmi160ApiFOC + * \page bmi160_api_bmi160_start_foc bmi160_start_foc + * \code + * int8_t bmi160_start_foc(const struct bmi160_foc_conf *foc_conf, + * \endcode + * @details This API starts the FOC of accel and gyro + * + * @note FOC should not be used in low-power mode of sensor + * + * @note Accel FOC targets values of +1g , 0g , -1g + * Gyro FOC always targets value of 0 dps + * + * @param[in] foc_conf : Structure instance of bmi160_foc_conf which + * has the FOC configuration + * @param[in,out] offset : Structure instance to store Offset + * values read from sensor + * @param[in] dev : Structure instance of bmi160_dev. + * + * @note Pre-requisites for triggering FOC in accel , Set the following, + * Enable the acc_off_en + * Ex : foc_conf.acc_off_en = BMI160_ENABLE; + * + * Set the desired target values of FOC to each axes (x,y,z) by using the + * following macros + * - BMI160_FOC_ACCEL_DISABLED + * - BMI160_FOC_ACCEL_POSITIVE_G + * - BMI160_FOC_ACCEL_NEGATIVE_G + * - BMI160_FOC_ACCEL_0G + * + * Ex : foc_conf.foc_acc_x = BMI160_FOC_ACCEL_0G; + * foc_conf.foc_acc_y = BMI160_FOC_ACCEL_0G; + * foc_conf.foc_acc_z = BMI160_FOC_ACCEL_POSITIVE_G; + * + * @note Pre-requisites for triggering FOC in gyro , + * Set the following parameters, + * + * Ex : foc_conf.foc_gyr_en = BMI160_ENABLE; + * foc_conf.gyro_off_en = BMI160_ENABLE; + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +int8_t bmi160_start_foc(const struct bmi160_foc_conf *foc_conf, + struct bmi160_offsets *offset, + struct bmi160_dev const *dev); + +/** + * \ingroup bmi160 + * \defgroup bmi160ApiOffsets Offsets + * @brief Set / Get offset values of accel and gyro sensors + */ + +/*! + * \ingroup bmi160ApiOffsets + * \page bmi160_api_bmi160_get_offsets bmi160_get_offsets + * \code + * int8_t bmi160_get_offsets(struct bmi160_offsets *offset, const struct bmi160_dev *dev); + * \endcode + * @details This API reads and stores the offset values of accel and gyro + * + * @param[in,out] offset : Structure instance of bmi160_offsets in which + * the offset values are read and stored + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +int8_t bmi160_get_offsets(struct bmi160_offsets *offset, const struct bmi160_dev *dev); + +/*! + * \ingroup bmi160ApiOffsets + * \page bmi160_api_bmi160_set_offsets bmi160_set_offsets + * \code + * int8_t bmi160_set_offsets(const struct bmi160_foc_conf *foc_conf, + * const struct bmi160_offsets *offset, + * struct bmi160_dev const *dev); + * \endcode + * @details This API writes the offset values of accel and gyro to + * the sensor but these values will be reset on POR or soft reset. + * + * @param[in] foc_conf : Structure instance of bmi160_foc_conf which + * has the FOC configuration + * @param[in] offset : Structure instance in which user updates offset + * values which are to be written in the sensor + * @param[in] dev : Structure instance of bmi160_dev. + * + * @note Offsets can be set by user like offset->off_acc_x = 10; + * where 1LSB = 3.9mg and for gyro 1LSB = 0.061degrees/second + * + * @note BMI160 offset values for xyz axes of accel should be within range of + * BMI160_ACCEL_MIN_OFFSET (-128) to BMI160_ACCEL_MAX_OFFSET (127) + * + * @note BMI160 offset values for xyz axes of gyro should be within range of + * BMI160_GYRO_MIN_OFFSET (-512) to BMI160_GYRO_MAX_OFFSET (511) + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +int8_t bmi160_set_offsets(const struct bmi160_foc_conf *foc_conf, + const struct bmi160_offsets *offset, + struct bmi160_dev const *dev); + +/** + * \ingroup bmi160 + * \defgroup bmi160ApiNVM NVM + * @brief Write image registers values to NVM + */ + +/*! + * \ingroup bmi160ApiNVM + * \page bmi160_api_bmi160_update_nvm bmi160_update_nvm + * \code + * int8_t bmi160_update_nvm(struct bmi160_dev const *dev); + * \endcode + * @details This API writes the image registers values to NVM which is + * stored even after POR or soft reset + * + * @param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +int8_t bmi160_update_nvm(struct bmi160_dev const *dev); + +/** + * \ingroup bmi160 + * \defgroup bmi160ApiInts Interrupt status + * @brief Read interrupt status from the sensor + */ + +/*! + * \ingroup bmi160ApiInts + * \page bmi160_api_bmi160_get_int_status bmi160_get_int_status + * \code + * int8_t bmi160_get_int_status(enum bmi160_int_status_sel int_status_sel, + * union bmi160_int_status *int_status, + * struct bmi160_dev const *dev); + * \endcode + * @details This API gets the interrupt status from the sensor. + * + * @param[in] int_status_sel : Enum variable to select either individual or all the + * interrupt status bits. + * @param[in] int_status : pointer variable to get the interrupt status + * from the sensor. + * param[in] dev : Structure instance of bmi160_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval Any non zero value -> Fail + */ +int8_t bmi160_get_int_status(enum bmi160_int_status_sel int_status_sel, + union bmi160_int_status *int_status, + struct bmi160_dev const *dev); + +/*************************** C++ guard macro *****************************/ +#ifdef __cplusplus +} +#endif + +#endif /* BMI160_H_ */ diff --git a/airmouse/lib/bmi160-api/bmi160_defs.h b/airmouse/lib/bmi160-api/bmi160_defs.h new file mode 100644 index 00000000000..b4b8682747d --- /dev/null +++ b/airmouse/lib/bmi160-api/bmi160_defs.h @@ -0,0 +1,1647 @@ +/** +* Copyright (c) 2021 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 bmi160_defs.h +* @date 2021-10-05 +* @version v3.9.2 +* +*/ + +#ifndef BMI160_DEFS_H_ +#define BMI160_DEFS_H_ + +/*************************** C types headers *****************************/ +#ifdef __KERNEL__ +#include +#include +#else +#include +#include +#endif + +/*************************** Common macros *****************************/ + +#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 + +/**@}*/ +/**\name C standard macros */ +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *) 0) +#endif +#endif + +/*************************** Sensor macros *****************************/ +/* Test for an endian machine */ +#ifndef __ORDER_LITTLE_ENDIAN__ +#define __ORDER_LITTLE_ENDIAN__ 0 +#endif + +#ifndef __BYTE_ORDER__ +#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ +#endif + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#ifndef LITTLE_ENDIAN +#define LITTLE_ENDIAN 1 +#endif +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#ifndef BIG_ENDIAN +#define BIG_ENDIAN 1 +#endif +#else +#error "Code does not support Endian format of the processor" +#endif + +/** Mask definitions */ +#define BMI160_ACCEL_BW_MASK UINT8_C(0x70) +#define BMI160_ACCEL_ODR_MASK UINT8_C(0x0F) +#define BMI160_ACCEL_UNDERSAMPLING_MASK UINT8_C(0x80) +#define BMI160_ACCEL_RANGE_MASK UINT8_C(0x0F) +#define BMI160_GYRO_BW_MASK UINT8_C(0x30) +#define BMI160_GYRO_ODR_MASK UINT8_C(0x0F) +#define BMI160_GYRO_RANGE_MASK UINT8_C(0x07) + +#define BMI160_ACCEL_BW_POS UINT8_C(4) +#define BMI160_GYRO_BW_POS UINT8_C(4) + +/** Mask definitions for INT_EN registers */ +#define BMI160_ANY_MOTION_X_INT_EN_MASK UINT8_C(0x01) +#define BMI160_HIGH_G_X_INT_EN_MASK UINT8_C(0x01) +#define BMI160_NO_MOTION_X_INT_EN_MASK UINT8_C(0x01) +#define BMI160_ANY_MOTION_Y_INT_EN_MASK UINT8_C(0x02) +#define BMI160_HIGH_G_Y_INT_EN_MASK UINT8_C(0x02) +#define BMI160_NO_MOTION_Y_INT_EN_MASK UINT8_C(0x02) +#define BMI160_ANY_MOTION_Z_INT_EN_MASK UINT8_C(0x04) +#define BMI160_HIGH_G_Z_INT_EN_MASK UINT8_C(0x04) +#define BMI160_NO_MOTION_Z_INT_EN_MASK UINT8_C(0x04) +#define BMI160_SIG_MOTION_INT_EN_MASK UINT8_C(0x07) +#define BMI160_ANY_MOTION_ALL_INT_EN_MASK UINT8_C(0x07) +#define BMI160_STEP_DETECT_INT_EN_MASK UINT8_C(0x08) +#define BMI160_DOUBLE_TAP_INT_EN_MASK UINT8_C(0x10) +#define BMI160_SINGLE_TAP_INT_EN_MASK UINT8_C(0x20) +#define BMI160_FIFO_FULL_INT_EN_MASK UINT8_C(0x20) +#define BMI160_ORIENT_INT_EN_MASK UINT8_C(0x40) +#define BMI160_FIFO_WATERMARK_INT_EN_MASK UINT8_C(0x40) +#define BMI160_LOW_G_INT_EN_MASK UINT8_C(0x08) +#define BMI160_STEP_DETECT_EN_MASK UINT8_C(0x08) +#define BMI160_FLAT_INT_EN_MASK UINT8_C(0x80) +#define BMI160_DATA_RDY_INT_EN_MASK UINT8_C(0x10) + +/** PMU status Macros */ +#define BMI160_AUX_PMU_SUSPEND UINT8_C(0x00) +#define BMI160_AUX_PMU_NORMAL UINT8_C(0x01) +#define BMI160_AUX_PMU_LOW_POWER UINT8_C(0x02) + +#define BMI160_GYRO_PMU_SUSPEND UINT8_C(0x00) +#define BMI160_GYRO_PMU_NORMAL UINT8_C(0x01) +#define BMI160_GYRO_PMU_FSU UINT8_C(0x03) + +#define BMI160_ACCEL_PMU_SUSPEND UINT8_C(0x00) +#define BMI160_ACCEL_PMU_NORMAL UINT8_C(0x01) +#define BMI160_ACCEL_PMU_LOW_POWER UINT8_C(0x02) + +/** Mask definitions for INT_OUT_CTRL register */ +#define BMI160_INT1_EDGE_CTRL_MASK UINT8_C(0x01) +#define BMI160_INT1_OUTPUT_MODE_MASK UINT8_C(0x04) +#define BMI160_INT1_OUTPUT_TYPE_MASK UINT8_C(0x02) +#define BMI160_INT1_OUTPUT_EN_MASK UINT8_C(0x08) +#define BMI160_INT2_EDGE_CTRL_MASK UINT8_C(0x10) +#define BMI160_INT2_OUTPUT_MODE_MASK UINT8_C(0x40) +#define BMI160_INT2_OUTPUT_TYPE_MASK UINT8_C(0x20) +#define BMI160_INT2_OUTPUT_EN_MASK UINT8_C(0x80) + +/** Mask definitions for INT_LATCH register */ +#define BMI160_INT1_INPUT_EN_MASK UINT8_C(0x10) +#define BMI160_INT2_INPUT_EN_MASK UINT8_C(0x20) +#define BMI160_INT_LATCH_MASK UINT8_C(0x0F) + +/** Mask definitions for INT_MAP register */ +#define BMI160_INT1_LOW_G_MASK UINT8_C(0x01) +#define BMI160_INT1_HIGH_G_MASK UINT8_C(0x02) +#define BMI160_INT1_SLOPE_MASK UINT8_C(0x04) +#define BMI160_INT1_NO_MOTION_MASK UINT8_C(0x08) +#define BMI160_INT1_DOUBLE_TAP_MASK UINT8_C(0x10) +#define BMI160_INT1_SINGLE_TAP_MASK UINT8_C(0x20) +#define BMI160_INT1_FIFO_FULL_MASK UINT8_C(0x20) +#define BMI160_INT1_FIFO_WM_MASK UINT8_C(0x40) +#define BMI160_INT1_ORIENT_MASK UINT8_C(0x40) +#define BMI160_INT1_FLAT_MASK UINT8_C(0x80) +#define BMI160_INT1_DATA_READY_MASK UINT8_C(0x80) +#define BMI160_INT2_LOW_G_MASK UINT8_C(0x01) +#define BMI160_INT1_LOW_STEP_DETECT_MASK UINT8_C(0x01) +#define BMI160_INT2_LOW_STEP_DETECT_MASK UINT8_C(0x01) +#define BMI160_INT2_HIGH_G_MASK UINT8_C(0x02) +#define BMI160_INT2_FIFO_FULL_MASK UINT8_C(0x02) +#define BMI160_INT2_FIFO_WM_MASK UINT8_C(0x04) +#define BMI160_INT2_SLOPE_MASK UINT8_C(0x04) +#define BMI160_INT2_DATA_READY_MASK UINT8_C(0x08) +#define BMI160_INT2_NO_MOTION_MASK UINT8_C(0x08) +#define BMI160_INT2_DOUBLE_TAP_MASK UINT8_C(0x10) +#define BMI160_INT2_SINGLE_TAP_MASK UINT8_C(0x20) +#define BMI160_INT2_ORIENT_MASK UINT8_C(0x40) +#define BMI160_INT2_FLAT_MASK UINT8_C(0x80) + +/** Mask definitions for INT_DATA register */ +#define BMI160_TAP_SRC_INT_MASK UINT8_C(0x08) +#define BMI160_LOW_HIGH_SRC_INT_MASK UINT8_C(0x80) +#define BMI160_MOTION_SRC_INT_MASK UINT8_C(0x80) + +/** Mask definitions for INT_MOTION register */ +#define BMI160_SLOPE_INT_DUR_MASK UINT8_C(0x03) +#define BMI160_NO_MOTION_INT_DUR_MASK UINT8_C(0xFC) +#define BMI160_NO_MOTION_SEL_BIT_MASK UINT8_C(0x01) + +/** Mask definitions for INT_TAP register */ +#define BMI160_TAP_DUR_MASK UINT8_C(0x07) +#define BMI160_TAP_SHOCK_DUR_MASK UINT8_C(0x40) +#define BMI160_TAP_QUIET_DUR_MASK UINT8_C(0x80) +#define BMI160_TAP_THRES_MASK UINT8_C(0x1F) + +/** Mask definitions for INT_FLAT register */ +#define BMI160_FLAT_THRES_MASK UINT8_C(0x3F) +#define BMI160_FLAT_HOLD_TIME_MASK UINT8_C(0x30) +#define BMI160_FLAT_HYST_MASK UINT8_C(0x07) + +/** Mask definitions for INT_LOWHIGH register */ +#define BMI160_LOW_G_HYST_MASK UINT8_C(0x03) +#define BMI160_LOW_G_LOW_MODE_MASK UINT8_C(0x04) +#define BMI160_HIGH_G_HYST_MASK UINT8_C(0xC0) + +/** Mask definitions for INT_SIG_MOTION register */ +#define BMI160_SIG_MOTION_SEL_MASK UINT8_C(0x02) +#define BMI160_SIG_MOTION_SKIP_MASK UINT8_C(0x0C) +#define BMI160_SIG_MOTION_PROOF_MASK UINT8_C(0x30) + +/** Mask definitions for INT_ORIENT register */ +#define BMI160_ORIENT_MODE_MASK UINT8_C(0x03) +#define BMI160_ORIENT_BLOCK_MASK UINT8_C(0x0C) +#define BMI160_ORIENT_HYST_MASK UINT8_C(0xF0) +#define BMI160_ORIENT_THETA_MASK UINT8_C(0x3F) +#define BMI160_ORIENT_UD_ENABLE UINT8_C(0x40) +#define BMI160_AXES_EN_MASK UINT8_C(0x80) + +/** Mask definitions for FIFO_CONFIG register */ +#define BMI160_FIFO_GYRO UINT8_C(0x80) +#define BMI160_FIFO_ACCEL UINT8_C(0x40) +#define BMI160_FIFO_AUX UINT8_C(0x20) +#define BMI160_FIFO_TAG_INT1 UINT8_C(0x08) +#define BMI160_FIFO_TAG_INT2 UINT8_C(0x04) +#define BMI160_FIFO_TIME UINT8_C(0x02) +#define BMI160_FIFO_HEADER UINT8_C(0x10) +#define BMI160_FIFO_CONFIG_1_MASK UINT8_C(0xFE) + +/** Mask definitions for STEP_CONF register */ +#define BMI160_STEP_COUNT_EN_BIT_MASK UINT8_C(0x08) +#define BMI160_STEP_DETECT_MIN_THRES_MASK UINT8_C(0x18) +#define BMI160_STEP_DETECT_STEPTIME_MIN_MASK UINT8_C(0x07) +#define BMI160_STEP_MIN_BUF_MASK UINT8_C(0x07) + +/** Mask definition for FIFO Header Data Tag */ +#define BMI160_FIFO_TAG_INTR_MASK UINT8_C(0xFC) + +/** Fifo byte counter mask definitions */ +#define BMI160_FIFO_BYTE_COUNTER_MASK UINT8_C(0x07) + +/** Enable/disable bit value */ +#define BMI160_ENABLE UINT8_C(0x01) +#define BMI160_DISABLE UINT8_C(0x00) + +/** Latch Duration */ +#define BMI160_LATCH_DUR_NONE UINT8_C(0x00) +#define BMI160_LATCH_DUR_312_5_MICRO_SEC UINT8_C(0x01) +#define BMI160_LATCH_DUR_625_MICRO_SEC UINT8_C(0x02) +#define BMI160_LATCH_DUR_1_25_MILLI_SEC UINT8_C(0x03) +#define BMI160_LATCH_DUR_2_5_MILLI_SEC UINT8_C(0x04) +#define BMI160_LATCH_DUR_5_MILLI_SEC UINT8_C(0x05) +#define BMI160_LATCH_DUR_10_MILLI_SEC UINT8_C(0x06) +#define BMI160_LATCH_DUR_20_MILLI_SEC UINT8_C(0x07) +#define BMI160_LATCH_DUR_40_MILLI_SEC UINT8_C(0x08) +#define BMI160_LATCH_DUR_80_MILLI_SEC UINT8_C(0x09) +#define BMI160_LATCH_DUR_160_MILLI_SEC UINT8_C(0x0A) +#define BMI160_LATCH_DUR_320_MILLI_SEC UINT8_C(0x0B) +#define BMI160_LATCH_DUR_640_MILLI_SEC UINT8_C(0x0C) +#define BMI160_LATCH_DUR_1_28_SEC UINT8_C(0x0D) +#define BMI160_LATCH_DUR_2_56_SEC UINT8_C(0x0E) +#define BMI160_LATCHED UINT8_C(0x0F) + +/** BMI160 Register map */ +#define BMI160_CHIP_ID_ADDR UINT8_C(0x00) +#define BMI160_ERROR_REG_ADDR UINT8_C(0x02) +#define BMI160_PMU_STATUS_ADDR UINT8_C(0x03) +#define BMI160_AUX_DATA_ADDR UINT8_C(0x04) +#define BMI160_GYRO_DATA_ADDR UINT8_C(0x0C) +#define BMI160_ACCEL_DATA_ADDR UINT8_C(0x12) +#define BMI160_STATUS_ADDR UINT8_C(0x1B) +#define BMI160_INT_STATUS_ADDR UINT8_C(0x1C) +#define BMI160_FIFO_LENGTH_ADDR UINT8_C(0x22) +#define BMI160_FIFO_DATA_ADDR UINT8_C(0x24) +#define BMI160_ACCEL_CONFIG_ADDR UINT8_C(0x40) +#define BMI160_ACCEL_RANGE_ADDR UINT8_C(0x41) +#define BMI160_GYRO_CONFIG_ADDR UINT8_C(0x42) +#define BMI160_GYRO_RANGE_ADDR UINT8_C(0x43) +#define BMI160_AUX_ODR_ADDR UINT8_C(0x44) +#define BMI160_FIFO_DOWN_ADDR UINT8_C(0x45) +#define BMI160_FIFO_CONFIG_0_ADDR UINT8_C(0x46) +#define BMI160_FIFO_CONFIG_1_ADDR UINT8_C(0x47) +#define BMI160_AUX_IF_0_ADDR UINT8_C(0x4B) +#define BMI160_AUX_IF_1_ADDR UINT8_C(0x4C) +#define BMI160_AUX_IF_2_ADDR UINT8_C(0x4D) +#define BMI160_AUX_IF_3_ADDR UINT8_C(0x4E) +#define BMI160_AUX_IF_4_ADDR UINT8_C(0x4F) +#define BMI160_INT_ENABLE_0_ADDR UINT8_C(0x50) +#define BMI160_INT_ENABLE_1_ADDR UINT8_C(0x51) +#define BMI160_INT_ENABLE_2_ADDR UINT8_C(0x52) +#define BMI160_INT_OUT_CTRL_ADDR UINT8_C(0x53) +#define BMI160_INT_LATCH_ADDR UINT8_C(0x54) +#define BMI160_INT_MAP_0_ADDR UINT8_C(0x55) +#define BMI160_INT_MAP_1_ADDR UINT8_C(0x56) +#define BMI160_INT_MAP_2_ADDR UINT8_C(0x57) +#define BMI160_INT_DATA_0_ADDR UINT8_C(0x58) +#define BMI160_INT_DATA_1_ADDR UINT8_C(0x59) +#define BMI160_INT_LOWHIGH_0_ADDR UINT8_C(0x5A) +#define BMI160_INT_LOWHIGH_1_ADDR UINT8_C(0x5B) +#define BMI160_INT_LOWHIGH_2_ADDR UINT8_C(0x5C) +#define BMI160_INT_LOWHIGH_3_ADDR UINT8_C(0x5D) +#define BMI160_INT_LOWHIGH_4_ADDR UINT8_C(0x5E) +#define BMI160_INT_MOTION_0_ADDR UINT8_C(0x5F) +#define BMI160_INT_MOTION_1_ADDR UINT8_C(0x60) +#define BMI160_INT_MOTION_2_ADDR UINT8_C(0x61) +#define BMI160_INT_MOTION_3_ADDR UINT8_C(0x62) +#define BMI160_INT_TAP_0_ADDR UINT8_C(0x63) +#define BMI160_INT_TAP_1_ADDR UINT8_C(0x64) +#define BMI160_INT_ORIENT_0_ADDR UINT8_C(0x65) +#define BMI160_INT_ORIENT_1_ADDR UINT8_C(0x66) +#define BMI160_INT_FLAT_0_ADDR UINT8_C(0x67) +#define BMI160_INT_FLAT_1_ADDR UINT8_C(0x68) +#define BMI160_FOC_CONF_ADDR UINT8_C(0x69) +#define BMI160_CONF_ADDR UINT8_C(0x6A) + +#define BMI160_IF_CONF_ADDR UINT8_C(0x6B) +#define BMI160_SELF_TEST_ADDR UINT8_C(0x6D) +#define BMI160_OFFSET_ADDR UINT8_C(0x71) +#define BMI160_OFFSET_CONF_ADDR UINT8_C(0x77) +#define BMI160_INT_STEP_CNT_0_ADDR UINT8_C(0x78) +#define BMI160_INT_STEP_CONFIG_0_ADDR UINT8_C(0x7A) +#define BMI160_INT_STEP_CONFIG_1_ADDR UINT8_C(0x7B) +#define BMI160_COMMAND_REG_ADDR UINT8_C(0x7E) +#define BMI160_SPI_COMM_TEST_ADDR UINT8_C(0x7F) +#define BMI160_INTL_PULLUP_CONF_ADDR UINT8_C(0x85) + +/** Error code definitions */ +#define BMI160_OK INT8_C(0) +#define BMI160_E_NULL_PTR INT8_C(-1) +#define BMI160_E_COM_FAIL INT8_C(-2) +#define BMI160_E_DEV_NOT_FOUND INT8_C(-3) +#define BMI160_E_OUT_OF_RANGE INT8_C(-4) +#define BMI160_E_INVALID_INPUT INT8_C(-5) +#define BMI160_E_ACCEL_ODR_BW_INVALID INT8_C(-6) +#define BMI160_E_GYRO_ODR_BW_INVALID INT8_C(-7) +#define BMI160_E_LWP_PRE_FLTR_INT_INVALID INT8_C(-8) +#define BMI160_E_LWP_PRE_FLTR_INVALID INT8_C(-9) +#define BMI160_E_AUX_NOT_FOUND INT8_C(-10) +#define BMI160_E_FOC_FAILURE INT8_C(-11) +#define BMI160_E_READ_WRITE_LENGTH_INVALID INT8_C(-12) +#define BMI160_E_INVALID_CONFIG INT8_C(-13) + +/**\name API warning codes */ +#define BMI160_W_GYRO_SELF_TEST_FAIL INT8_C(1) +#define BMI160_W_ACCEl_SELF_TEST_FAIL INT8_C(2) + +/** BMI160 unique chip identifier */ +#define BMI160_CHIP_ID UINT8_C(0xD1) + +/** Soft reset command */ +#define BMI160_SOFT_RESET_CMD UINT8_C(0xb6) +#define BMI160_SOFT_RESET_DELAY_MS UINT8_C(1) + +/** Start FOC command */ +#define BMI160_START_FOC_CMD UINT8_C(0x03) + +/** NVM backup enabling command */ +#define BMI160_NVM_BACKUP_EN UINT8_C(0xA0) + +/* Delay in ms settings */ +#define BMI160_ACCEL_DELAY_MS UINT8_C(5) +#define BMI160_GYRO_DELAY_MS UINT8_C(80) +#define BMI160_ONE_MS_DELAY UINT8_C(1) +#define BMI160_AUX_COM_DELAY UINT8_C(10) +#define BMI160_GYRO_SELF_TEST_DELAY UINT8_C(20) +#define BMI160_ACCEL_SELF_TEST_DELAY UINT8_C(50) + +/** Self test configurations */ +#define BMI160_ACCEL_SELF_TEST_CONFIG UINT8_C(0x2C) +#define BMI160_ACCEL_SELF_TEST_POSITIVE_EN UINT8_C(0x0D) +#define BMI160_ACCEL_SELF_TEST_NEGATIVE_EN UINT8_C(0x09) +#define BMI160_ACCEL_SELF_TEST_LIMIT UINT16_C(8192) + +/** Power mode settings */ +/* Accel power mode */ +#define BMI160_ACCEL_NORMAL_MODE UINT8_C(0x11) +#define BMI160_ACCEL_LOWPOWER_MODE UINT8_C(0x12) +#define BMI160_ACCEL_SUSPEND_MODE UINT8_C(0x10) + +/* Gyro power mode */ +#define BMI160_GYRO_SUSPEND_MODE UINT8_C(0x14) +#define BMI160_GYRO_NORMAL_MODE UINT8_C(0x15) +#define BMI160_GYRO_FASTSTARTUP_MODE UINT8_C(0x17) + +/* Aux power mode */ +#define BMI160_AUX_SUSPEND_MODE UINT8_C(0x18) +#define BMI160_AUX_NORMAL_MODE UINT8_C(0x19) +#define BMI160_AUX_LOWPOWER_MODE UINT8_C(0x1A) + +/** Range settings */ +/* Accel Range */ +#define BMI160_ACCEL_RANGE_2G UINT8_C(0x03) +#define BMI160_ACCEL_RANGE_4G UINT8_C(0x05) +#define BMI160_ACCEL_RANGE_8G UINT8_C(0x08) +#define BMI160_ACCEL_RANGE_16G UINT8_C(0x0C) + +/* Gyro Range */ +#define BMI160_GYRO_RANGE_2000_DPS UINT8_C(0x00) +#define BMI160_GYRO_RANGE_1000_DPS UINT8_C(0x01) +#define BMI160_GYRO_RANGE_500_DPS UINT8_C(0x02) +#define BMI160_GYRO_RANGE_250_DPS UINT8_C(0x03) +#define BMI160_GYRO_RANGE_125_DPS UINT8_C(0x04) + +/** Bandwidth settings */ +/* Accel Bandwidth */ +#define BMI160_ACCEL_BW_OSR4_AVG1 UINT8_C(0x00) +#define BMI160_ACCEL_BW_OSR2_AVG2 UINT8_C(0x01) +#define BMI160_ACCEL_BW_NORMAL_AVG4 UINT8_C(0x02) +#define BMI160_ACCEL_BW_RES_AVG8 UINT8_C(0x03) +#define BMI160_ACCEL_BW_RES_AVG16 UINT8_C(0x04) +#define BMI160_ACCEL_BW_RES_AVG32 UINT8_C(0x05) +#define BMI160_ACCEL_BW_RES_AVG64 UINT8_C(0x06) +#define BMI160_ACCEL_BW_RES_AVG128 UINT8_C(0x07) + +#define BMI160_GYRO_BW_OSR4_MODE UINT8_C(0x00) +#define BMI160_GYRO_BW_OSR2_MODE UINT8_C(0x01) +#define BMI160_GYRO_BW_NORMAL_MODE UINT8_C(0x02) + +/* Output Data Rate settings */ +/* Accel Output data rate */ +#define BMI160_ACCEL_ODR_RESERVED UINT8_C(0x00) +#define BMI160_ACCEL_ODR_0_78HZ UINT8_C(0x01) +#define BMI160_ACCEL_ODR_1_56HZ UINT8_C(0x02) +#define BMI160_ACCEL_ODR_3_12HZ UINT8_C(0x03) +#define BMI160_ACCEL_ODR_6_25HZ UINT8_C(0x04) +#define BMI160_ACCEL_ODR_12_5HZ UINT8_C(0x05) +#define BMI160_ACCEL_ODR_25HZ UINT8_C(0x06) +#define BMI160_ACCEL_ODR_50HZ UINT8_C(0x07) +#define BMI160_ACCEL_ODR_100HZ UINT8_C(0x08) +#define BMI160_ACCEL_ODR_200HZ UINT8_C(0x09) +#define BMI160_ACCEL_ODR_400HZ UINT8_C(0x0A) +#define BMI160_ACCEL_ODR_800HZ UINT8_C(0x0B) +#define BMI160_ACCEL_ODR_1600HZ UINT8_C(0x0C) +#define BMI160_ACCEL_ODR_RESERVED0 UINT8_C(0x0D) +#define BMI160_ACCEL_ODR_RESERVED1 UINT8_C(0x0E) +#define BMI160_ACCEL_ODR_RESERVED2 UINT8_C(0x0F) + +/* Gyro Output data rate */ +#define BMI160_GYRO_ODR_RESERVED UINT8_C(0x00) +#define BMI160_GYRO_ODR_25HZ UINT8_C(0x06) +#define BMI160_GYRO_ODR_50HZ UINT8_C(0x07) +#define BMI160_GYRO_ODR_100HZ UINT8_C(0x08) +#define BMI160_GYRO_ODR_200HZ UINT8_C(0x09) +#define BMI160_GYRO_ODR_400HZ UINT8_C(0x0A) +#define BMI160_GYRO_ODR_800HZ UINT8_C(0x0B) +#define BMI160_GYRO_ODR_1600HZ UINT8_C(0x0C) +#define BMI160_GYRO_ODR_3200HZ UINT8_C(0x0D) + +/* Auxiliary sensor Output data rate */ +#define BMI160_AUX_ODR_RESERVED UINT8_C(0x00) +#define BMI160_AUX_ODR_0_78HZ UINT8_C(0x01) +#define BMI160_AUX_ODR_1_56HZ UINT8_C(0x02) +#define BMI160_AUX_ODR_3_12HZ UINT8_C(0x03) +#define BMI160_AUX_ODR_6_25HZ UINT8_C(0x04) +#define BMI160_AUX_ODR_12_5HZ UINT8_C(0x05) +#define BMI160_AUX_ODR_25HZ UINT8_C(0x06) +#define BMI160_AUX_ODR_50HZ UINT8_C(0x07) +#define BMI160_AUX_ODR_100HZ UINT8_C(0x08) +#define BMI160_AUX_ODR_200HZ UINT8_C(0x09) +#define BMI160_AUX_ODR_400HZ UINT8_C(0x0A) +#define BMI160_AUX_ODR_800HZ UINT8_C(0x0B) + +/** FIFO_CONFIG Definitions */ +#define BMI160_FIFO_TIME_ENABLE UINT8_C(0x02) +#define BMI160_FIFO_TAG_INT2_ENABLE UINT8_C(0x04) +#define BMI160_FIFO_TAG_INT1_ENABLE UINT8_C(0x08) +#define BMI160_FIFO_HEAD_ENABLE UINT8_C(0x10) +#define BMI160_FIFO_M_ENABLE UINT8_C(0x20) +#define BMI160_FIFO_A_ENABLE UINT8_C(0x40) +#define BMI160_FIFO_M_A_ENABLE UINT8_C(0x60) +#define BMI160_FIFO_G_ENABLE UINT8_C(0x80) +#define BMI160_FIFO_M_G_ENABLE UINT8_C(0xA0) +#define BMI160_FIFO_G_A_ENABLE UINT8_C(0xC0) +#define BMI160_FIFO_M_G_A_ENABLE UINT8_C(0xE0) + +/* Macro to specify the number of bytes over-read from the + * FIFO in order to get the sensor time at the end of FIFO */ +#ifndef BMI160_FIFO_BYTES_OVERREAD +#define BMI160_FIFO_BYTES_OVERREAD UINT8_C(25) +#endif + +/* Accel, gyro and aux. sensor length and also their combined + * length definitions in FIFO */ +#define BMI160_FIFO_G_LENGTH UINT8_C(6) +#define BMI160_FIFO_A_LENGTH UINT8_C(6) +#define BMI160_FIFO_M_LENGTH UINT8_C(8) +#define BMI160_FIFO_GA_LENGTH UINT8_C(12) +#define BMI160_FIFO_MA_LENGTH UINT8_C(14) +#define BMI160_FIFO_MG_LENGTH UINT8_C(14) +#define BMI160_FIFO_MGA_LENGTH UINT8_C(20) + +/** FIFO Header Data definitions */ +#define BMI160_FIFO_HEAD_SKIP_FRAME UINT8_C(0x40) +#define BMI160_FIFO_HEAD_SENSOR_TIME UINT8_C(0x44) +#define BMI160_FIFO_HEAD_INPUT_CONFIG UINT8_C(0x48) +#define BMI160_FIFO_HEAD_OVER_READ UINT8_C(0x80) +#define BMI160_FIFO_HEAD_A UINT8_C(0x84) +#define BMI160_FIFO_HEAD_G UINT8_C(0x88) +#define BMI160_FIFO_HEAD_G_A UINT8_C(0x8C) +#define BMI160_FIFO_HEAD_M UINT8_C(0x90) +#define BMI160_FIFO_HEAD_M_A UINT8_C(0x94) +#define BMI160_FIFO_HEAD_M_G UINT8_C(0x98) +#define BMI160_FIFO_HEAD_M_G_A UINT8_C(0x9C) + +/** FIFO sensor time length definitions */ +#define BMI160_SENSOR_TIME_LENGTH UINT8_C(3) + +/** FIFO DOWN selection */ +/* Accel fifo down-sampling values*/ +#define BMI160_ACCEL_FIFO_DOWN_ZERO UINT8_C(0x00) +#define BMI160_ACCEL_FIFO_DOWN_ONE UINT8_C(0x10) +#define BMI160_ACCEL_FIFO_DOWN_TWO UINT8_C(0x20) +#define BMI160_ACCEL_FIFO_DOWN_THREE UINT8_C(0x30) +#define BMI160_ACCEL_FIFO_DOWN_FOUR UINT8_C(0x40) +#define BMI160_ACCEL_FIFO_DOWN_FIVE UINT8_C(0x50) +#define BMI160_ACCEL_FIFO_DOWN_SIX UINT8_C(0x60) +#define BMI160_ACCEL_FIFO_DOWN_SEVEN UINT8_C(0x70) + +/* Gyro fifo down-smapling values*/ +#define BMI160_GYRO_FIFO_DOWN_ZERO UINT8_C(0x00) +#define BMI160_GYRO_FIFO_DOWN_ONE UINT8_C(0x01) +#define BMI160_GYRO_FIFO_DOWN_TWO UINT8_C(0x02) +#define BMI160_GYRO_FIFO_DOWN_THREE UINT8_C(0x03) +#define BMI160_GYRO_FIFO_DOWN_FOUR UINT8_C(0x04) +#define BMI160_GYRO_FIFO_DOWN_FIVE UINT8_C(0x05) +#define BMI160_GYRO_FIFO_DOWN_SIX UINT8_C(0x06) +#define BMI160_GYRO_FIFO_DOWN_SEVEN UINT8_C(0x07) + +/* Accel Fifo filter enable*/ +#define BMI160_ACCEL_FIFO_FILT_EN UINT8_C(0x80) + +/* Gyro Fifo filter enable*/ +#define BMI160_GYRO_FIFO_FILT_EN UINT8_C(0x08) + +/** Definitions to check validity of FIFO frames */ +#define FIFO_CONFIG_MSB_CHECK UINT8_C(0x80) +#define FIFO_CONFIG_LSB_CHECK UINT8_C(0x00) + +/*! BMI160 accel FOC configurations */ +#define BMI160_FOC_ACCEL_DISABLED UINT8_C(0x00) +#define BMI160_FOC_ACCEL_POSITIVE_G UINT8_C(0x01) +#define BMI160_FOC_ACCEL_NEGATIVE_G UINT8_C(0x02) +#define BMI160_FOC_ACCEL_0G UINT8_C(0x03) + +/** Array Parameter DefinItions */ +#define BMI160_SENSOR_TIME_LSB_BYTE UINT8_C(0) +#define BMI160_SENSOR_TIME_XLSB_BYTE UINT8_C(1) +#define BMI160_SENSOR_TIME_MSB_BYTE UINT8_C(2) + +/** Interface settings */ +#define BMI160_SPI_INTF UINT8_C(1) +#define BMI160_I2C_INTF UINT8_C(0) +#define BMI160_SPI_RD_MASK UINT8_C(0x80) +#define BMI160_SPI_WR_MASK UINT8_C(0x7F) + +/* Sensor & time select definition*/ +#define BMI160_ACCEL_SEL UINT8_C(0x01) +#define BMI160_GYRO_SEL UINT8_C(0x02) +#define BMI160_TIME_SEL UINT8_C(0x04) + +/* Sensor select mask*/ +#define BMI160_SEN_SEL_MASK UINT8_C(0x07) + +/* Error code mask */ +#define BMI160_ERR_REG_MASK UINT8_C(0x0F) + +/* BMI160 I2C address */ +#define BMI160_I2C_ADDR UINT8_C(0x68) + +/* BMI160 secondary IF address */ +#define BMI160_AUX_BMM150_I2C_ADDR UINT8_C(0x10) + +/** BMI160 Length definitions */ +#define BMI160_ONE UINT8_C(1) +#define BMI160_TWO UINT8_C(2) +#define BMI160_THREE UINT8_C(3) +#define BMI160_FOUR UINT8_C(4) +#define BMI160_FIVE UINT8_C(5) + +/** BMI160 fifo level Margin */ +#define BMI160_FIFO_LEVEL_MARGIN UINT8_C(16) + +/** BMI160 fifo flush Command */ +#define BMI160_FIFO_FLUSH_VALUE UINT8_C(0xB0) + +/** BMI160 offset values for xyz axes of accel */ +#define BMI160_ACCEL_MIN_OFFSET INT8_C(-128) +#define BMI160_ACCEL_MAX_OFFSET INT8_C(127) + +/** BMI160 offset values for xyz axes of gyro */ +#define BMI160_GYRO_MIN_OFFSET INT16_C(-512) +#define BMI160_GYRO_MAX_OFFSET INT16_C(511) + +/** BMI160 fifo full interrupt position and mask */ +#define BMI160_FIFO_FULL_INT_POS UINT8_C(5) +#define BMI160_FIFO_FULL_INT_MSK UINT8_C(0x20) +#define BMI160_FIFO_WTM_INT_POS UINT8_C(6) +#define BMI160_FIFO_WTM_INT_MSK UINT8_C(0x40) + +#define BMI160_FIFO_FULL_INT_PIN1_POS UINT8_C(5) +#define BMI160_FIFO_FULL_INT_PIN1_MSK UINT8_C(0x20) +#define BMI160_FIFO_FULL_INT_PIN2_POS UINT8_C(1) +#define BMI160_FIFO_FULL_INT_PIN2_MSK UINT8_C(0x02) + +#define BMI160_FIFO_WTM_INT_PIN1_POS UINT8_C(6) +#define BMI160_FIFO_WTM_INT_PIN1_MSK UINT8_C(0x40) +#define BMI160_FIFO_WTM_INT_PIN2_POS UINT8_C(2) +#define BMI160_FIFO_WTM_INT_PIN2_MSK UINT8_C(0x04) + +#define BMI160_MANUAL_MODE_EN_POS UINT8_C(7) +#define BMI160_MANUAL_MODE_EN_MSK UINT8_C(0x80) +#define BMI160_AUX_READ_BURST_POS UINT8_C(0) +#define BMI160_AUX_READ_BURST_MSK UINT8_C(0x03) + +#define BMI160_GYRO_SELF_TEST_POS UINT8_C(4) +#define BMI160_GYRO_SELF_TEST_MSK UINT8_C(0x10) +#define BMI160_GYRO_SELF_TEST_STATUS_POS UINT8_C(1) +#define BMI160_GYRO_SELF_TEST_STATUS_MSK UINT8_C(0x02) + +#define BMI160_GYRO_FOC_EN_POS UINT8_C(6) +#define BMI160_GYRO_FOC_EN_MSK UINT8_C(0x40) + +#define BMI160_ACCEL_FOC_X_CONF_POS UINT8_C(4) +#define BMI160_ACCEL_FOC_X_CONF_MSK UINT8_C(0x30) + +#define BMI160_ACCEL_FOC_Y_CONF_POS UINT8_C(2) +#define BMI160_ACCEL_FOC_Y_CONF_MSK UINT8_C(0x0C) + +#define BMI160_ACCEL_FOC_Z_CONF_MSK UINT8_C(0x03) + +#define BMI160_FOC_STATUS_POS UINT8_C(3) +#define BMI160_FOC_STATUS_MSK UINT8_C(0x08) + +#define BMI160_GYRO_OFFSET_X_MSK UINT8_C(0x03) + +#define BMI160_GYRO_OFFSET_Y_POS UINT8_C(2) +#define BMI160_GYRO_OFFSET_Y_MSK UINT8_C(0x0C) + +#define BMI160_GYRO_OFFSET_Z_POS UINT8_C(4) +#define BMI160_GYRO_OFFSET_Z_MSK UINT8_C(0x30) + +#define BMI160_GYRO_OFFSET_EN_POS UINT8_C(7) +#define BMI160_GYRO_OFFSET_EN_MSK UINT8_C(0x80) + +#define BMI160_ACCEL_OFFSET_EN_POS UINT8_C(6) +#define BMI160_ACCEL_OFFSET_EN_MSK UINT8_C(0x40) + +#define BMI160_GYRO_OFFSET_POS UINT16_C(8) +#define BMI160_GYRO_OFFSET_MSK UINT16_C(0x0300) + +#define BMI160_NVM_UPDATE_POS UINT8_C(1) +#define BMI160_NVM_UPDATE_MSK UINT8_C(0x02) + +#define BMI160_NVM_STATUS_POS UINT8_C(4) +#define BMI160_NVM_STATUS_MSK UINT8_C(0x10) + +#define BMI160_MAG_POWER_MODE_MSK UINT8_C(0x03) + +#define BMI160_ACCEL_POWER_MODE_MSK UINT8_C(0x30) +#define BMI160_ACCEL_POWER_MODE_POS UINT8_C(4) + +#define BMI160_GYRO_POWER_MODE_MSK UINT8_C(0x0C) +#define BMI160_GYRO_POWER_MODE_POS UINT8_C(2) + +/* BIT SLICE GET AND SET FUNCTIONS */ +#define BMI160_GET_BITS(regvar, bitname) \ + ((regvar & bitname##_MSK) >> bitname##_POS) +#define BMI160_SET_BITS(regvar, bitname, val) \ + ((regvar & ~bitname##_MSK) | \ + ((val << bitname##_POS) & bitname##_MSK)) + +#define BMI160_SET_BITS_POS_0(reg_data, bitname, data) \ + ((reg_data & ~(bitname##_MSK)) | \ + (data & bitname##_MSK)) + +#define BMI160_GET_BITS_POS_0(reg_data, bitname) (reg_data & (bitname##_MSK)) + +/**\name UTILITY MACROS */ +#define BMI160_SET_LOW_BYTE UINT16_C(0x00FF) +#define BMI160_SET_HIGH_BYTE UINT16_C(0xFF00) + +#define BMI160_GET_LSB(var) (uint8_t)(var & BMI160_SET_LOW_BYTE) +#define BMI160_GET_MSB(var) (uint8_t)((var & BMI160_SET_HIGH_BYTE) >> 8) + +/*****************************************************************************/ +/* type definitions */ + +/*! + * @brief Bus communication function pointer which should be mapped to + * the platform specific read functions of the user + */ +typedef int8_t (*bmi160_read_fptr_t)(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint16_t len); + +/*! + * @brief Bus communication function pointer which should be mapped to + * the platform specific write functions of the user + */ +typedef int8_t (*bmi160_write_fptr_t)(uint8_t dev_addr, uint8_t reg_addr, uint8_t *read_data, uint16_t len); +typedef void (*bmi160_delay_fptr_t)(uint32_t period); + +/*************************** Data structures *********************************/ + +/*! + * @brief bmi160 interrupt status selection enum. + */ +enum bmi160_int_status_sel { + BMI160_INT_STATUS_0 = 1, + BMI160_INT_STATUS_1 = 2, + BMI160_INT_STATUS_2 = 4, + BMI160_INT_STATUS_3 = 8, + BMI160_INT_STATUS_ALL = 15 +}; + +/*! + * @brief bmi160 interrupt status bits structure + */ +struct bmi160_int_status_bits +{ +#ifdef LITTLE_ENDIAN + + uint32_t step : 1; + uint32_t sigmot : 1; + uint32_t anym : 1; + + /* pmu trigger will be handled later */ + uint32_t pmu_trigger_reserved : 1; + uint32_t d_tap : 1; + uint32_t s_tap : 1; + uint32_t orient : 1; + uint32_t flat_int : 1; + uint32_t reserved : 2; + uint32_t high_g : 1; + uint32_t low_g : 1; + uint32_t drdy : 1; + uint32_t ffull : 1; + uint32_t fwm : 1; + uint32_t nomo : 1; + uint32_t anym_first_x : 1; + uint32_t anym_first_y : 1; + uint32_t anym_first_z : 1; + uint32_t anym_sign : 1; + uint32_t tap_first_x : 1; + uint32_t tap_first_y : 1; + uint32_t tap_first_z : 1; + uint32_t tap_sign : 1; + uint32_t high_first_x : 1; + uint32_t high_first_y : 1; + uint32_t high_first_z : 1; + uint32_t high_sign : 1; + uint32_t orient_1_0 : 2; + uint32_t orient_2 : 1; + uint32_t flat : 1; +#else + uint32_t high_first_x : 1; + uint32_t high_first_y : 1; + uint32_t high_first_z : 1; + uint32_t high_sign : 1; + uint32_t orient_1_0 : 2; + uint32_t orient_2 : 1; + uint32_t flat : 1; + uint32_t anym_first_x : 1; + uint32_t anym_first_y : 1; + uint32_t anym_first_z : 1; + uint32_t anym_sign : 1; + uint32_t tap_first_x : 1; + uint32_t tap_first_y : 1; + uint32_t tap_first_z : 1; + uint32_t tap_sign : 1; + uint32_t reserved : 2; + uint32_t high_g : 1; + uint32_t low_g : 1; + uint32_t drdy : 1; + uint32_t ffull : 1; + uint32_t fwm : 1; + uint32_t nomo : 1; + uint32_t step : 1; + uint32_t sigmot : 1; + uint32_t anym : 1; + + /* pmu trigger will be handled later */ + uint32_t pmu_trigger_reserved : 1; + uint32_t d_tap : 1; + uint32_t s_tap : 1; + uint32_t orient : 1; + uint32_t flat_int : 1; +#endif +}; + +/*! + * @brief bmi160 interrupt status structure + */ +union bmi160_int_status +{ + uint8_t data[4]; + struct bmi160_int_status_bits bit; +}; + +/*! + * @brief bmi160 sensor data structure which comprises of accel data + */ +struct bmi160_sensor_data +{ + /*! X-axis sensor data */ + int16_t x; + + /*! Y-axis sensor data */ + int16_t y; + + /*! Z-axis sensor data */ + int16_t z; + + /*! sensor time */ + uint32_t sensortime; +}; + +/*! + * @brief bmi160 aux data structure which comprises of 8 bytes of accel data + */ +struct bmi160_aux_data +{ + /*! Auxiliary data */ + uint8_t data[8]; +}; + +/*! + * @brief bmi160 FOC configuration structure + */ +struct bmi160_foc_conf +{ + /*! Enabling FOC in gyro + * Assignable macros : + * - BMI160_ENABLE + * - BMI160_DISABLE + */ + uint8_t foc_gyr_en; + + /*! Accel FOC configurations + * Assignable macros : + * - BMI160_FOC_ACCEL_DISABLED + * - BMI160_FOC_ACCEL_POSITIVE_G + * - BMI160_FOC_ACCEL_NEGATIVE_G + * - BMI160_FOC_ACCEL_0G + */ + uint8_t foc_acc_x; + uint8_t foc_acc_y; + uint8_t foc_acc_z; + + /*! Enabling offset compensation for accel in data registers + * Assignable macros : + * - BMI160_ENABLE + * - BMI160_DISABLE + */ + uint8_t acc_off_en; + + /*! Enabling offset compensation for gyro in data registers + * Assignable macros : + * - BMI160_ENABLE + * - BMI160_DISABLE + */ + uint8_t gyro_off_en; +}; + +/*! + * @brief bmi160 accel gyro offsets + */ +struct bmi160_offsets +{ + /*! Accel offset for x axis */ + int8_t off_acc_x; + + /*! Accel offset for y axis */ + int8_t off_acc_y; + + /*! Accel offset for z axis */ + int8_t off_acc_z; + + /*! Gyro offset for x axis */ + int16_t off_gyro_x; + + /*! Gyro offset for y axis */ + int16_t off_gyro_y; + + /*! Gyro offset for z axis */ + int16_t off_gyro_z; +}; + +/*! + * @brief FIFO aux. sensor data structure + */ +struct bmi160_aux_fifo_data +{ + /*! The value of aux. sensor x LSB data */ + uint8_t aux_x_lsb; + + /*! The value of aux. sensor x MSB data */ + uint8_t aux_x_msb; + + /*! The value of aux. sensor y LSB data */ + uint8_t aux_y_lsb; + + /*! The value of aux. sensor y MSB data */ + uint8_t aux_y_msb; + + /*! The value of aux. sensor z LSB data */ + uint8_t aux_z_lsb; + + /*! The value of aux. sensor z MSB data */ + uint8_t aux_z_msb; + + /*! The value of aux. sensor r for BMM150 LSB data */ + uint8_t aux_r_y2_lsb; + + /*! The value of aux. sensor r for BMM150 MSB data */ + uint8_t aux_r_y2_msb; +}; + +/*! + * @brief bmi160 sensor select structure + */ +enum bmi160_select_sensor { + BMI160_ACCEL_ONLY = 1, + BMI160_GYRO_ONLY, + BMI160_BOTH_ACCEL_AND_GYRO +}; + +/*! + * @brief bmi160 sensor step detector mode structure + */ +enum bmi160_step_detect_mode { + BMI160_STEP_DETECT_NORMAL, + BMI160_STEP_DETECT_SENSITIVE, + BMI160_STEP_DETECT_ROBUST, + + /*! Non recommended User defined setting */ + BMI160_STEP_DETECT_USER_DEFINE +}; + +/*! + * @brief enum for auxiliary burst read selection + */ +enum bmi160_aux_read_len { + BMI160_AUX_READ_LEN_0, + BMI160_AUX_READ_LEN_1, + BMI160_AUX_READ_LEN_2, + BMI160_AUX_READ_LEN_3 +}; + +/*! + * @brief bmi160 sensor configuration structure + */ +struct bmi160_cfg +{ + /*! power mode */ + uint8_t power; + + /*! output data rate */ + uint8_t odr; + + /*! range */ + uint8_t range; + + /*! bandwidth */ + uint8_t bw; +}; + +/*! + * @brief Aux sensor configuration structure + */ +struct bmi160_aux_cfg +{ + /*! Aux sensor, 1 - enable 0 - disable */ + uint8_t aux_sensor_enable : 1; + + /*! Aux manual/auto mode status */ + uint8_t manual_enable : 1; + + /*! Aux read burst length */ + uint8_t aux_rd_burst_len : 2; + + /*! output data rate */ + uint8_t aux_odr : 4; + + /*! i2c addr of auxiliary sensor */ + uint8_t aux_i2c_addr; +}; + +/*! + * @brief bmi160 interrupt channel selection structure + */ +enum bmi160_int_channel { + /*! Un-map both channels */ + BMI160_INT_CHANNEL_NONE, + + /*! interrupt Channel 1 */ + BMI160_INT_CHANNEL_1, + + /*! interrupt Channel 2 */ + BMI160_INT_CHANNEL_2, + + /*! Map both channels */ + BMI160_INT_CHANNEL_BOTH +}; +enum bmi160_int_types { + /*! Slope/Any-motion interrupt */ + BMI160_ACC_ANY_MOTION_INT, + + /*! Significant motion interrupt */ + BMI160_ACC_SIG_MOTION_INT, + + /*! Step detector interrupt */ + BMI160_STEP_DETECT_INT, + + /*! double tap interrupt */ + BMI160_ACC_DOUBLE_TAP_INT, + + /*! single tap interrupt */ + BMI160_ACC_SINGLE_TAP_INT, + + /*! orientation interrupt */ + BMI160_ACC_ORIENT_INT, + + /*! flat interrupt */ + BMI160_ACC_FLAT_INT, + + /*! high-g interrupt */ + BMI160_ACC_HIGH_G_INT, + + /*! low-g interrupt */ + BMI160_ACC_LOW_G_INT, + + /*! slow/no-motion interrupt */ + BMI160_ACC_SLOW_NO_MOTION_INT, + + /*! data ready interrupt */ + BMI160_ACC_GYRO_DATA_RDY_INT, + + /*! fifo full interrupt */ + BMI160_ACC_GYRO_FIFO_FULL_INT, + + /*! fifo watermark interrupt */ + BMI160_ACC_GYRO_FIFO_WATERMARK_INT, + + /*! fifo tagging feature support */ + BMI160_FIFO_TAG_INT_PIN +}; + +/*! + * @brief bmi160 active state of any & sig motion interrupt. + */ +enum bmi160_any_sig_motion_active_interrupt_state { + /*! Both any & sig motion are disabled */ + BMI160_BOTH_ANY_SIG_MOTION_DISABLED = -1, + + /*! Any-motion selected */ + BMI160_ANY_MOTION_ENABLED, + + /*! Sig-motion selected */ + BMI160_SIG_MOTION_ENABLED +}; +struct bmi160_acc_tap_int_cfg +{ +#ifdef LITTLE_ENDIAN + + /*! tap threshold */ + uint16_t tap_thr : 5; + + /*! tap shock */ + uint16_t tap_shock : 1; + + /*! tap quiet */ + uint16_t tap_quiet : 1; + + /*! tap duration */ + uint16_t tap_dur : 3; + + /*! data source 0- filter & 1 pre-filter*/ + uint16_t tap_data_src : 1; + + /*! tap enable, 1 - enable, 0 - disable */ + uint16_t tap_en : 1; +#else + + /*! tap enable, 1 - enable, 0 - disable */ + uint16_t tap_en : 1; + + /*! data source 0- filter & 1 pre-filter*/ + uint16_t tap_data_src : 1; + + /*! tap duration */ + uint16_t tap_dur : 3; + + /*! tap quiet */ + uint16_t tap_quiet : 1; + + /*! tap shock */ + uint16_t tap_shock : 1; + + /*! tap threshold */ + uint16_t tap_thr : 5; +#endif +}; +struct bmi160_acc_any_mot_int_cfg +{ +#ifdef LITTLE_ENDIAN + + /*! 1 any-motion enable, 0 - any-motion disable */ + uint8_t anymotion_en : 1; + + /*! slope interrupt x, 1 - enable, 0 - disable */ + uint8_t anymotion_x : 1; + + /*! slope interrupt y, 1 - enable, 0 - disable */ + uint8_t anymotion_y : 1; + + /*! slope interrupt z, 1 - enable, 0 - disable */ + uint8_t anymotion_z : 1; + + /*! slope duration */ + uint8_t anymotion_dur : 2; + + /*! data source 0- filter & 1 pre-filter*/ + uint8_t anymotion_data_src : 1; + + /*! slope threshold */ + uint8_t anymotion_thr; +#else + + /*! slope threshold */ + uint8_t anymotion_thr; + + /*! data source 0- filter & 1 pre-filter*/ + uint8_t anymotion_data_src : 1; + + /*! slope duration */ + uint8_t anymotion_dur : 2; + + /*! slope interrupt z, 1 - enable, 0 - disable */ + uint8_t anymotion_z : 1; + + /*! slope interrupt y, 1 - enable, 0 - disable */ + uint8_t anymotion_y : 1; + + /*! slope interrupt x, 1 - enable, 0 - disable */ + uint8_t anymotion_x : 1; + + /*! 1 any-motion enable, 0 - any-motion disable */ + uint8_t anymotion_en : 1; +#endif +}; +struct bmi160_acc_sig_mot_int_cfg +{ +#ifdef LITTLE_ENDIAN + + /*! skip time of sig-motion interrupt */ + uint8_t sig_mot_skip : 2; + + /*! proof time of sig-motion interrupt */ + uint8_t sig_mot_proof : 2; + + /*! data source 0- filter & 1 pre-filter*/ + uint8_t sig_data_src : 1; + + /*! 1 - enable sig, 0 - disable sig & enable anymotion */ + uint8_t sig_en : 1; + + /*! sig-motion threshold */ + uint8_t sig_mot_thres; +#else + + /*! sig-motion threshold */ + uint8_t sig_mot_thres; + + /*! 1 - enable sig, 0 - disable sig & enable anymotion */ + uint8_t sig_en : 1; + + /*! data source 0- filter & 1 pre-filter*/ + uint8_t sig_data_src : 1; + + /*! proof time of sig-motion interrupt */ + uint8_t sig_mot_proof : 2; + + /*! skip time of sig-motion interrupt */ + uint8_t sig_mot_skip : 2; +#endif +}; +struct bmi160_acc_step_detect_int_cfg +{ +#ifdef LITTLE_ENDIAN + + /*! 1- step detector enable, 0- step detector disable */ + uint16_t step_detector_en : 1; + + /*! minimum threshold */ + uint16_t min_threshold : 2; + + /*! minimal detectable step time */ + uint16_t steptime_min : 3; + + /*! enable step counter mode setting */ + uint16_t step_detector_mode : 2; + + /*! minimum step buffer size*/ + uint16_t step_min_buf : 3; +#else + + /*! minimum step buffer size*/ + uint16_t step_min_buf : 3; + + /*! enable step counter mode setting */ + uint16_t step_detector_mode : 2; + + /*! minimal detectable step time */ + uint16_t steptime_min : 3; + + /*! minimum threshold */ + uint16_t min_threshold : 2; + + /*! 1- step detector enable, 0- step detector disable */ + uint16_t step_detector_en : 1; +#endif +}; +struct bmi160_acc_no_motion_int_cfg +{ +#ifdef LITTLE_ENDIAN + + /*! no motion interrupt x */ + uint16_t no_motion_x : 1; + + /*! no motion interrupt y */ + uint16_t no_motion_y : 1; + + /*! no motion interrupt z */ + uint16_t no_motion_z : 1; + + /*! no motion duration */ + uint16_t no_motion_dur : 6; + + /*! no motion sel , 1 - enable no-motion ,0- enable slow-motion */ + uint16_t no_motion_sel : 1; + + /*! data source 0- filter & 1 pre-filter*/ + uint16_t no_motion_src : 1; + + /*! no motion threshold */ + uint8_t no_motion_thres; +#else + + /*! no motion threshold */ + uint8_t no_motion_thres; + + /*! data source 0- filter & 1 pre-filter*/ + uint16_t no_motion_src : 1; + + /*! no motion sel , 1 - enable no-motion ,0- enable slow-motion */ + uint16_t no_motion_sel : 1; + + /*! no motion duration */ + uint16_t no_motion_dur : 6; + + /* no motion interrupt z */ + uint16_t no_motion_z : 1; + + /*! no motion interrupt y */ + uint16_t no_motion_y : 1; + + /*! no motion interrupt x */ + uint16_t no_motion_x : 1; +#endif +}; +struct bmi160_acc_orient_int_cfg +{ +#ifdef LITTLE_ENDIAN + + /*! thresholds for switching between the different orientations */ + uint16_t orient_mode : 2; + + /*! blocking_mode */ + uint16_t orient_blocking : 2; + + /*! Orientation interrupt hysteresis */ + uint16_t orient_hyst : 4; + + /*! Orientation interrupt theta */ + uint16_t orient_theta : 6; + + /*! Enable/disable Orientation interrupt */ + uint16_t orient_ud_en : 1; + + /*! exchange x- and z-axis in algorithm ,0 - z, 1 - x */ + uint16_t axes_ex : 1; + + /*! 1 - orient enable, 0 - orient disable */ + uint8_t orient_en : 1; +#else + + /*! 1 - orient enable, 0 - orient disable */ + uint8_t orient_en : 1; + + /*! exchange x- and z-axis in algorithm ,0 - z, 1 - x */ + uint16_t axes_ex : 1; + + /*! Enable/disable Orientation interrupt */ + uint16_t orient_ud_en : 1; + + /*! Orientation interrupt theta */ + uint16_t orient_theta : 6; + + /*! Orientation interrupt hysteresis */ + uint16_t orient_hyst : 4; + + /*! blocking_mode */ + uint16_t orient_blocking : 2; + + /*! thresholds for switching between the different orientations */ + uint16_t orient_mode : 2; +#endif +}; +struct bmi160_acc_flat_detect_int_cfg +{ +#ifdef LITTLE_ENDIAN + + /*! flat threshold */ + uint16_t flat_theta : 6; + + /*! flat interrupt hysteresis */ + uint16_t flat_hy : 3; + + /*! delay time for which the flat value must remain stable for the + * flat interrupt to be generated */ + uint16_t flat_hold_time : 2; + + /*! 1 - flat enable, 0 - flat disable */ + uint16_t flat_en : 1; +#else + + /*! 1 - flat enable, 0 - flat disable */ + uint16_t flat_en : 1; + + /*! delay time for which the flat value must remain stable for the + * flat interrupt to be generated */ + uint16_t flat_hold_time : 2; + + /*! flat interrupt hysteresis */ + uint16_t flat_hy : 3; + + /*! flat threshold */ + uint16_t flat_theta : 6; +#endif +}; +struct bmi160_acc_low_g_int_cfg +{ +#ifdef LITTLE_ENDIAN + + /*! low-g interrupt trigger delay */ + uint8_t low_dur; + + /*! low-g interrupt trigger threshold */ + uint8_t low_thres; + + /*! hysteresis of low-g interrupt */ + uint8_t low_hyst : 2; + + /*! 0 - single-axis mode ,1 - axis-summing mode */ + uint8_t low_mode : 1; + + /*! data source 0- filter & 1 pre-filter */ + uint8_t low_data_src : 1; + + /*! 1 - enable low-g, 0 - disable low-g */ + uint8_t low_en : 1; +#else + + /*! 1 - enable low-g, 0 - disable low-g */ + uint8_t low_en : 1; + + /*! data source 0- filter & 1 pre-filter */ + uint8_t low_data_src : 1; + + /*! 0 - single-axis mode ,1 - axis-summing mode */ + uint8_t low_mode : 1; + + /*! hysteresis of low-g interrupt */ + uint8_t low_hyst : 2; + + /*! low-g interrupt trigger threshold */ + uint8_t low_thres; + + /*! low-g interrupt trigger delay */ + uint8_t low_dur; +#endif +}; +struct bmi160_acc_high_g_int_cfg +{ +#ifdef LITTLE_ENDIAN + + /*! High-g interrupt x, 1 - enable, 0 - disable */ + uint8_t high_g_x : 1; + + /*! High-g interrupt y, 1 - enable, 0 - disable */ + uint8_t high_g_y : 1; + + /*! High-g interrupt z, 1 - enable, 0 - disable */ + uint8_t high_g_z : 1; + + /*! High-g hysteresis */ + uint8_t high_hy : 2; + + /*! data source 0- filter & 1 pre-filter */ + uint8_t high_data_src : 1; + + /*! High-g threshold */ + uint8_t high_thres; + + /*! High-g duration */ + uint8_t high_dur; +#else + + /*! High-g duration */ + uint8_t high_dur; + + /*! High-g threshold */ + uint8_t high_thres; + + /*! data source 0- filter & 1 pre-filter */ + uint8_t high_data_src : 1; + + /*! High-g hysteresis */ + uint8_t high_hy : 2; + + /*! High-g interrupt z, 1 - enable, 0 - disable */ + uint8_t high_g_z : 1; + + /*! High-g interrupt y, 1 - enable, 0 - disable */ + uint8_t high_g_y : 1; + + /*! High-g interrupt x, 1 - enable, 0 - disable */ + uint8_t high_g_x : 1; +#endif +}; +struct bmi160_int_pin_settg +{ +#ifdef LITTLE_ENDIAN + + /*! To enable either INT1 or INT2 pin as output. + * 0- output disabled ,1- output enabled */ + uint16_t output_en : 1; + + /*! 0 - push-pull 1- open drain,only valid if output_en is set 1 */ + uint16_t output_mode : 1; + + /*! 0 - active low , 1 - active high level. + * if output_en is 1,this applies to interrupts,else PMU_trigger */ + uint16_t output_type : 1; + + /*! 0 - level trigger , 1 - edge trigger */ + uint16_t edge_ctrl : 1; + + /*! To enable either INT1 or INT2 pin as input. + * 0 - input disabled ,1 - input enabled */ + uint16_t input_en : 1; + + /*! latch duration*/ + uint16_t latch_dur : 4; +#else + + /*! latch duration*/ + uint16_t latch_dur : 4; + + /*! Latched,non-latched or temporary interrupt modes */ + uint16_t input_en : 1; + + /*! 1 - edge trigger, 0 - level trigger */ + uint16_t edge_ctrl : 1; + + /*! 0 - active low , 1 - active high level. + * if output_en is 1,this applies to interrupts,else PMU_trigger */ + uint16_t output_type : 1; + + /*! 0 - push-pull , 1 - open drain,only valid if output_en is set 1 */ + uint16_t output_mode : 1; + + /*! To enable either INT1 or INT2 pin as output. + * 0 - output disabled , 1 - output enabled */ + uint16_t output_en : 1; +#endif +}; +union bmi160_int_type_cfg +{ + /*! Tap interrupt structure */ + struct bmi160_acc_tap_int_cfg acc_tap_int; + + /*! Slope interrupt structure */ + struct bmi160_acc_any_mot_int_cfg acc_any_motion_int; + + /*! Significant motion interrupt structure */ + struct bmi160_acc_sig_mot_int_cfg acc_sig_motion_int; + + /*! Step detector interrupt structure */ + struct bmi160_acc_step_detect_int_cfg acc_step_detect_int; + + /*! No motion interrupt structure */ + struct bmi160_acc_no_motion_int_cfg acc_no_motion_int; + + /*! Orientation interrupt structure */ + struct bmi160_acc_orient_int_cfg acc_orient_int; + + /*! Flat interrupt structure */ + struct bmi160_acc_flat_detect_int_cfg acc_flat_int; + + /*! Low-g interrupt structure */ + struct bmi160_acc_low_g_int_cfg acc_low_g_int; + + /*! High-g interrupt structure */ + struct bmi160_acc_high_g_int_cfg acc_high_g_int; +}; +struct bmi160_int_settg +{ + /*! Interrupt channel */ + enum bmi160_int_channel int_channel; + + /*! Select Interrupt */ + enum bmi160_int_types int_type; + + /*! Structure configuring Interrupt pins */ + struct bmi160_int_pin_settg int_pin_settg; + + /*! Union configures required interrupt */ + union bmi160_int_type_cfg int_type_cfg; + + /*! FIFO FULL INT 1-enable, 0-disable */ + uint8_t fifo_full_int_en : 1; + + /*! FIFO WTM INT 1-enable, 0-disable */ + uint8_t fifo_wtm_int_en : 1; +}; + +/*! + * @brief This structure holds the information for usage of + * FIFO by the user. + */ +struct bmi160_fifo_frame +{ + /*! Data buffer of user defined length is to be mapped here */ + uint8_t *data; + + /*! While calling the API "bmi160_get_fifo_data" , length stores + * number of bytes in FIFO to be read (specified by user as input) + * and after execution of the API ,number of FIFO data bytes + * available is provided as an output to user + */ + uint16_t length; + + /*! FIFO time enable */ + uint8_t fifo_time_enable; + + /*! Enabling of the FIFO header to stream in header mode */ + uint8_t fifo_header_enable; + + /*! Streaming of the Accelerometer, Gyroscope + * sensor data or both in FIFO */ + uint8_t fifo_data_enable; + + /*! Will be equal to length when no more frames are there to parse */ + uint16_t accel_byte_start_idx; + + /*! Will be equal to length when no more frames are there to parse */ + uint16_t gyro_byte_start_idx; + + /*! Will be equal to length when no more frames are there to parse */ + uint16_t aux_byte_start_idx; + + /*! Value of FIFO sensor time time */ + uint32_t sensor_time; + + /*! Value of Skipped frame counts */ + uint8_t skipped_frame_count; +}; +struct bmi160_dev +{ + /*! Chip Id */ + uint8_t chip_id; + + /*! Device Id */ + uint8_t id; + + /*! 0 - I2C , 1 - SPI Interface */ + uint8_t intf; + + /*! Hold active interrupts status for any and sig motion + * 0 - Any-motion enable, 1 - Sig-motion enable, + * -1 neither any-motion nor sig-motion selected */ + enum bmi160_any_sig_motion_active_interrupt_state any_sig_sel; + + /*! Structure to configure Accel sensor */ + struct bmi160_cfg accel_cfg; + + /*! Structure to hold previous/old accel config parameters. + * This is used at driver level to prevent overwriting of same + * data, hence user does not change it in the code */ + struct bmi160_cfg prev_accel_cfg; + + /*! Structure to configure Gyro sensor */ + struct bmi160_cfg gyro_cfg; + + /*! Structure to hold previous/old gyro config parameters. + * This is used at driver level to prevent overwriting of same + * data, hence user does not change it in the code */ + struct bmi160_cfg prev_gyro_cfg; + + /*! Structure to configure the auxiliary sensor */ + struct bmi160_aux_cfg aux_cfg; + + /*! Structure to hold previous/old aux config parameters. + * This is used at driver level to prevent overwriting of same + * data, hence user does not change it in the code */ + struct bmi160_aux_cfg prev_aux_cfg; + + /*! FIFO related configurations */ + struct bmi160_fifo_frame *fifo; + + /*! Read function pointer */ + bmi160_read_fptr_t read; + + /*! Write function pointer */ + bmi160_write_fptr_t write; + + /*! Delay function pointer */ + bmi160_delay_fptr_t delay_ms; + + /*! User set read/write length */ + uint16_t read_write_len; +}; + +#endif /* BMI160_DEFS_H_ */ diff --git a/airmouse/lib/bmi160-api/examples/read_chip_id/Makefile b/airmouse/lib/bmi160-api/examples/read_chip_id/Makefile new file mode 100644 index 00000000000..41bff4e5f42 --- /dev/null +++ b/airmouse/lib/bmi160-api/examples/read_chip_id/Makefile @@ -0,0 +1,13 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= read_chip_id.c + +API_LOCATION ?= ../.. + +C_SRCS += \ +$(API_LOCATION)/bmi160.c + +INCLUDEPATHS += \ +$(API_LOCATION) + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/airmouse/lib/bmi160-api/examples/read_chip_id/read_chip_id.c b/airmouse/lib/bmi160-api/examples/read_chip_id/read_chip_id.c new file mode 100644 index 00000000000..29207e17895 --- /dev/null +++ b/airmouse/lib/bmi160-api/examples/read_chip_id/read_chip_id.c @@ -0,0 +1,237 @@ +/** + * Copyright (C) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*********************************************************************/ +/* system header files */ +/*********************************************************************/ +#include +#include +#include + +/*********************************************************************/ +/* own header files */ +/*********************************************************************/ +#include "coines.h" +#include "bmi160.h" + +/*********************************************************************/ +/* local macro definitions */ +/*! i2c interface communication, 1 - Enable; 0- Disable */ +#define BMI160_INTERFACE_I2C 1 + +/*! spi interface communication, 1 - Enable; 0- Disable */ +#define BMI160_INTERFACE_SPI 0 + +#if (!((BMI160_INTERFACE_I2C == 1) && (BMI160_INTERFACE_SPI == 0)) && \ + (!((BMI160_INTERFACE_I2C == 0) && (BMI160_INTERFACE_SPI == 1)))) +#error "Invalid value given for the macros BMI160_INTERFACE_I2C / BMI160_INTERFACE_SPI" +#endif + +/*! bmi160 shuttle id */ +#define BMI160_SHUTTLE_ID 0x38 + +/*! bmi160 Device address */ +#define BMI160_DEV_ADDR BMI160_I2C_ADDR + +/*********************************************************************/ +/* global variables */ +/*********************************************************************/ + +/*! @brief This structure containing relevant bmi160 info */ +struct bmi160_dev bmi160dev; + +/*! @brief variable to hold the bmi160 accel data */ +struct bmi160_sensor_data bmi160_accel; + +/*! @brief variable to hold the bmi160 gyro data */ +struct bmi160_sensor_data bmi160_gyro; + +/*********************************************************************/ +/* static function declarations */ +/*********************************************************************/ + +/*! + * @brief internal API is used to initialize the sensor interface + */ +static void init_sensor_interface(void); + +/*! + * @brief This internal API is used to initialize the bmi160 sensor with default + */ +static void init_bmi160(void); + +/*! + * @brief This internal API is used to initialize the sensor driver interface + */ +static void init_bmi160_sensor_driver_interface(void); + +/*********************************************************************/ +/* functions */ +/*********************************************************************/ + +/*! + * @brief This internal API is used to initialize the sensor interface depending + * on selection either SPI or I2C. + * + * @param[in] void + * + * @return void + * + */ +static void init_sensor_interface(void) +{ + /* Switch VDD for sensor off */ + coines_set_shuttleboard_vdd_vddio_config(0, 0); + + /* wait until the sensor goes off */ + coines_delay_msec(10); +#if BMI160_INTERFACE_I2C == 1 + + /* SDO pin is made low for selecting I2C address 0x68 */ + coines_set_pin_config(COINES_SHUTTLE_PIN_15, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_LOW); + + /* set the sensor interface as I2C */ + coines_config_i2c_bus(COINES_I2C_BUS_0, COINES_I2C_FAST_MODE); + coines_delay_msec(10); + + /* CSB pin is made high for selecting I2C protocol*/ + coines_set_pin_config(COINES_SHUTTLE_PIN_7, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_HIGH); +#endif +#if BMI160_INTERFACE_SPI == 1 + + /* CSB pin is made low for selecting SPI protocol*/ + coines_set_pin_config(COINES_SHUTTLE_PIN_7, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_LOW); + + coines_delay_msec(10); + coines_config_spi_bus(COINES_SPI_BUS_0, COINES_SPI_SPEED_5_MHZ, COINES_SPI_MODE3); +#endif + coines_delay_msec(10); + + /* Switch VDD for sensor on */ + coines_set_shuttleboard_vdd_vddio_config(3300, 3300); + +#if BMI160_INTERFACE_SPI == 1 + coines_delay_msec(10); + + /* CSB pin is made high for selecting SPI protocol + * Note: CSB has to see rising after power up, to switch to SPI protocol */ + coines_set_pin_config(COINES_SHUTTLE_PIN_7, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_HIGH); +#endif +} + +/*! + * @brief This internal API is used to initializes the bmi160 sensor + * settings like power mode and OSRS settings. + * + * @param[in] void + * + * @return void + * + */ +static void init_bmi160(void) +{ + int8_t rslt; + + rslt = bmi160_init(&bmi160dev); + + if (rslt == BMI160_OK) + { + printf("BMI160 initialization success !\n"); + printf("Chip ID 0x%X\n", bmi160dev.chip_id); + } + else + { + printf("BMI160 initialization failure !\n"); + exit(COINES_E_FAILURE); + } +} + +/*! + * @brief This internal API is used to set the sensor driver interface to + * read/write the data. + * + * @param[in] void + * + * @return void + * + */ +static void init_bmi160_sensor_driver_interface(void) +{ +#if BMI160_INTERFACE_I2C == 1 + + /* I2C setup */ + + /* link read/write/delay function of host system to appropriate + * bmi160 function call prototypes */ + bmi160dev.write = coines_write_i2c; + bmi160dev.read = coines_read_i2c; + bmi160dev.delay_ms = coines_delay_msec; + + /* set correct i2c address */ + bmi160dev.id = BMI160_DEV_ADDR; + bmi160dev.intf = BMI160_I2C_INTF; +#endif +#if BMI160_INTERFACE_SPI == 1 + + /* SPI setup */ + + /* link read/write/delay function of host system to appropriate + * bmi160 function call prototypes */ + bmi160dev.write = coines_write_spi; + bmi160dev.read = coines_read_spi; + bmi160dev.delay_ms = coines_delay_msec; + bmi160dev.id = COINES_SHUTTLE_PIN_7; + bmi160dev.intf = BMI160_SPI_INTF; +#endif +} + +/*! + * @brief Main Function where the execution getting started to test the code. + * + * @param[in] argc + * @param[in] argv + * + * @return status + * + */ +int main(int argc, char *argv[]) +{ + struct coines_board_info board_info; + int16_t rslt; + + init_bmi160_sensor_driver_interface(); + + rslt = coines_open_comm_intf(COINES_COMM_INTF_USB); + + if (rslt < 0) + { + printf( + "\n Unable to connect with Application Board ! \n" " 1. Check if the board is connected and powered on. \n" " 2. Check if Application Board USB driver is installed. \n" + " 3. Check if board is in use by another application. (Insufficient permissions to access USB) \n"); + exit(rslt); + } + + rslt = coines_get_board_info(&board_info); + + if (rslt == COINES_SUCCESS) + { + if (board_info.shuttle_id != BMI160_SHUTTLE_ID) + { + + printf("! Warning invalid sensor shuttle \n ," "This application will not support this sensor \n"); + exit(COINES_E_FAILURE); + } + } + + init_sensor_interface(); + + /* After sensor init introduce 200 msec sleep */ + coines_delay_msec(200); + init_bmi160(); + coines_close_comm_intf(COINES_COMM_INTF_USB); + + return EXIT_SUCCESS; +} diff --git a/airmouse/lib/bmi160-api/examples/read_sensor_data/Makefile b/airmouse/lib/bmi160-api/examples/read_sensor_data/Makefile new file mode 100644 index 00000000000..fdf2597ab92 --- /dev/null +++ b/airmouse/lib/bmi160-api/examples/read_sensor_data/Makefile @@ -0,0 +1,13 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= read_sensor_data.c + +API_LOCATION ?= ../.. + +C_SRCS += \ +$(API_LOCATION)/bmi160.c + +INCLUDEPATHS += \ +$(API_LOCATION) + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/airmouse/lib/bmi160-api/examples/read_sensor_data/read_sensor_data.c b/airmouse/lib/bmi160-api/examples/read_sensor_data/read_sensor_data.c new file mode 100644 index 00000000000..7462e0fd0d7 --- /dev/null +++ b/airmouse/lib/bmi160-api/examples/read_sensor_data/read_sensor_data.c @@ -0,0 +1,271 @@ +/** + * Copyright (C) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*********************************************************************/ +/* system header files */ +/*********************************************************************/ +#include +#include +#include + +/*********************************************************************/ +/* own header files */ +/*********************************************************************/ +#include "coines.h" +#include "bmi160.h" + +/*********************************************************************/ +/* local macro definitions */ +/*! I2C interface communication, 1 - Enable; 0- Disable */ +#define BMI160_INTERFACE_I2C 1 + +/*! SPI interface communication, 1 - Enable; 0- Disable */ +#define BMI160_INTERFACE_SPI 0 + +#if (!((BMI160_INTERFACE_I2C == 1) && (BMI160_INTERFACE_SPI == 0)) && \ + (!((BMI160_INTERFACE_I2C == 0) && (BMI160_INTERFACE_SPI == 1)))) +#error "Invalid value given for the macros BMI160_INTERFACE_I2C / BMI160_INTERFACE_SPI" +#endif + +/*! bmi160 shuttle id */ +#define BMI160_SHUTTLE_ID 0x38 + +/*! bmi160 Device address */ +#define BMI160_DEV_ADDR BMI160_I2C_ADDR + +/*********************************************************************/ +/* global variables */ +/*********************************************************************/ + +/*! @brief This structure containing relevant bmi160 info */ +struct bmi160_dev bmi160dev; + +/*! @brief variable to hold the bmi160 accel data */ +struct bmi160_sensor_data bmi160_accel; + +/*! @brief variable to hold the bmi160 gyro data */ +struct bmi160_sensor_data bmi160_gyro; + +/*********************************************************************/ +/* static function declarations */ +/*********************************************************************/ + +/*! + * @brief internal API is used to initialize the sensor interface + */ +static void init_sensor_interface(void); + +/*! + * @brief This internal API is used to initialize the bmi160 sensor with default + */ +static void init_bmi160(void); + +/*! + * @brief This internal API is used to initialize the sensor driver interface + */ +static void init_bmi160_sensor_driver_interface(void); + +/*********************************************************************/ +/* functions */ +/*********************************************************************/ + +/*! + * @brief This internal API is used to initialize the sensor interface depending + * on selection either SPI or I2C. + * + * @param[in] void + * + * @return void + * + */ +static void init_sensor_interface(void) +{ + /* Switch VDD for sensor off */ + coines_set_shuttleboard_vdd_vddio_config(0, 0); + + /* wait until the sensor goes off */ + coines_delay_msec(10); +#if BMI160_INTERFACE_I2C == 1 + + /* SDO pin is made low for selecting I2C address 0x68 */ + coines_set_pin_config(COINES_SHUTTLE_PIN_15, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_LOW); + + /* set the sensor interface as I2C */ + coines_config_i2c_bus(COINES_I2C_BUS_0, COINES_I2C_FAST_MODE); + coines_delay_msec(10); + + /* CSB pin is made high for selecting I2C protocol*/ + coines_set_pin_config(COINES_SHUTTLE_PIN_7, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_HIGH); +#endif +#if BMI160_INTERFACE_SPI == 1 + + /* CSB pin is made low for selecting SPI protocol*/ + coines_set_pin_config(COINES_SHUTTLE_PIN_7, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_LOW); + + coines_delay_msec(10); + coines_config_spi_bus(COINES_SPI_BUS_0, COINES_SPI_SPEED_5_MHZ, COINES_SPI_MODE3); +#endif + coines_delay_msec(10); + + /* Switch VDD for sensor on */ + coines_set_shuttleboard_vdd_vddio_config(3300, 3300); + +#if BMI160_INTERFACE_SPI == 1 + coines_delay_msec(10); + + /* CSB pin is made high for selecting SPI protocol + * Note: CSB has to see rising after power up, to switch to SPI protocol */ + coines_set_pin_config(COINES_SHUTTLE_PIN_7, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_HIGH); +#endif +} + +/*! + * @brief This internal API is used to initializes the bmi160 sensor + * settings like power mode and OSRS settings. + * + * @param[in] void + * + * @return void + * + */ +static void init_bmi160(void) +{ + int8_t rslt; + + rslt = bmi160_init(&bmi160dev); + + if (rslt == BMI160_OK) + { + printf("BMI160 initialization success !\n"); + printf("Chip ID 0x%X\n", bmi160dev.chip_id); + } + else + { + printf("BMI160 initialization failure !\n"); + exit(COINES_E_FAILURE); + } + + /* Select the Output data rate, range of accelerometer sensor */ + bmi160dev.accel_cfg.odr = BMI160_ACCEL_ODR_1600HZ; + bmi160dev.accel_cfg.range = BMI160_ACCEL_RANGE_16G; + bmi160dev.accel_cfg.bw = BMI160_ACCEL_BW_NORMAL_AVG4; + + /* Select the power mode of accelerometer sensor */ + bmi160dev.accel_cfg.power = BMI160_ACCEL_NORMAL_MODE; + + /* Select the Output data rate, range of Gyroscope sensor */ + bmi160dev.gyro_cfg.odr = BMI160_GYRO_ODR_3200HZ; + bmi160dev.gyro_cfg.range = BMI160_GYRO_RANGE_2000_DPS; + bmi160dev.gyro_cfg.bw = BMI160_GYRO_BW_NORMAL_MODE; + + /* Select the power mode of Gyroscope sensor */ + bmi160dev.gyro_cfg.power = BMI160_GYRO_NORMAL_MODE; + + /* Set the sensor configuration */ + rslt = bmi160_set_sens_conf(&bmi160dev); +} + +/*! + * @brief This internal API is used to set the sensor driver interface to + * read/write the data. + * + * @param[in] void + * + * @return void + * + */ +static void init_bmi160_sensor_driver_interface(void) +{ +#if BMI160_INTERFACE_I2C == 1 + + /* I2C setup */ + + /* link read/write/delay function of host system to appropriate + * bmi160 function call prototypes */ + bmi160dev.write = coines_write_i2c; + bmi160dev.read = coines_read_i2c; + bmi160dev.delay_ms = coines_delay_msec; + + /* set correct i2c address */ + bmi160dev.id = BMI160_DEV_ADDR; + bmi160dev.intf = BMI160_I2C_INTF; +#endif +#if BMI160_INTERFACE_SPI == 1 + + /* SPI setup */ + + /* link read/write/delay function of host system to appropriate + * bmi160 function call prototypes */ + bmi160dev.write = coines_write_spi; + bmi160dev.read = coines_read_spi; + bmi160dev.delay_ms = coines_delay_msec; + bmi160dev.id = COINES_SHUTTLE_PIN_7; + bmi160dev.intf = BMI160_SPI_INTF; +#endif +} + +/*! + * @brief Main Function where the execution getting started to test the code. + * + * @param[in] argc + * @param[in] argv + * + * @return status + * + */ +int main(int argc, char *argv[]) +{ + struct coines_board_info board_info; + int16_t rslt; + int times_to_read = 0; + + init_bmi160_sensor_driver_interface(); + + rslt = coines_open_comm_intf(COINES_COMM_INTF_USB); + + if (rslt < 0) + { + printf( + "\n Unable to connect with Application Board ! \n" " 1. Check if the board is connected and powered on. \n" " 2. Check if Application Board USB driver is installed. \n" + " 3. Check if board is in use by another application. (Insufficient permissions to access USB) \n"); + exit(rslt); + } + + rslt = coines_get_board_info(&board_info); + + if (rslt == COINES_SUCCESS) + { + if (board_info.shuttle_id != BMI160_SHUTTLE_ID) + { + + printf("! Warning invalid sensor shuttle \n ," "This application will not support this sensor \n"); + exit(COINES_E_FAILURE); + } + } + + init_sensor_interface(); + + /* After sensor init introduce 200 msec sleep */ + coines_delay_msec(200); + init_bmi160(); + + while (times_to_read < 100) + { + /* To read both Accel and Gyro data */ + bmi160_get_sensor_data((BMI160_ACCEL_SEL | BMI160_GYRO_SEL), &bmi160_accel, &bmi160_gyro, &bmi160dev); + + printf("ax:%d\tay:%d\taz:%d\n", bmi160_accel.x, bmi160_accel.y, bmi160_accel.z); + printf("gx:%d\tgy:%d\tgz:%d\n", bmi160_gyro.x, bmi160_gyro.y, bmi160_gyro.z); + fflush(stdout); + + coines_delay_msec(10); + times_to_read = times_to_read + 1; + } + + coines_close_comm_intf(COINES_COMM_INTF_USB); + + return EXIT_SUCCESS; +} diff --git a/airmouse/lib/bmi160-api/examples/tap/Makefile b/airmouse/lib/bmi160-api/examples/tap/Makefile new file mode 100644 index 00000000000..40583362684 --- /dev/null +++ b/airmouse/lib/bmi160-api/examples/tap/Makefile @@ -0,0 +1,13 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= tap.c + +API_LOCATION ?= ../.. + +C_SRCS += \ +$(API_LOCATION)/bmi160.c + +INCLUDEPATHS += \ +$(API_LOCATION) + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/airmouse/lib/bmi160-api/examples/tap/tap.c b/airmouse/lib/bmi160-api/examples/tap/tap.c new file mode 100644 index 00000000000..b8ea2d006b4 --- /dev/null +++ b/airmouse/lib/bmi160-api/examples/tap/tap.c @@ -0,0 +1,366 @@ +/** + * Copyright (C) 2021 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*********************************************************************/ +/* system header files */ +/*********************************************************************/ +#include +#include +#include + +/*********************************************************************/ +/* own header files */ +/*********************************************************************/ +#include "coines.h" +#include "bmi160.h" + +/*********************************************************************/ +/* local macro definitions */ +/*! i2c interface communication, 1 - Enable; 0- Disable */ +#define BMI160_INTERFACE_I2C 0 + +/*! spi interface communication, 1 - Enable; 0- Disable */ +#define BMI160_INTERFACE_SPI 1 + +#if (!((BMI160_INTERFACE_I2C == 1) && (BMI160_INTERFACE_SPI == 0)) && \ + (!((BMI160_INTERFACE_I2C == 0) && (BMI160_INTERFACE_SPI == 1)))) +#error "Invalid value given for the macros BMI160_INTERFACE_I2C / BMI160_INTERFACE_SPI" +#endif + +/*! bmi160 shuttle id */ +#define BMI160_SHUTTLE_ID 0x38 + +/*! bmi160 Device address */ +#define BMI160_DEV_ADDR BMI160_I2C_ADDR + +/*********************************************************************/ +/* global variables */ +/*********************************************************************/ + +/*! @brief This structure containing relevant bmi160 info */ +struct bmi160_dev bmi160dev; + +/*! @brief variable to hold the bmi160 accel data */ +struct bmi160_sensor_data bmi160_accel; + +/*! @brief variable to hold the bmi160 gyro data */ +struct bmi160_sensor_data bmi160_gyro; + +/*********************************************************************/ +/* static function declarations */ +/*********************************************************************/ + +/*! + * @brief internal API is used to initialize the sensor interface + */ +static void init_sensor_interface(void); + +/*! + * @brief This internal API is used to initialize the bmi160 sensor with default + */ +static void init_bmi160(void); + +/*! + * @brief This internal API is used to initialize the sensor driver interface + */ +static void init_bmi160_sensor_driver_interface(void); + +/*! + * @brief This internal API is used to set tap configurations + */ +static int8_t set_tap_config(uint8_t feature_enable); + +/*********************************************************************/ +/* functions */ +/*********************************************************************/ + +/*! + * @brief This internal API is used to initialize the sensor interface depending + * on selection either SPI or I2C. + * + * @param[in] void + * + * @return void + * + */ +static void init_sensor_interface(void) +{ + /* Switch VDD for sensor off */ + coines_set_shuttleboard_vdd_vddio_config(0, 0); + + /* wait until the sensor goes off */ + coines_delay_msec(10); +#if BMI160_INTERFACE_I2C == 1 + + /* SDO pin is made low for selecting I2C address 0x68 */ + coines_set_pin_config(COINES_SHUTTLE_PIN_15, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_LOW); + + /* set the sensor interface as I2C */ + coines_config_i2c_bus(COINES_I2C_BUS_0, COINES_I2C_FAST_MODE); + coines_delay_msec(10); + + /* CSB pin is made high for selecting I2C protocol*/ + coines_set_pin_config(COINES_SHUTTLE_PIN_7, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_HIGH); +#endif +#if BMI160_INTERFACE_SPI == 1 + + /* CSB pin is made low for selecting SPI protocol*/ + coines_set_pin_config(COINES_SHUTTLE_PIN_7, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_LOW); + + coines_delay_msec(10); + coines_config_spi_bus(COINES_SPI_BUS_0, COINES_SPI_SPEED_5_MHZ, COINES_SPI_MODE3); +#endif + coines_delay_msec(10); + + /* Switch VDD for sensor on */ + coines_set_shuttleboard_vdd_vddio_config(3300, 3300); + +#if BMI160_INTERFACE_SPI == 1 + coines_delay_msec(10); + + /* CSB pin is made high for selecting SPI protocol + * Note: CSB has to see rising after power up, to switch to SPI protocol */ + coines_set_pin_config(COINES_SHUTTLE_PIN_7, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_HIGH); +#endif +} + +/*! + * @brief This internal API is used to initializes the bmi160 sensor + * settings like power mode and OSRS settings. + * + * @param[in] void + * + * @return void + * + */ +static void init_bmi160(void) +{ + int8_t rslt; + + rslt = bmi160_init(&bmi160dev); + + if (rslt == BMI160_OK) + { + printf("BMI160 initialization success !\n"); + printf("Chip ID 0x%X\n", bmi160dev.chip_id); + } + else + { + printf("BMI160 initialization failure !\n"); + exit(COINES_E_FAILURE); + } + + /* Select the Output data rate, range of accelerometer sensor */ + bmi160dev.accel_cfg.odr = BMI160_ACCEL_ODR_100HZ; + bmi160dev.accel_cfg.range = BMI160_ACCEL_RANGE_8G; + bmi160dev.accel_cfg.bw = BMI160_ACCEL_BW_NORMAL_AVG4; + + /* Select the power mode of accelerometer sensor */ + bmi160dev.accel_cfg.power = BMI160_ACCEL_NORMAL_MODE; + + /* Set the sensor configuration */ + rslt = bmi160_set_sens_conf(&bmi160dev); +} + +/*! + * @brief This internal API is used to set the sensor driver interface to + * read/write the data. + * + * @param[in] void + * + * @return void + * + */ +static void init_bmi160_sensor_driver_interface(void) +{ +#if BMI160_INTERFACE_I2C == 1 + + /* I2C setup */ + + /* link read/write/delay function of host system to appropriate + * bmi160 function call prototypes */ + bmi160dev.write = coines_write_i2c; + bmi160dev.read = coines_read_i2c; + bmi160dev.delay_ms = coines_delay_msec; + + /* set correct i2c address */ + bmi160dev.id = BMI160_DEV_ADDR; + bmi160dev.intf = BMI160_I2C_INTF; +#endif +#if BMI160_INTERFACE_SPI == 1 + + /* SPI setup */ + + /* link read/write/delay function of host system to appropriate + * bmi160 function call prototypes */ + bmi160dev.write = coines_write_spi; + bmi160dev.read = coines_read_spi; + bmi160dev.delay_ms = coines_delay_msec; + bmi160dev.id = COINES_SHUTTLE_PIN_7; + bmi160dev.intf = BMI160_SPI_INTF; +#endif +} + +/*! + * @brief Main Function where the execution getting started to test the code. + * + * @param[in] argc + * @param[in] argv + * + * @return status + * + */ +int main(int argc, char *argv[]) +{ + struct coines_board_info board_info; + int16_t rslt; + + init_bmi160_sensor_driver_interface(); + + rslt = coines_open_comm_intf(COINES_COMM_INTF_USB); + + if (rslt < 0) + { + printf( + "\n Unable to connect with Application Board ! \n" " 1. Check if the board is connected and powered on. \n" " 2. Check if Application Board USB driver is installed. \n" + " 3. Check if board is in use by another application. (Insufficient permissions to access USB) \n"); + exit(rslt); + } + + rslt = coines_get_board_info(&board_info); + + if (rslt == COINES_SUCCESS) + { + if (board_info.shuttle_id != BMI160_SHUTTLE_ID) + { + + printf("! Warning invalid sensor shuttle \n ," "This application will not support this sensor \n"); + exit(COINES_E_FAILURE); + } + } + + init_sensor_interface(); + + /* after sensor init introduce 200 msec sleep */ + coines_delay_msec(200); + init_bmi160(); + + rslt = set_tap_config(BMI160_ENABLE); + if (rslt == BMI160_OK) + { + union bmi160_int_status int_status; + uint8_t loop = 0; + uint32_t last_time = 0; + uint32_t current_time = 0; + + printf("Do Single or Double Tap the board\n"); + fflush(stdout); + + memset(int_status.data, 0x00, sizeof(int_status.data)); + + while (loop < 10) + { + /* Read interrupt status */ + rslt = bmi160_get_int_status(BMI160_INT_STATUS_ALL, &int_status, &bmi160dev); + current_time = coines_get_millis(); + + /* Enters only if the obtained interrupt is single-tap */ + if (rslt == BMI160_OK) + { + /* Enters only if the obtained interrupt is single-tap */ + if (int_status.bit.s_tap) + { + printf("Single tap, iter:%d, time:%d ms, delta:%d ms, int_status:0x%x\n", + loop++, + current_time, + current_time - last_time, + int_status.data[0]); + } + /* Enters only if the obtained interrupt is double-tap */ + else if (int_status.bit.d_tap) + { + printf("Double tap, iter:%d, time:%d ms, delta:%d ms, int_status:0x%x\n", + loop++, + current_time, + current_time - last_time, + int_status.data[0]); + } + + fflush(stdout); + } + else + { + break; + } + + memset(int_status.data, 0x00, sizeof(int_status.data)); + last_time = current_time; + } + + /* Disable tap feature */ + printf("\nDisable tap test...\n"); + rslt = set_tap_config(BMI160_DISABLE); + printf("bmi160_set_int_config(tap enable) status:%d\n", rslt); + + fflush(stdout); + } + + coines_close_comm_intf(COINES_COMM_INTF_USB); + + return EXIT_SUCCESS; +} + +static int8_t set_tap_config(uint8_t feature_enable) +{ + int8_t rslt = BMI160_OK; + struct bmi160_int_settg int_config; + + if (feature_enable > 0) + { + /* Select the Interrupt channel/pin */ + int_config.int_channel = BMI160_INT_CHANNEL_1; /* Interrupt channel/pin 1 */ + + /* Select the interrupt channel/pin settings */ + int_config.int_pin_settg.output_en = BMI160_ENABLE; /* Enabling interrupt pins to act as output pin */ + int_config.int_pin_settg.output_mode = BMI160_DISABLE; /* Choosing push-pull mode for interrupt pin */ + int_config.int_pin_settg.output_type = BMI160_ENABLE; /* Choosing active low output */ + int_config.int_pin_settg.edge_ctrl = BMI160_DISABLE; /* Choosing edge triggered output */ + int_config.int_pin_settg.input_en = BMI160_DISABLE; /* Disabling interrupt pin to act as input */ + int_config.int_pin_settg.latch_dur = BMI160_LATCH_DUR_NONE; /* non-latched output */ + + /* Select the Interrupt type */ + int_config.int_type = BMI160_ACC_SINGLE_TAP_INT; /* Choosing tap interrupt */ + + /* Select the Any-motion interrupt parameters */ + int_config.int_type_cfg.acc_tap_int.tap_en = BMI160_ENABLE; /* 1- Enable tap, 0- disable tap */ + int_config.int_type_cfg.acc_tap_int.tap_thr = 2; /* Set tap threshold */ + int_config.int_type_cfg.acc_tap_int.tap_dur = 2; /* Set tap duration */ + int_config.int_type_cfg.acc_tap_int.tap_shock = 0; /* Set tap shock value */ + int_config.int_type_cfg.acc_tap_int.tap_quiet = 0; /* Set tap quiet duration */ + int_config.int_type_cfg.acc_tap_int.tap_data_src = 1; /* data source 0 : filter or 1 : pre-filter */ + + /* Set the Any-motion interrupt */ + rslt = bmi160_set_int_config(&int_config, &bmi160dev); /* sensor is an instance of the structure bmi160_dev */ + printf("bmi160_set_int_config(tap enable) status:%d\n", rslt); + } + else + { + /* Select the Interrupt channel/pin */ + int_config.int_channel = BMI160_INT_CHANNEL_1; + int_config.int_pin_settg.output_en = BMI160_DISABLE; /* Disabling interrupt pins to act as output pin */ + int_config.int_pin_settg.edge_ctrl = BMI160_DISABLE; /* Choosing edge triggered output */ + + /* Select the Interrupt type */ + int_config.int_type = BMI160_ACC_SINGLE_TAP_INT; /* Choosing Tap interrupt */ + int_config.int_type_cfg.acc_tap_int.tap_en = BMI160_DISABLE; /* 1- Enable tap, 0- disable tap */ + + /* Set the Data ready interrupt */ + rslt = bmi160_set_int_config(&int_config, &bmi160dev); /* sensor is an instance of the structure bmi160_dev */ + printf("bmi160_set_int_config(tap disable) status:%d\n", rslt); + } + + return rslt; +} diff --git a/airmouse/lib/lsm6ds3tr-api/.gitsubtree b/airmouse/lib/lsm6ds3tr-api/.gitsubtree new file mode 100644 index 00000000000..9e0d9a43f52 --- /dev/null +++ b/airmouse/lib/lsm6ds3tr-api/.gitsubtree @@ -0,0 +1 @@ +https://github.com/STMicroelectronics/lsm6ds3tr-c-pid master / diff --git a/airmouse/lib/lsm6ds3tr-api/CONTRIBUTING.md b/airmouse/lib/lsm6ds3tr-api/CONTRIBUTING.md new file mode 100644 index 00000000000..bb7d8a3b89c --- /dev/null +++ b/airmouse/lib/lsm6ds3tr-api/CONTRIBUTING.md @@ -0,0 +1,33 @@ +## Contributing guide +This document serves as a checklist before contributing to this repository. It includes links to additional information if topics are unclear to you. + +This guide mainly focuses on the proper use of Git. + +### 1. Before opening an issue +To report a bug/request please enter the issue in the right repository. + +Please check the following boxes before posting an issue: +- [ ] `Make sure you are using the latest commit (major releases are Tagged, but corrections are available as new commits).` +- [ ] `Make sure your issue is a question/feedback/suggestion RELATED TO the software provided in this repository.` Otherwise, it should be discussed on the [ST Community forum](https://community.st.com/s/). +- [ ] `Make sure your issue is not already reported/fixed on GitHub or discussed in a previous issue.` Please refer to the tab issue for the list of issues and pull-requests. Do not forget to browse to the **closed** issues. + +### 2. Posting the issue +When you have checked the previous boxes, you will find two templates (Bug Report or Other Issue) available in the **Issues** tab of the repository. + +### 3. Pull Requests +STMicroelectronics is happy to receive contributions from the community, based on an initial Contributor License Agreement (CLA) procedure. + +* If you are an individual writing original source code and you are sure **you own the intellectual property**, then you need to sign an Individual CLA (https://cla.st.com). +* If you work for a company that wants also to allow you to contribute with your work, your company needs to provide a Corporate CLA (https://cla.st.com) mentioning your GitHub account name. +* If you are not sure that a CLA (Individual or Corporate) has been signed for your GitHub account, you can check here (https://cla.st.com). + +Please note that: +* The Corporate CLA will always take precedence over the Individual CLA. +* One CLA submission is sufficient for any project proposed by STMicroelectronics. + +#### How to proceed + +* We recommend to engage first a communication through an issue, in order to present your proposal and just to confirm that it corresponds to a STMicroelectronics domain or scope. +* Then fork the project to your GitHub account to further develop your contribution. Please use the latest commit version. +* Please submit one Pull Request for one new feature or proposal. This will facilitate the analysis and the final merge if accepted. + diff --git a/airmouse/lib/lsm6ds3tr-api/LICENSE b/airmouse/lib/lsm6ds3tr-api/LICENSE new file mode 100644 index 00000000000..bc7d5adf95c --- /dev/null +++ b/airmouse/lib/lsm6ds3tr-api/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2019, STMicroelectronics +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* 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. + +* 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. diff --git a/airmouse/lib/lsm6ds3tr-api/README.md b/airmouse/lib/lsm6ds3tr-api/README.md new file mode 100644 index 00000000000..06d8c34b282 --- /dev/null +++ b/airmouse/lib/lsm6ds3tr-api/README.md @@ -0,0 +1,65 @@ +![latest tag](https://img.shields.io/github/v/tag/STMicroelectronics/lsm6ds3tr-c-pid.svg?color=brightgreen) + +# 1 - Introduction + +Sensor driver for LSM6DS3TR-C sensor written in C programming language. This repository contains the sensor driver files (.h and .c) to be included, or linked directly as a git submodule, in your project. The driver is MISRA compliant and the documentation can be generated using the [Doxygen](http://www.doxygen.org/) tool. + +In order to `clone` the complete content of the repository folder, use the command: + +``` +git clone https://github.com/STMicroelectronics/LSM6DS3TR-C-PID/ +``` + +Some examples of driver usage can be found [here](https://github.com/STMicroelectronics/STMems_Standard_C_drivers). + +------ + + + +# 2 - Integration details + +The driver is platform-independent, you only need to define two functions for read and write transactions from the sensor hardware bus (ie. SPI or I²C) and an optional one to implement a delay of millisecond granularity. **A few devices integrate an extra bit in the communication protocol in order to enable multi read/write access, this bit must be managed in the read and write functions defined by the user.** Please refer to the read and write implementation in the [reference examples](https://github.com/STMicroelectronics/STMems_Standard_C_drivers/tree/master/lsm6ds3tr-c_STdC/examples). + + +### 2.a Source code integration + +- Include in your project the driver files of the sensor (.h and .c) +- Define in your code the read and write functions that use the I²C or SPI platform driver like the following: + +``` +/** Please note that is MANDATORY: return 0 -> no Error.**/ +int32_t platform_write(void *handle, uint8_t reg, const uint8_t *bufp, uint16_t len) +int32_t platform_read(void *handle, uint8_t reg, uint8_t *bufp, uint16_t len) + +/** Optional (may be required by driver) **/ +void platform_delay(uint32_t millisec) +``` + +- Declare and initialize the structure of the device interface: + +``` +xxxxxxx_ctx_t dev_ctx; /** xxxxxxx is the used part number **/ +dev_ctx.write_reg = platform_write; +dev_ctx.read_reg = platform_read; +dev_ctx.mdelay = platform_delay; + +``` + +- If needed by the platform read and write functions, initialize the handle parameter: + +``` +dev_ctx.handle = &platform_handle; +``` + +Some integration examples can be found [here](https://github.com/STMicroelectronics/STMems_Standard_C_drivers/tree/master/lsm6ds3tr-c_STdC/examples). + +### 2.b Required properties + +> - A standard C language compiler for the target MCU +> - A C library for the target MCU and the desired interface (ie. SPI, I²C) + +------ + +**More Information: [http://www.st.com](http://st.com/MEMS)** + +**Copyright (C) 2021 STMicroelectronics** \ No newline at end of file diff --git a/airmouse/lib/lsm6ds3tr-api/Release_Notes.html b/airmouse/lib/lsm6ds3tr-api/Release_Notes.html new file mode 100644 index 00000000000..a2700ef49cc --- /dev/null +++ b/airmouse/lib/lsm6ds3tr-api/Release_Notes.html @@ -0,0 +1,110 @@ + + + + + + + Release Notes for LSM6DS3TR-C Component + + + + + +
+
+
+

Release Notes +for LSM6DS3TR-C Component Driver

+

Copyright © 2021 STMicroelectronics
+

+ +
+

License

+

This software component is licensed by ST under BSD 3-Clause license, +the “License”. You may not use this component except in compliance with +the License. You may obtain a copy of the License at:

+

BSD 3-Clause +license

+

Purpose

+

This directory contains the LSM6DS3TR-C component drivers.

+
+
+

Update history

+
+ + +
+

Main changes

+

First release

+
    +
  • First official release [ref. DS v3.0]
  • +
+

+
+ + +
+

Main changes

+
    +
  • Add __weak directive to read/write registers routines
  • +
  • Extend stmdev_ctx_t structure with mdelay callback
  • +
  • repo name changed adding ‘-pid’ extension
  • +
+

+
+ + +
+

Main changes

+
    +
  • Fixed code style (Artistic Style Version 3.4.13)
  • +
  • Add “const” to ctx arg for all APIs
  • +
+

+
+ + +
+

Main changes

+
    +
  • updated README.md file with tag reference and mdelay +description
  • +
+

+
+
+
+
+
+
+
+

For complete documentation on LSM6DS3TR-C, visit: LSM6DS3TR-C

+
+

Info

+
+
+
+ + diff --git a/airmouse/lib/lsm6ds3tr-api/Release_Notes.md b/airmouse/lib/lsm6ds3tr-api/Release_Notes.md new file mode 100644 index 00000000000..120d1346db2 --- /dev/null +++ b/airmouse/lib/lsm6ds3tr-api/Release_Notes.md @@ -0,0 +1,101 @@ +--- +pagetitle: Release Notes for LSM6DS3TR-C Component +lang: en +header-includes: +--- + +::: {.row} +::: {.col-sm-12 .col-lg-4} + +
+# Release Notes for LSM6DS3TR-C Component Driver +Copyright © 2021 STMicroelectronics\ + +[![ST logo](_htmresc/st_logo_2020.png)](https://www.st.com){.logo} +
+ +# License + +This software component is licensed by ST under BSD 3-Clause license, the "License". +You may not use this component except in compliance with the License. You may obtain a copy of the License at: + +[BSD 3-Clause license](https://opensource.org/licenses/BSD-3-Clause) + +# Purpose + +This directory contains the LSM6DS3TR-C component drivers. +::: + +::: {.col-sm-12 .col-lg-8} +# Update history + +::: {.collapse} + + +
+ +## Main changes + +### First release + +- First official release [ref. DS v3.0] + +## + +
+ + + +
+ +## Main changes + +- Add __weak directive to read/write registers routines +- Extend stmdev_ctx_t structure with mdelay callback +- repo name changed adding '-pid' extension + +## + +
+ + + +
+ +## Main changes + +- Fixed code style (Artistic Style Version 3.4.13) +- Add "const" to ctx arg for all APIs + +## + +
+ + + +
+ +## Main changes + +- updated README.md file with tag reference and mdelay description + +## + +
+::: + +::: +::: + +
+::: {.columns} +::: {.column width="95%"} +For complete documentation on LSM6DS3TR-C, +visit: +[LSM6DS3TR-C](https://www.st.com/content/st_com/en/products/mems-and-sensors/inemo-inertial-modules/lsm6ds3tr-c.html) +::: +::: {.column width="5%"} +Info +::: +::: +
diff --git a/airmouse/lib/lsm6ds3tr-api/_htmresc/favicon.png b/airmouse/lib/lsm6ds3tr-api/_htmresc/favicon.png new file mode 100644 index 00000000000..06713eec497 Binary files /dev/null and b/airmouse/lib/lsm6ds3tr-api/_htmresc/favicon.png differ diff --git a/airmouse/lib/lsm6ds3tr-api/_htmresc/mini-st_2020.css b/airmouse/lib/lsm6ds3tr-api/_htmresc/mini-st_2020.css new file mode 100644 index 00000000000..986f4d42050 --- /dev/null +++ b/airmouse/lib/lsm6ds3tr-api/_htmresc/mini-st_2020.css @@ -0,0 +1,1711 @@ +@charset "UTF-8"; +/* + Flavor name: Custom (mini-custom) + Generated online - https://minicss.org/flavors + mini.css version: v3.0.1 +*/ +/* + Browsers resets and base typography. +*/ +/* Core module CSS variable definitions */ +:root { + --fore-color: #03234b; + --secondary-fore-color: #03234b; + --back-color: #ffffff; + --secondary-back-color: #ffffff; + --blockquote-color: #e6007e; + --pre-color: #e6007e; + --border-color: #3cb4e6; + --secondary-border-color: #3cb4e6; + --heading-ratio: 1.2; + --universal-margin: 0.5rem; + --universal-padding: 0.25rem; + --universal-border-radius: 0.075rem; + --background-margin: 1.5%; + --a-link-color: #3cb4e6; + --a-visited-color: #8c0078; } + +html { + font-size: 13.5px; } + +a, b, del, em, i, ins, q, span, strong, u { + font-size: 1em; } + +html, * { + font-family: -apple-system, BlinkMacSystemFont, Helvetica, arial, sans-serif; + line-height: 1.25; + -webkit-text-size-adjust: 100%; } + +* { + font-size: 1rem; } + +body { + margin: 0; + color: var(--fore-color); + @background: var(--back-color); + background: var(--back-color) linear-gradient(#ffd200, #ffd200) repeat-y left top; + background-size: var(--background-margin); + } + +details { + display: block; } + +summary { + display: list-item; } + +abbr[title] { + border-bottom: none; + text-decoration: underline dotted; } + +input { + overflow: visible; } + +img { + max-width: 100%; + height: auto; } + +h1, h2, h3, h4, h5, h6 { + line-height: 1.25; + margin: calc(1.5 * var(--universal-margin)) var(--universal-margin); + font-weight: 400; } + h1 small, h2 small, h3 small, h4 small, h5 small, h6 small { + color: var(--secondary-fore-color); + display: block; + margin-top: -0.25rem; } + +h1 { + font-size: calc(1rem * var(--heading-ratio) * var(--heading-ratio) * var(--heading-ratio)); } + +h2 { + font-size: calc(1rem * var(--heading-ratio) * var(--heading-ratio) ); + border-style: none none solid none ; + border-width: thin; + border-color: var(--border-color); } +h3 { + font-size: calc(1rem * var(--heading-ratio) ); } + +h4 { + font-size: calc(1rem * var(--heading-ratio)); } + +h5 { + font-size: 1rem; } + +h6 { + font-size: calc(1rem / var(--heading-ratio)); } + +p { + margin: var(--universal-margin); } + +ol, ul { + margin: var(--universal-margin); + padding-left: calc(3 * var(--universal-margin)); } + +b, strong { + font-weight: 700; } + +hr { + box-sizing: content-box; + border: 0; + line-height: 1.25em; + margin: var(--universal-margin); + height: 0.0714285714rem; + background: linear-gradient(to right, transparent, var(--border-color) 20%, var(--border-color) 80%, transparent); } + +blockquote { + display: block; + position: relative; + font-style: italic; + color: var(--secondary-fore-color); + margin: var(--universal-margin); + padding: calc(3 * var(--universal-padding)); + border: 0.0714285714rem solid var(--secondary-border-color); + border-left: 0.3rem solid var(--blockquote-color); + border-radius: 0 var(--universal-border-radius) var(--universal-border-radius) 0; } + blockquote:before { + position: absolute; + top: calc(0rem - var(--universal-padding)); + left: 0; + font-family: sans-serif; + font-size: 2rem; + font-weight: 800; + content: "\201c"; + color: var(--blockquote-color); } + blockquote[cite]:after { + font-style: normal; + font-size: 0.75em; + font-weight: 700; + content: "\a— " attr(cite); + white-space: pre; } + +code, kbd, pre, samp { + font-family: Menlo, Consolas, monospace; + font-size: 0.85em; } + +code { + background: var(--secondary-back-color); + border-radius: var(--universal-border-radius); + padding: calc(var(--universal-padding) / 4) calc(var(--universal-padding) / 2); } + +kbd { + background: var(--fore-color); + color: var(--back-color); + border-radius: var(--universal-border-radius); + padding: calc(var(--universal-padding) / 4) calc(var(--universal-padding) / 2); } + +pre { + overflow: auto; + background: var(--secondary-back-color); + padding: calc(1.5 * var(--universal-padding)); + margin: var(--universal-margin); + border: 0.0714285714rem solid var(--secondary-border-color); + border-left: 0.2857142857rem solid var(--pre-color); + border-radius: 0 var(--universal-border-radius) var(--universal-border-radius) 0; } + +sup, sub, code, kbd { + line-height: 0; + position: relative; + vertical-align: baseline; } + +small, sup, sub, figcaption { + font-size: 0.75em; } + +sup { + top: -0.5em; } + +sub { + bottom: -0.25em; } + +figure { + margin: var(--universal-margin); } + +figcaption { + color: var(--secondary-fore-color); } + +a { + text-decoration: none; } + a:link { + color: var(--a-link-color); } + a:visited { + color: var(--a-visited-color); } + a:hover, a:focus { + text-decoration: underline; } + +/* + Definitions for the grid system, cards and containers. +*/ +.container { + margin: 0 auto; + padding: 0 calc(1.5 * var(--universal-padding)); } + +.row { + box-sizing: border-box; + display: flex; + flex: 0 1 auto; + flex-flow: row wrap; + margin: 0 0 0 var(--background-margin); } + +.col-sm, +[class^='col-sm-'], +[class^='col-sm-offset-'], +.row[class*='cols-sm-'] > * { + box-sizing: border-box; + flex: 0 0 auto; + padding: 0 calc(var(--universal-padding) / 2); } + +.col-sm, +.row.cols-sm > * { + max-width: 100%; + flex-grow: 1; + flex-basis: 0; } + +.col-sm-1, +.row.cols-sm-1 > * { + max-width: 8.3333333333%; + flex-basis: 8.3333333333%; } + +.col-sm-offset-0 { + margin-left: 0; } + +.col-sm-2, +.row.cols-sm-2 > * { + max-width: 16.6666666667%; + flex-basis: 16.6666666667%; } + +.col-sm-offset-1 { + margin-left: 8.3333333333%; } + +.col-sm-3, +.row.cols-sm-3 > * { + max-width: 25%; + flex-basis: 25%; } + +.col-sm-offset-2 { + margin-left: 16.6666666667%; } + +.col-sm-4, +.row.cols-sm-4 > * { + max-width: 33.3333333333%; + flex-basis: 33.3333333333%; } + +.col-sm-offset-3 { + margin-left: 25%; } + +.col-sm-5, +.row.cols-sm-5 > * { + max-width: 41.6666666667%; + flex-basis: 41.6666666667%; } + +.col-sm-offset-4 { + margin-left: 33.3333333333%; } + +.col-sm-6, +.row.cols-sm-6 > * { + max-width: 50%; + flex-basis: 50%; } + +.col-sm-offset-5 { + margin-left: 41.6666666667%; } + +.col-sm-7, +.row.cols-sm-7 > * { + max-width: 58.3333333333%; + flex-basis: 58.3333333333%; } + +.col-sm-offset-6 { + margin-left: 50%; } + +.col-sm-8, +.row.cols-sm-8 > * { + max-width: 66.6666666667%; + flex-basis: 66.6666666667%; } + +.col-sm-offset-7 { + margin-left: 58.3333333333%; } + +.col-sm-9, +.row.cols-sm-9 > * { + max-width: 75%; + flex-basis: 75%; } + +.col-sm-offset-8 { + margin-left: 66.6666666667%; } + +.col-sm-10, +.row.cols-sm-10 > * { + max-width: 83.3333333333%; + flex-basis: 83.3333333333%; } + +.col-sm-offset-9 { + margin-left: 75%; } + +.col-sm-11, +.row.cols-sm-11 > * { + max-width: 91.6666666667%; + flex-basis: 91.6666666667%; } + +.col-sm-offset-10 { + margin-left: 83.3333333333%; } + +.col-sm-12, +.row.cols-sm-12 > * { + max-width: 100%; + flex-basis: 100%; } + +.col-sm-offset-11 { + margin-left: 91.6666666667%; } + +.col-sm-normal { + order: initial; } + +.col-sm-first { + order: -999; } + +.col-sm-last { + order: 999; } + +@media screen and (min-width: 500px) { + .col-md, + [class^='col-md-'], + [class^='col-md-offset-'], + .row[class*='cols-md-'] > * { + box-sizing: border-box; + flex: 0 0 auto; + padding: 0 calc(var(--universal-padding) / 2); } + + .col-md, + .row.cols-md > * { + max-width: 100%; + flex-grow: 1; + flex-basis: 0; } + + .col-md-1, + .row.cols-md-1 > * { + max-width: 8.3333333333%; + flex-basis: 8.3333333333%; } + + .col-md-offset-0 { + margin-left: 0; } + + .col-md-2, + .row.cols-md-2 > * { + max-width: 16.6666666667%; + flex-basis: 16.6666666667%; } + + .col-md-offset-1 { + margin-left: 8.3333333333%; } + + .col-md-3, + .row.cols-md-3 > * { + max-width: 25%; + flex-basis: 25%; } + + .col-md-offset-2 { + margin-left: 16.6666666667%; } + + .col-md-4, + .row.cols-md-4 > * { + max-width: 33.3333333333%; + flex-basis: 33.3333333333%; } + + .col-md-offset-3 { + margin-left: 25%; } + + .col-md-5, + .row.cols-md-5 > * { + max-width: 41.6666666667%; + flex-basis: 41.6666666667%; } + + .col-md-offset-4 { + margin-left: 33.3333333333%; } + + .col-md-6, + .row.cols-md-6 > * { + max-width: 50%; + flex-basis: 50%; } + + .col-md-offset-5 { + margin-left: 41.6666666667%; } + + .col-md-7, + .row.cols-md-7 > * { + max-width: 58.3333333333%; + flex-basis: 58.3333333333%; } + + .col-md-offset-6 { + margin-left: 50%; } + + .col-md-8, + .row.cols-md-8 > * { + max-width: 66.6666666667%; + flex-basis: 66.6666666667%; } + + .col-md-offset-7 { + margin-left: 58.3333333333%; } + + .col-md-9, + .row.cols-md-9 > * { + max-width: 75%; + flex-basis: 75%; } + + .col-md-offset-8 { + margin-left: 66.6666666667%; } + + .col-md-10, + .row.cols-md-10 > * { + max-width: 83.3333333333%; + flex-basis: 83.3333333333%; } + + .col-md-offset-9 { + margin-left: 75%; } + + .col-md-11, + .row.cols-md-11 > * { + max-width: 91.6666666667%; + flex-basis: 91.6666666667%; } + + .col-md-offset-10 { + margin-left: 83.3333333333%; } + + .col-md-12, + .row.cols-md-12 > * { + max-width: 100%; + flex-basis: 100%; } + + .col-md-offset-11 { + margin-left: 91.6666666667%; } + + .col-md-normal { + order: initial; } + + .col-md-first { + order: -999; } + + .col-md-last { + order: 999; } } +@media screen and (min-width: 1280px) { + .col-lg, + [class^='col-lg-'], + [class^='col-lg-offset-'], + .row[class*='cols-lg-'] > * { + box-sizing: border-box; + flex: 0 0 auto; + padding: 0 calc(var(--universal-padding) / 2); } + + .col-lg, + .row.cols-lg > * { + max-width: 100%; + flex-grow: 1; + flex-basis: 0; } + + .col-lg-1, + .row.cols-lg-1 > * { + max-width: 8.3333333333%; + flex-basis: 8.3333333333%; } + + .col-lg-offset-0 { + margin-left: 0; } + + .col-lg-2, + .row.cols-lg-2 > * { + max-width: 16.6666666667%; + flex-basis: 16.6666666667%; } + + .col-lg-offset-1 { + margin-left: 8.3333333333%; } + + .col-lg-3, + .row.cols-lg-3 > * { + max-width: 25%; + flex-basis: 25%; } + + .col-lg-offset-2 { + margin-left: 16.6666666667%; } + + .col-lg-4, + .row.cols-lg-4 > * { + max-width: 33.3333333333%; + flex-basis: 33.3333333333%; } + + .col-lg-offset-3 { + margin-left: 25%; } + + .col-lg-5, + .row.cols-lg-5 > * { + max-width: 41.6666666667%; + flex-basis: 41.6666666667%; } + + .col-lg-offset-4 { + margin-left: 33.3333333333%; } + + .col-lg-6, + .row.cols-lg-6 > * { + max-width: 50%; + flex-basis: 50%; } + + .col-lg-offset-5 { + margin-left: 41.6666666667%; } + + .col-lg-7, + .row.cols-lg-7 > * { + max-width: 58.3333333333%; + flex-basis: 58.3333333333%; } + + .col-lg-offset-6 { + margin-left: 50%; } + + .col-lg-8, + .row.cols-lg-8 > * { + max-width: 66.6666666667%; + flex-basis: 66.6666666667%; } + + .col-lg-offset-7 { + margin-left: 58.3333333333%; } + + .col-lg-9, + .row.cols-lg-9 > * { + max-width: 75%; + flex-basis: 75%; } + + .col-lg-offset-8 { + margin-left: 66.6666666667%; } + + .col-lg-10, + .row.cols-lg-10 > * { + max-width: 83.3333333333%; + flex-basis: 83.3333333333%; } + + .col-lg-offset-9 { + margin-left: 75%; } + + .col-lg-11, + .row.cols-lg-11 > * { + max-width: 91.6666666667%; + flex-basis: 91.6666666667%; } + + .col-lg-offset-10 { + margin-left: 83.3333333333%; } + + .col-lg-12, + .row.cols-lg-12 > * { + max-width: 100%; + flex-basis: 100%; } + + .col-lg-offset-11 { + margin-left: 91.6666666667%; } + + .col-lg-normal { + order: initial; } + + .col-lg-first { + order: -999; } + + .col-lg-last { + order: 999; } } +/* Card component CSS variable definitions */ +:root { + --card-back-color: #3cb4e6; + --card-fore-color: #03234b; + --card-border-color: #03234b; } + +.card { + display: flex; + flex-direction: column; + justify-content: space-between; + align-self: center; + position: relative; + width: 100%; + background: var(--card-back-color); + color: var(--card-fore-color); + border: 0.0714285714rem solid var(--card-border-color); + border-radius: var(--universal-border-radius); + margin: var(--universal-margin); + overflow: hidden; } + @media screen and (min-width: 320px) { + .card { + max-width: 320px; } } + .card > .sectione { + background: var(--card-back-color); + color: var(--card-fore-color); + box-sizing: border-box; + margin: 0; + border: 0; + border-radius: 0; + border-bottom: 0.0714285714rem solid var(--card-border-color); + padding: var(--universal-padding); + width: 100%; } + .card > .sectione.media { + height: 200px; + padding: 0; + -o-object-fit: cover; + object-fit: cover; } + .card > .sectione:last-child { + border-bottom: 0; } + +/* + Custom elements for card elements. +*/ +@media screen and (min-width: 240px) { + .card.small { + max-width: 240px; } } +@media screen and (min-width: 480px) { + .card.large { + max-width: 480px; } } +.card.fluid { + max-width: 100%; + width: auto; } + +.card.warning { + --card-back-color: #e5b8b7; + --card-fore-color: #3b234b; + --card-border-color: #8c0078; } + +.card.error { + --card-back-color: #464650; + --card-fore-color: #ffffff; + --card-border-color: #8c0078; } + +.card > .sectione.dark { + --card-back-color: #3b234b; + --card-fore-color: #ffffff; } + +.card > .sectione.double-padded { + padding: calc(1.5 * var(--universal-padding)); } + +/* + Definitions for forms and input elements. +*/ +/* Input_control module CSS variable definitions */ +:root { + --form-back-color: #ffe97f; + --form-fore-color: #03234b; + --form-border-color: #3cb4e6; + --input-back-color: #ffffff; + --input-fore-color: #03234b; + --input-border-color: #3cb4e6; + --input-focus-color: #0288d1; + --input-invalid-color: #d32f2f; + --button-back-color: #e2e2e2; + --button-hover-back-color: #dcdcdc; + --button-fore-color: #212121; + --button-border-color: transparent; + --button-hover-border-color: transparent; + --button-group-border-color: rgba(124, 124, 124, 0.54); } + +form { + background: var(--form-back-color); + color: var(--form-fore-color); + border: 0.0714285714rem solid var(--form-border-color); + border-radius: var(--universal-border-radius); + margin: var(--universal-margin); + padding: calc(2 * var(--universal-padding)) var(--universal-padding); } + +fieldset { + border: 0.0714285714rem solid var(--form-border-color); + border-radius: var(--universal-border-radius); + margin: calc(var(--universal-margin) / 4); + padding: var(--universal-padding); } + +legend { + box-sizing: border-box; + display: table; + max-width: 100%; + white-space: normal; + font-weight: 500; + padding: calc(var(--universal-padding) / 2); } + +label { + padding: calc(var(--universal-padding) / 2) var(--universal-padding); } + +.input-group { + display: inline-block; } + .input-group.fluid { + display: flex; + align-items: center; + justify-content: center; } + .input-group.fluid > input { + max-width: 100%; + flex-grow: 1; + flex-basis: 0px; } + @media screen and (max-width: 499px) { + .input-group.fluid { + align-items: stretch; + flex-direction: column; } } + .input-group.vertical { + display: flex; + align-items: stretch; + flex-direction: column; } + .input-group.vertical > input { + max-width: 100%; + flex-grow: 1; + flex-basis: 0px; } + +[type="number"]::-webkit-inner-spin-button, [type="number"]::-webkit-outer-spin-button { + height: auto; } + +[type="search"] { + -webkit-appearance: textfield; + outline-offset: -2px; } + +[type="search"]::-webkit-search-cancel-button, +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; } + +input:not([type]), [type="text"], [type="email"], [type="number"], [type="search"], +[type="password"], [type="url"], [type="tel"], [type="checkbox"], [type="radio"], textarea, select { + box-sizing: border-box; + background: var(--input-back-color); + color: var(--input-fore-color); + border: 0.0714285714rem solid var(--input-border-color); + border-radius: var(--universal-border-radius); + margin: calc(var(--universal-margin) / 2); + padding: var(--universal-padding) calc(1.5 * var(--universal-padding)); } + +input:not([type="button"]):not([type="submit"]):not([type="reset"]):hover, input:not([type="button"]):not([type="submit"]):not([type="reset"]):focus, textarea:hover, textarea:focus, select:hover, select:focus { + border-color: var(--input-focus-color); + box-shadow: none; } +input:not([type="button"]):not([type="submit"]):not([type="reset"]):invalid, input:not([type="button"]):not([type="submit"]):not([type="reset"]):focus:invalid, textarea:invalid, textarea:focus:invalid, select:invalid, select:focus:invalid { + border-color: var(--input-invalid-color); + box-shadow: none; } +input:not([type="button"]):not([type="submit"]):not([type="reset"])[readonly], textarea[readonly], select[readonly] { + background: var(--secondary-back-color); } + +select { + max-width: 100%; } + +option { + overflow: hidden; + text-overflow: ellipsis; } + +[type="checkbox"], [type="radio"] { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + position: relative; + height: calc(1rem + var(--universal-padding) / 2); + width: calc(1rem + var(--universal-padding) / 2); + vertical-align: text-bottom; + padding: 0; + flex-basis: calc(1rem + var(--universal-padding) / 2) !important; + flex-grow: 0 !important; } + [type="checkbox"]:checked:before, [type="radio"]:checked:before { + position: absolute; } + +[type="checkbox"]:checked:before { + content: '\2713'; + font-family: sans-serif; + font-size: calc(1rem + var(--universal-padding) / 2); + top: calc(0rem - var(--universal-padding)); + left: calc(var(--universal-padding) / 4); } + +[type="radio"] { + border-radius: 100%; } + [type="radio"]:checked:before { + border-radius: 100%; + content: ''; + top: calc(0.0714285714rem + var(--universal-padding) / 2); + left: calc(0.0714285714rem + var(--universal-padding) / 2); + background: var(--input-fore-color); + width: 0.5rem; + height: 0.5rem; } + +:placeholder-shown { + color: var(--input-fore-color); } + +::-ms-placeholder { + color: var(--input-fore-color); + opacity: 0.54; } + +button::-moz-focus-inner, [type="button"]::-moz-focus-inner, [type="reset"]::-moz-focus-inner, [type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; } + +button, html [type="button"], [type="reset"], [type="submit"] { + -webkit-appearance: button; } + +button { + overflow: visible; + text-transform: none; } + +button, [type="button"], [type="submit"], [type="reset"], +a.button, label.button, .button, +a[role="button"], label[role="button"], [role="button"] { + display: inline-block; + background: var(--button-back-color); + color: var(--button-fore-color); + border: 0.0714285714rem solid var(--button-border-color); + border-radius: var(--universal-border-radius); + padding: var(--universal-padding) calc(1.5 * var(--universal-padding)); + margin: var(--universal-margin); + text-decoration: none; + cursor: pointer; + transition: background 0.3s; } + button:hover, button:focus, [type="button"]:hover, [type="button"]:focus, [type="submit"]:hover, [type="submit"]:focus, [type="reset"]:hover, [type="reset"]:focus, + a.button:hover, + a.button:focus, label.button:hover, label.button:focus, .button:hover, .button:focus, + a[role="button"]:hover, + a[role="button"]:focus, label[role="button"]:hover, label[role="button"]:focus, [role="button"]:hover, [role="button"]:focus { + background: var(--button-hover-back-color); + border-color: var(--button-hover-border-color); } + +input:disabled, input[disabled], textarea:disabled, textarea[disabled], select:disabled, select[disabled], button:disabled, button[disabled], .button:disabled, .button[disabled], [role="button"]:disabled, [role="button"][disabled] { + cursor: not-allowed; + opacity: 0.75; } + +.button-group { + display: flex; + border: 0.0714285714rem solid var(--button-group-border-color); + border-radius: var(--universal-border-radius); + margin: var(--universal-margin); } + .button-group > button, .button-group [type="button"], .button-group > [type="submit"], .button-group > [type="reset"], .button-group > .button, .button-group > [role="button"] { + margin: 0; + max-width: 100%; + flex: 1 1 auto; + text-align: center; + border: 0; + border-radius: 0; + box-shadow: none; } + .button-group > :not(:first-child) { + border-left: 0.0714285714rem solid var(--button-group-border-color); } + @media screen and (max-width: 499px) { + .button-group { + flex-direction: column; } + .button-group > :not(:first-child) { + border: 0; + border-top: 0.0714285714rem solid var(--button-group-border-color); } } + +/* + Custom elements for forms and input elements. +*/ +button.primary, [type="button"].primary, [type="submit"].primary, [type="reset"].primary, .button.primary, [role="button"].primary { + --button-back-color: #1976d2; + --button-fore-color: #f8f8f8; } + button.primary:hover, button.primary:focus, [type="button"].primary:hover, [type="button"].primary:focus, [type="submit"].primary:hover, [type="submit"].primary:focus, [type="reset"].primary:hover, [type="reset"].primary:focus, .button.primary:hover, .button.primary:focus, [role="button"].primary:hover, [role="button"].primary:focus { + --button-hover-back-color: #1565c0; } + +button.secondary, [type="button"].secondary, [type="submit"].secondary, [type="reset"].secondary, .button.secondary, [role="button"].secondary { + --button-back-color: #d32f2f; + --button-fore-color: #f8f8f8; } + button.secondary:hover, button.secondary:focus, [type="button"].secondary:hover, [type="button"].secondary:focus, [type="submit"].secondary:hover, [type="submit"].secondary:focus, [type="reset"].secondary:hover, [type="reset"].secondary:focus, .button.secondary:hover, .button.secondary:focus, [role="button"].secondary:hover, [role="button"].secondary:focus { + --button-hover-back-color: #c62828; } + +button.tertiary, [type="button"].tertiary, [type="submit"].tertiary, [type="reset"].tertiary, .button.tertiary, [role="button"].tertiary { + --button-back-color: #308732; + --button-fore-color: #f8f8f8; } + button.tertiary:hover, button.tertiary:focus, [type="button"].tertiary:hover, [type="button"].tertiary:focus, [type="submit"].tertiary:hover, [type="submit"].tertiary:focus, [type="reset"].tertiary:hover, [type="reset"].tertiary:focus, .button.tertiary:hover, .button.tertiary:focus, [role="button"].tertiary:hover, [role="button"].tertiary:focus { + --button-hover-back-color: #277529; } + +button.inverse, [type="button"].inverse, [type="submit"].inverse, [type="reset"].inverse, .button.inverse, [role="button"].inverse { + --button-back-color: #212121; + --button-fore-color: #f8f8f8; } + button.inverse:hover, button.inverse:focus, [type="button"].inverse:hover, [type="button"].inverse:focus, [type="submit"].inverse:hover, [type="submit"].inverse:focus, [type="reset"].inverse:hover, [type="reset"].inverse:focus, .button.inverse:hover, .button.inverse:focus, [role="button"].inverse:hover, [role="button"].inverse:focus { + --button-hover-back-color: #111; } + +button.small, [type="button"].small, [type="submit"].small, [type="reset"].small, .button.small, [role="button"].small { + padding: calc(0.5 * var(--universal-padding)) calc(0.75 * var(--universal-padding)); + margin: var(--universal-margin); } + +button.large, [type="button"].large, [type="submit"].large, [type="reset"].large, .button.large, [role="button"].large { + padding: calc(1.5 * var(--universal-padding)) calc(2 * var(--universal-padding)); + margin: var(--universal-margin); } + +/* + Definitions for navigation elements. +*/ +/* Navigation module CSS variable definitions */ +:root { + --header-back-color: #03234b; + --header-hover-back-color: #ffd200; + --header-fore-color: #ffffff; + --header-border-color: #3cb4e6; + --nav-back-color: #ffffff; + --nav-hover-back-color: #ffe97f; + --nav-fore-color: #e6007e; + --nav-border-color: #3cb4e6; + --nav-link-color: #3cb4e6; + --footer-fore-color: #ffffff; + --footer-back-color: #03234b; + --footer-border-color: #3cb4e6; + --footer-link-color: #3cb4e6; + --drawer-back-color: #ffffff; + --drawer-hover-back-color: #ffe97f; + --drawer-border-color: #3cb4e6; + --drawer-close-color: #e6007e; } + +header { + height: 2.75rem; + background: var(--header-back-color); + color: var(--header-fore-color); + border-bottom: 0.0714285714rem solid var(--header-border-color); + padding: calc(var(--universal-padding) / 4) 0; + white-space: nowrap; + overflow-x: auto; + overflow-y: hidden; } + header.row { + box-sizing: content-box; } + header .logo { + color: var(--header-fore-color); + font-size: 1.75rem; + padding: var(--universal-padding) calc(2 * var(--universal-padding)); + text-decoration: none; } + header button, header [type="button"], header .button, header [role="button"] { + box-sizing: border-box; + position: relative; + top: calc(0rem - var(--universal-padding) / 4); + height: calc(3.1875rem + var(--universal-padding) / 2); + background: var(--header-back-color); + line-height: calc(3.1875rem - var(--universal-padding) * 1.5); + text-align: center; + color: var(--header-fore-color); + border: 0; + border-radius: 0; + margin: 0; + text-transform: uppercase; } + header button:hover, header button:focus, header [type="button"]:hover, header [type="button"]:focus, header .button:hover, header .button:focus, header [role="button"]:hover, header [role="button"]:focus { + background: var(--header-hover-back-color); } + +nav { + background: var(--nav-back-color); + color: var(--nav-fore-color); + border: 0.0714285714rem solid var(--nav-border-color); + border-radius: var(--universal-border-radius); + margin: var(--universal-margin); } + nav * { + padding: var(--universal-padding) calc(1.5 * var(--universal-padding)); } + nav a, nav a:visited { + display: block; + color: var(--nav-link-color); + border-radius: var(--universal-border-radius); + transition: background 0.3s; } + nav a:hover, nav a:focus, nav a:visited:hover, nav a:visited:focus { + text-decoration: none; + background: var(--nav-hover-back-color); } + nav .sublink-1 { + position: relative; + margin-left: calc(2 * var(--universal-padding)); } + nav .sublink-1:before { + position: absolute; + left: calc(var(--universal-padding) - 1 * var(--universal-padding)); + top: -0.0714285714rem; + content: ''; + height: 100%; + border: 0.0714285714rem solid var(--nav-border-color); + border-left: 0; } + nav .sublink-2 { + position: relative; + margin-left: calc(4 * var(--universal-padding)); } + nav .sublink-2:before { + position: absolute; + left: calc(var(--universal-padding) - 3 * var(--universal-padding)); + top: -0.0714285714rem; + content: ''; + height: 100%; + border: 0.0714285714rem solid var(--nav-border-color); + border-left: 0; } + +footer { + background: var(--footer-back-color); + color: var(--footer-fore-color); + border-top: 0.0714285714rem solid var(--footer-border-color); + padding: calc(2 * var(--universal-padding)) var(--universal-padding); + font-size: 0.875rem; } + footer a, footer a:visited { + color: var(--footer-link-color); } + +header.sticky { + position: -webkit-sticky; + position: sticky; + z-index: 1101; + top: 0; } + +footer.sticky { + position: -webkit-sticky; + position: sticky; + z-index: 1101; + bottom: 0; } + +.drawer-toggle:before { + display: inline-block; + position: relative; + vertical-align: bottom; + content: '\00a0\2261\00a0'; + font-family: sans-serif; + font-size: 1.5em; } +@media screen and (min-width: 500px) { + .drawer-toggle:not(.persistent) { + display: none; } } + +[type="checkbox"].drawer { + height: 1px; + width: 1px; + margin: -1px; + overflow: hidden; + position: absolute; + clip: rect(0 0 0 0); + -webkit-clip-path: inset(100%); + clip-path: inset(100%); } + [type="checkbox"].drawer + * { + display: block; + box-sizing: border-box; + position: fixed; + top: 0; + width: 320px; + height: 100vh; + overflow-y: auto; + background: var(--drawer-back-color); + border: 0.0714285714rem solid var(--drawer-border-color); + border-radius: 0; + margin: 0; + z-index: 1110; + right: -320px; + transition: right 0.3s; } + [type="checkbox"].drawer + * .drawer-close { + position: absolute; + top: var(--universal-margin); + right: var(--universal-margin); + z-index: 1111; + width: 2rem; + height: 2rem; + border-radius: var(--universal-border-radius); + padding: var(--universal-padding); + margin: 0; + cursor: pointer; + transition: background 0.3s; } + [type="checkbox"].drawer + * .drawer-close:before { + display: block; + content: '\00D7'; + color: var(--drawer-close-color); + position: relative; + font-family: sans-serif; + font-size: 2rem; + line-height: 1; + text-align: center; } + [type="checkbox"].drawer + * .drawer-close:hover, [type="checkbox"].drawer + * .drawer-close:focus { + background: var(--drawer-hover-back-color); } + @media screen and (max-width: 320px) { + [type="checkbox"].drawer + * { + width: 100%; } } + [type="checkbox"].drawer:checked + * { + right: 0; } + @media screen and (min-width: 500px) { + [type="checkbox"].drawer:not(.persistent) + * { + position: static; + height: 100%; + z-index: 1100; } + [type="checkbox"].drawer:not(.persistent) + * .drawer-close { + display: none; } } + +/* + Definitions for the responsive table component. +*/ +/* Table module CSS variable definitions. */ +:root { + --table-border-color: #03234b; + --table-border-separator-color: #03234b; + --table-head-back-color: #03234b; + --table-head-fore-color: #ffffff; + --table-body-back-color: #ffffff; + --table-body-fore-color: #03234b; + --table-body-alt-back-color: #f4f4f4; } + +table { + border-collapse: separate; + border-spacing: 0; + margin: 0; + display: flex; + flex: 0 1 auto; + flex-flow: row wrap; + padding: var(--universal-padding); + padding-top: 0; } + table caption { + font-size: 1rem; + margin: calc(2 * var(--universal-margin)) 0; + max-width: 100%; + flex: 0 0 100%; } + table thead, table tbody { + display: flex; + flex-flow: row wrap; + border: 0.0714285714rem solid var(--table-border-color); } + table thead { + z-index: 999; + border-radius: var(--universal-border-radius) var(--universal-border-radius) 0 0; + border-bottom: 0.0714285714rem solid var(--table-border-separator-color); } + table tbody { + border-top: 0; + margin-top: calc(0 - var(--universal-margin)); + border-radius: 0 0 var(--universal-border-radius) var(--universal-border-radius); } + table tr { + display: flex; + padding: 0; } + table th, table td { + padding: calc(0.5 * var(--universal-padding)); + font-size: 0.9rem; } + table th { + text-align: left; + background: var(--table-head-back-color); + color: var(--table-head-fore-color); } + table td { + background: var(--table-body-back-color); + color: var(--table-body-fore-color); + border-top: 0.0714285714rem solid var(--table-border-color); } + +table:not(.horizontal) { + overflow: auto; + max-height: 100%; } + table:not(.horizontal) thead, table:not(.horizontal) tbody { + max-width: 100%; + flex: 0 0 100%; } + table:not(.horizontal) tr { + flex-flow: row wrap; + flex: 0 0 100%; } + table:not(.horizontal) th, table:not(.horizontal) td { + flex: 1 0 0%; + overflow: hidden; + text-overflow: ellipsis; } + table:not(.horizontal) thead { + position: sticky; + top: 0; } + table:not(.horizontal) tbody tr:first-child td { + border-top: 0; } + +table.horizontal { + border: 0; } + table.horizontal thead, table.horizontal tbody { + border: 0; + flex: .2 0 0; + flex-flow: row nowrap; } + table.horizontal tbody { + overflow: auto; + justify-content: space-between; + flex: .8 0 0; + margin-left: 0; + padding-bottom: calc(var(--universal-padding) / 4); } + table.horizontal tr { + flex-direction: column; + flex: 1 0 auto; } + table.horizontal th, table.horizontal td { + width: auto; + border: 0; + border-bottom: 0.0714285714rem solid var(--table-border-color); } + table.horizontal th:not(:first-child), table.horizontal td:not(:first-child) { + border-top: 0; } + table.horizontal th { + text-align: right; + border-left: 0.0714285714rem solid var(--table-border-color); + border-right: 0.0714285714rem solid var(--table-border-separator-color); } + table.horizontal thead tr:first-child { + padding-left: 0; } + table.horizontal th:first-child, table.horizontal td:first-child { + border-top: 0.0714285714rem solid var(--table-border-color); } + table.horizontal tbody tr:last-child td { + border-right: 0.0714285714rem solid var(--table-border-color); } + table.horizontal tbody tr:last-child td:first-child { + border-top-right-radius: 0.25rem; } + table.horizontal tbody tr:last-child td:last-child { + border-bottom-right-radius: 0.25rem; } + table.horizontal thead tr:first-child th:first-child { + border-top-left-radius: 0.25rem; } + table.horizontal thead tr:first-child th:last-child { + border-bottom-left-radius: 0.25rem; } + +@media screen and (max-width: 499px) { + table, table.horizontal { + border-collapse: collapse; + border: 0; + width: 100%; + display: table; } + table thead, table th, table.horizontal thead, table.horizontal th { + border: 0; + height: 1px; + width: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + clip: rect(0 0 0 0); + -webkit-clip-path: inset(100%); + clip-path: inset(100%); } + table tbody, table.horizontal tbody { + border: 0; + display: table-row-group; } + table tr, table.horizontal tr { + display: block; + border: 0.0714285714rem solid var(--table-border-color); + border-radius: var(--universal-border-radius); + background: #ffffff; + padding: var(--universal-padding); + margin: var(--universal-margin); + margin-bottom: calc(1 * var(--universal-margin)); } + table th, table td, table.horizontal th, table.horizontal td { + width: auto; } + table td, table.horizontal td { + display: block; + border: 0; + text-align: right; } + table td:before, table.horizontal td:before { + content: attr(data-label); + float: left; + font-weight: 600; } + table th:first-child, table td:first-child, table.horizontal th:first-child, table.horizontal td:first-child { + border-top: 0; } + table tbody tr:last-child td, table.horizontal tbody tr:last-child td { + border-right: 0; } } +table tr:nth-of-type(2n) > td { + background: var(--table-body-alt-back-color); } + +@media screen and (max-width: 500px) { + table tr:nth-of-type(2n) { + background: var(--table-body-alt-back-color); } } +:root { + --table-body-hover-back-color: #90caf9; } + +table.hoverable tr:hover, table.hoverable tr:hover > td, table.hoverable tr:focus, table.hoverable tr:focus > td { + background: var(--table-body-hover-back-color); } + +@media screen and (max-width: 500px) { + table.hoverable tr:hover, table.hoverable tr:hover > td, table.hoverable tr:focus, table.hoverable tr:focus > td { + background: var(--table-body-hover-back-color); } } +/* + Definitions for contextual background elements, toasts and tooltips. +*/ +/* Contextual module CSS variable definitions */ +:root { + --mark-back-color: #3cb4e6; + --mark-fore-color: #ffffff; } + +mark { + background: var(--mark-back-color); + color: var(--mark-fore-color); + font-size: 0.95em; + line-height: 1em; + border-radius: var(--universal-border-radius); + padding: calc(var(--universal-padding) / 4) var(--universal-padding); } + mark.inline-block { + display: inline-block; + font-size: 1em; + line-height: 1.4; + padding: calc(var(--universal-padding) / 2) var(--universal-padding); } + +:root { + --toast-back-color: #424242; + --toast-fore-color: #fafafa; } + +.toast { + position: fixed; + bottom: calc(var(--universal-margin) * 3); + left: 50%; + transform: translate(-50%, -50%); + z-index: 1111; + color: var(--toast-fore-color); + background: var(--toast-back-color); + border-radius: calc(var(--universal-border-radius) * 16); + padding: var(--universal-padding) calc(var(--universal-padding) * 3); } + +:root { + --tooltip-back-color: #212121; + --tooltip-fore-color: #fafafa; } + +.tooltip { + position: relative; + display: inline-block; } + .tooltip:before, .tooltip:after { + position: absolute; + opacity: 0; + clip: rect(0 0 0 0); + -webkit-clip-path: inset(100%); + clip-path: inset(100%); + transition: all 0.3s; + z-index: 1010; + left: 50%; } + .tooltip:not(.bottom):before, .tooltip:not(.bottom):after { + bottom: 75%; } + .tooltip.bottom:before, .tooltip.bottom:after { + top: 75%; } + .tooltip:hover:before, .tooltip:hover:after, .tooltip:focus:before, .tooltip:focus:after { + opacity: 1; + clip: auto; + -webkit-clip-path: inset(0%); + clip-path: inset(0%); } + .tooltip:before { + content: ''; + background: transparent; + border: var(--universal-margin) solid transparent; + left: calc(50% - var(--universal-margin)); } + .tooltip:not(.bottom):before { + border-top-color: #212121; } + .tooltip.bottom:before { + border-bottom-color: #212121; } + .tooltip:after { + content: attr(aria-label); + color: var(--tooltip-fore-color); + background: var(--tooltip-back-color); + border-radius: var(--universal-border-radius); + padding: var(--universal-padding); + white-space: nowrap; + transform: translateX(-50%); } + .tooltip:not(.bottom):after { + margin-bottom: calc(2 * var(--universal-margin)); } + .tooltip.bottom:after { + margin-top: calc(2 * var(--universal-margin)); } + +:root { + --modal-overlay-color: rgba(0, 0, 0, 0.45); + --modal-close-color: #e6007e; + --modal-close-hover-color: #ffe97f; } + +[type="checkbox"].modal { + height: 1px; + width: 1px; + margin: -1px; + overflow: hidden; + position: absolute; + clip: rect(0 0 0 0); + -webkit-clip-path: inset(100%); + clip-path: inset(100%); } + [type="checkbox"].modal + div { + position: fixed; + top: 0; + left: 0; + display: none; + width: 100vw; + height: 100vh; + background: var(--modal-overlay-color); } + [type="checkbox"].modal + div .card { + margin: 0 auto; + max-height: 50vh; + overflow: auto; } + [type="checkbox"].modal + div .card .modal-close { + position: absolute; + top: 0; + right: 0; + width: 1.75rem; + height: 1.75rem; + border-radius: var(--universal-border-radius); + padding: var(--universal-padding); + margin: 0; + cursor: pointer; + transition: background 0.3s; } + [type="checkbox"].modal + div .card .modal-close:before { + display: block; + content: '\00D7'; + color: var(--modal-close-color); + position: relative; + font-family: sans-serif; + font-size: 1.75rem; + line-height: 1; + text-align: center; } + [type="checkbox"].modal + div .card .modal-close:hover, [type="checkbox"].modal + div .card .modal-close:focus { + background: var(--modal-close-hover-color); } + [type="checkbox"].modal:checked + div { + display: flex; + flex: 0 1 auto; + z-index: 1200; } + [type="checkbox"].modal:checked + div .card .modal-close { + z-index: 1211; } + +:root { + --collapse-label-back-color: #03234b; + --collapse-label-fore-color: #ffffff; + --collapse-label-hover-back-color: #3cb4e6; + --collapse-selected-label-back-color: #3cb4e6; + --collapse-border-color: var(--collapse-label-back-color); + --collapse-selected-border-color: #ceecf8; + --collapse-content-back-color: #ffffff; + --collapse-selected-label-border-color: #3cb4e6; } + +.collapse { + width: calc(100% - 2 * var(--universal-margin)); + opacity: 1; + display: flex; + flex-direction: column; + margin: var(--universal-margin); + border-radius: var(--universal-border-radius); } + .collapse > [type="radio"], .collapse > [type="checkbox"] { + height: 1px; + width: 1px; + margin: -1px; + overflow: hidden; + position: absolute; + clip: rect(0 0 0 0); + -webkit-clip-path: inset(100%); + clip-path: inset(100%); } + .collapse > label { + flex-grow: 1; + display: inline-block; + height: 1.25rem; + cursor: pointer; + transition: background 0.2s; + color: var(--collapse-label-fore-color); + background: var(--collapse-label-back-color); + border: 0.0714285714rem solid var(--collapse-selected-border-color); + padding: calc(1.25 * var(--universal-padding)); } + .collapse > label:hover, .collapse > label:focus { + background: var(--collapse-label-hover-back-color); } + .collapse > label + div { + flex-basis: auto; + height: 1px; + width: 1px; + margin: -1px; + overflow: hidden; + position: absolute; + clip: rect(0 0 0 0); + -webkit-clip-path: inset(100%); + clip-path: inset(100%); + transition: max-height 0.3s; + max-height: 1px; } + .collapse > :checked + label { + background: var(--collapse-selected-label-back-color); + border-color: var(--collapse-selected-label-border-color); } + .collapse > :checked + label + div { + box-sizing: border-box; + position: relative; + width: 100%; + height: auto; + overflow: auto; + margin: 0; + background: var(--collapse-content-back-color); + border: 0.0714285714rem solid var(--collapse-selected-border-color); + border-top: 0; + padding: var(--universal-padding); + clip: auto; + -webkit-clip-path: inset(0%); + clip-path: inset(0%); + max-height: 100%; } + .collapse > label:not(:first-of-type) { + border-top: 0; } + .collapse > label:first-of-type { + border-radius: var(--universal-border-radius) var(--universal-border-radius) 0 0; } + .collapse > label:last-of-type:not(:first-of-type) { + border-radius: 0 0 var(--universal-border-radius) var(--universal-border-radius); } + .collapse > label:last-of-type:first-of-type { + border-radius: var(--universal-border-radius); } + .collapse > :checked:last-of-type:not(:first-of-type) + label { + border-radius: 0; } + .collapse > :checked:last-of-type + label + div { + border-radius: 0 0 var(--universal-border-radius) var(--universal-border-radius); } + +/* + Custom elements for contextual background elements, toasts and tooltips. +*/ +mark.tertiary { + --mark-back-color: #3cb4e6; } + +mark.tag { + padding: calc(var(--universal-padding)/2) var(--universal-padding); + border-radius: 1em; } + +/* + Definitions for progress elements and spinners. +*/ +/* Progress module CSS variable definitions */ +:root { + --progress-back-color: #3cb4e6; + --progress-fore-color: #555; } + +progress { + display: block; + vertical-align: baseline; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + height: 0.75rem; + width: calc(100% - 2 * var(--universal-margin)); + margin: var(--universal-margin); + border: 0; + border-radius: calc(2 * var(--universal-border-radius)); + background: var(--progress-back-color); + color: var(--progress-fore-color); } + progress::-webkit-progress-value { + background: var(--progress-fore-color); + border-top-left-radius: calc(2 * var(--universal-border-radius)); + border-bottom-left-radius: calc(2 * var(--universal-border-radius)); } + progress::-webkit-progress-bar { + background: var(--progress-back-color); } + progress::-moz-progress-bar { + background: var(--progress-fore-color); + border-top-left-radius: calc(2 * var(--universal-border-radius)); + border-bottom-left-radius: calc(2 * var(--universal-border-radius)); } + progress[value="1000"]::-webkit-progress-value { + border-radius: calc(2 * var(--universal-border-radius)); } + progress[value="1000"]::-moz-progress-bar { + border-radius: calc(2 * var(--universal-border-radius)); } + progress.inline { + display: inline-block; + vertical-align: middle; + width: 60%; } + +:root { + --spinner-back-color: #ddd; + --spinner-fore-color: #555; } + +@keyframes spinner-donut-anim { + 0% { + transform: rotate(0deg); } + 100% { + transform: rotate(360deg); } } +.spinner { + display: inline-block; + margin: var(--universal-margin); + border: 0.25rem solid var(--spinner-back-color); + border-left: 0.25rem solid var(--spinner-fore-color); + border-radius: 50%; + width: 1.25rem; + height: 1.25rem; + animation: spinner-donut-anim 1.2s linear infinite; } + +/* + Custom elements for progress bars and spinners. +*/ +progress.primary { + --progress-fore-color: #1976d2; } + +progress.secondary { + --progress-fore-color: #d32f2f; } + +progress.tertiary { + --progress-fore-color: #308732; } + +.spinner.primary { + --spinner-fore-color: #1976d2; } + +.spinner.secondary { + --spinner-fore-color: #d32f2f; } + +.spinner.tertiary { + --spinner-fore-color: #308732; } + +/* + Definitions for icons - powered by Feather (https://feathericons.com/). +*/ +span[class^='icon-'] { + display: inline-block; + height: 1em; + width: 1em; + vertical-align: -0.125em; + background-size: contain; + margin: 0 calc(var(--universal-margin) / 4); } + span[class^='icon-'].secondary { + -webkit-filter: invert(25%); + filter: invert(25%); } + span[class^='icon-'].inverse { + -webkit-filter: invert(100%); + filter: invert(100%); } + +span.icon-alert { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12' y2='16'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-bookmark { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z'%3E%3C/path%3E%3C/svg%3E"); } +span.icon-calendar { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-credit { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='1' y='4' width='22' height='16' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='1' y1='10' x2='23' y2='10'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-edit { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 14.66V20a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h5.34'%3E%3C/path%3E%3Cpolygon points='18 2 22 6 12 16 8 16 8 12 18 2'%3E%3C/polygon%3E%3C/svg%3E"); } +span.icon-link { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6'%3E%3C/path%3E%3Cpolyline points='15 3 21 3 21 9'%3E%3C/polyline%3E%3Cline x1='10' y1='14' x2='21' y2='3'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-help { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3'%3E%3C/path%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='17' x2='12' y2='17'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-home { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z'%3E%3C/path%3E%3Cpolyline points='9 22 9 12 15 12 15 22'%3E%3C/polyline%3E%3C/svg%3E"); } +span.icon-info { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='16' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='8' x2='12' y2='8'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-lock { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='11' width='18' height='11' rx='2' ry='2'%3E%3C/rect%3E%3Cpath d='M7 11V7a5 5 0 0 1 10 0v4'%3E%3C/path%3E%3C/svg%3E"); } +span.icon-mail { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z'%3E%3C/path%3E%3Cpolyline points='22,6 12,13 2,6'%3E%3C/polyline%3E%3C/svg%3E"); } +span.icon-location { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z'%3E%3C/path%3E%3Ccircle cx='12' cy='10' r='3'%3E%3C/circle%3E%3C/svg%3E"); } +span.icon-phone { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z'%3E%3C/path%3E%3C/svg%3E"); } +span.icon-rss { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 11a9 9 0 0 1 9 9'%3E%3C/path%3E%3Cpath d='M4 4a16 16 0 0 1 16 16'%3E%3C/path%3E%3Ccircle cx='5' cy='19' r='1'%3E%3C/circle%3E%3C/svg%3E"); } +span.icon-search { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-settings { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='3'%3E%3C/circle%3E%3Cpath d='M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z'%3E%3C/path%3E%3C/svg%3E"); } +span.icon-share { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='18' cy='5' r='3'%3E%3C/circle%3E%3Ccircle cx='6' cy='12' r='3'%3E%3C/circle%3E%3Ccircle cx='18' cy='19' r='3'%3E%3C/circle%3E%3Cline x1='8.59' y1='13.51' x2='15.42' y2='17.49'%3E%3C/line%3E%3Cline x1='15.41' y1='6.51' x2='8.59' y2='10.49'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-cart { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='9' cy='21' r='1'%3E%3C/circle%3E%3Ccircle cx='20' cy='21' r='1'%3E%3C/circle%3E%3Cpath d='M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6'%3E%3C/path%3E%3C/svg%3E"); } +span.icon-upload { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4'%3E%3C/path%3E%3Cpolyline points='17 8 12 3 7 8'%3E%3C/polyline%3E%3Cline x1='12' y1='3' x2='12' y2='15'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-user { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2'%3E%3C/path%3E%3Ccircle cx='12' cy='7' r='4'%3E%3C/circle%3E%3C/svg%3E"); } + +/* + Definitions for STMicroelectronics icons (https://brandportal.st.com/document/26). +*/ +span.icon-st-update { + background-image: url("Update.svg"); } +span.icon-st-add { + background-image: url("Add button.svg"); } + +/* + Definitions for utilities and helper classes. +*/ +/* Utility module CSS variable definitions */ +:root { + --generic-border-color: rgba(0, 0, 0, 0.3); + --generic-box-shadow: 0 0.2857142857rem 0.2857142857rem 0 rgba(0, 0, 0, 0.125), 0 0.1428571429rem 0.1428571429rem -0.1428571429rem rgba(0, 0, 0, 0.125); } + +.hidden { + display: none !important; } + +.visually-hidden { + position: absolute !important; + width: 1px !important; + height: 1px !important; + margin: -1px !important; + border: 0 !important; + padding: 0 !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(100%) !important; + clip-path: inset(100%) !important; + overflow: hidden !important; } + +.bordered { + border: 0.0714285714rem solid var(--generic-border-color) !important; } + +.rounded { + border-radius: var(--universal-border-radius) !important; } + +.circular { + border-radius: 50% !important; } + +.shadowed { + box-shadow: var(--generic-box-shadow) !important; } + +.responsive-margin { + margin: calc(var(--universal-margin) / 4) !important; } + @media screen and (min-width: 500px) { + .responsive-margin { + margin: calc(var(--universal-margin) / 2) !important; } } + @media screen and (min-width: 1280px) { + .responsive-margin { + margin: var(--universal-margin) !important; } } + +.responsive-padding { + padding: calc(var(--universal-padding) / 4) !important; } + @media screen and (min-width: 500px) { + .responsive-padding { + padding: calc(var(--universal-padding) / 2) !important; } } + @media screen and (min-width: 1280px) { + .responsive-padding { + padding: var(--universal-padding) !important; } } + +@media screen and (max-width: 499px) { + .hidden-sm { + display: none !important; } } +@media screen and (min-width: 500px) and (max-width: 1279px) { + .hidden-md { + display: none !important; } } +@media screen and (min-width: 1280px) { + .hidden-lg { + display: none !important; } } +@media screen and (max-width: 499px) { + .visually-hidden-sm { + position: absolute !important; + width: 1px !important; + height: 1px !important; + margin: -1px !important; + border: 0 !important; + padding: 0 !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(100%) !important; + clip-path: inset(100%) !important; + overflow: hidden !important; } } +@media screen and (min-width: 500px) and (max-width: 1279px) { + .visually-hidden-md { + position: absolute !important; + width: 1px !important; + height: 1px !important; + margin: -1px !important; + border: 0 !important; + padding: 0 !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(100%) !important; + clip-path: inset(100%) !important; + overflow: hidden !important; } } +@media screen and (min-width: 1280px) { + .visually-hidden-lg { + position: absolute !important; + width: 1px !important; + height: 1px !important; + margin: -1px !important; + border: 0 !important; + padding: 0 !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(100%) !important; + clip-path: inset(100%) !important; + overflow: hidden !important; } } + +/*# sourceMappingURL=mini-custom.css.map */ + +img[alt="ST logo"] { display: block; margin: auto; width: 75%; max-width: 250px; min-width: 71px; } +img[alt="Cube logo"] { float: right; width: 30%; max-width: 10rem; min-width: 8rem; padding-right: 1rem;} + +.figure { + display: block; + margin-left: auto; + margin-right: auto; + text-align: center; +} \ No newline at end of file diff --git a/airmouse/lib/lsm6ds3tr-api/_htmresc/st_logo_2020.png b/airmouse/lib/lsm6ds3tr-api/_htmresc/st_logo_2020.png new file mode 100644 index 00000000000..d6cebb5ac70 Binary files /dev/null and b/airmouse/lib/lsm6ds3tr-api/_htmresc/st_logo_2020.png differ diff --git a/airmouse/lib/lsm6ds3tr-api/lsm6ds3tr-c_reg.c b/airmouse/lib/lsm6ds3tr-api/lsm6ds3tr-c_reg.c new file mode 100644 index 00000000000..6bc987f60cd --- /dev/null +++ b/airmouse/lib/lsm6ds3tr-api/lsm6ds3tr-c_reg.c @@ -0,0 +1,8219 @@ +/** + ****************************************************************************** + * @file lsm6ds3tr_c_reg.c + * @author Sensors Software Solution Team + * @brief LSM6DS3TR_C driver file + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +#include "lsm6ds3tr-c_reg.h" + +/** + * @defgroup LSM6DS3TR_C + * @brief This file provides a set of functions needed to drive the + * lsm6ds3tr_c enanced inertial module. + * @{ + * + */ + +/** + * @defgroup LSM6DS3TR_C_interfaces_functions + * @brief This section provide a set of functions used to read and + * write a generic register of the device. + * MANDATORY: return 0 -> no Error. + * @{ + * + */ + +/** + * @brief Read generic device register + * + * @param ctx read / write interface definitions(ptr) + * @param reg register to read + * @param data pointer to buffer that store the data read(ptr) + * @param len number of consecutive register to read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t __weak lsm6ds3tr_c_read_reg(const stmdev_ctx_t *ctx, uint8_t reg, + uint8_t *data, + uint16_t len) +{ + int32_t ret; + + if (ctx == NULL) + { + return -1; + } + + ret = ctx->read_reg(ctx->handle, reg, data, len); + + return ret; +} + +/** + * @brief Write generic device register + * + * @param ctx read / write interface definitions(ptr) + * @param reg register to write + * @param data pointer to data to write in register reg(ptr) + * @param len number of consecutive register to write + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t __weak lsm6ds3tr_c_write_reg(const stmdev_ctx_t *ctx, uint8_t reg, + uint8_t *data, + uint16_t len) +{ + int32_t ret; + + if (ctx == NULL) + { + return -1; + } + + ret = ctx->write_reg(ctx->handle, reg, data, len); + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DS3TR_C_Sensitivity + * @brief These functions convert raw-data into engineering units. + * @{ + * + */ + +float_t lsm6ds3tr_c_from_fs2g_to_mg(int16_t lsb) +{ + return ((float_t)lsb * 0.061f); +} + +float_t lsm6ds3tr_c_from_fs4g_to_mg(int16_t lsb) +{ + return ((float_t)lsb * 0.122f); +} + +float_t lsm6ds3tr_c_from_fs8g_to_mg(int16_t lsb) +{ + return ((float_t)lsb * 0.244f); +} + +float_t lsm6ds3tr_c_from_fs16g_to_mg(int16_t lsb) +{ + return ((float_t)lsb * 0.488f); +} + +float_t lsm6ds3tr_c_from_fs125dps_to_mdps(int16_t lsb) +{ + return ((float_t)lsb * 4.375f); +} + +float_t lsm6ds3tr_c_from_fs250dps_to_mdps(int16_t lsb) +{ + return ((float_t)lsb * 8.750f); +} + +float_t lsm6ds3tr_c_from_fs500dps_to_mdps(int16_t lsb) +{ + return ((float_t)lsb * 17.50f); +} + +float_t lsm6ds3tr_c_from_fs1000dps_to_mdps(int16_t lsb) +{ + return ((float_t)lsb * 35.0f); +} + +float_t lsm6ds3tr_c_from_fs2000dps_to_mdps(int16_t lsb) +{ + return ((float_t)lsb * 70.0f); +} + +float_t lsm6ds3tr_c_from_lsb_to_celsius(int16_t lsb) +{ + return (((float_t)lsb / 256.0f) + 25.0f); +} + +/** + * @} + * + */ + + +/** + * @defgroup LSM6DS3TR_C_data_generation + * @brief This section groups all the functions concerning data + * generation + * @{ + * + */ + +/** + * @brief Accelerometer full-scale selection.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of fs_xl in reg CTRL1_XL + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_xl_full_scale_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_fs_xl_t val) +{ + lsm6ds3tr_c_ctrl1_xl_t ctrl1_xl; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL1_XL, + (uint8_t *)&ctrl1_xl, 1); + + if (ret == 0) + { + ctrl1_xl.fs_xl = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL1_XL, + (uint8_t *)&ctrl1_xl, 1); + } + + return ret; +} + +/** + * @brief Accelerometer full-scale selection.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of fs_xl in reg CTRL1_XL + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_xl_full_scale_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_fs_xl_t *val) +{ + lsm6ds3tr_c_ctrl1_xl_t ctrl1_xl; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL1_XL, + (uint8_t *)&ctrl1_xl, 1); + + switch (ctrl1_xl.fs_xl) + { + case LSM6DS3TR_C_2g: + *val = LSM6DS3TR_C_2g; + break; + + case LSM6DS3TR_C_16g: + *val = LSM6DS3TR_C_16g; + break; + + case LSM6DS3TR_C_4g: + *val = LSM6DS3TR_C_4g; + break; + + case LSM6DS3TR_C_8g: + *val = LSM6DS3TR_C_8g; + break; + + default: + *val = LSM6DS3TR_C_XL_FS_ND; + break; + } + + return ret; +} + +/** + * @brief Accelerometer data rate selection.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of odr_xl in reg CTRL1_XL + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_xl_data_rate_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_odr_xl_t val) +{ + lsm6ds3tr_c_ctrl1_xl_t ctrl1_xl; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL1_XL, + (uint8_t *)&ctrl1_xl, 1); + + if (ret == 0) + { + ctrl1_xl.odr_xl = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL1_XL, + (uint8_t *)&ctrl1_xl, 1); + } + + return ret; +} + +/** + * @brief Accelerometer data rate selection.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of odr_xl in reg CTRL1_XL + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_xl_data_rate_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_odr_xl_t *val) +{ + lsm6ds3tr_c_ctrl1_xl_t ctrl1_xl; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL1_XL, + (uint8_t *)&ctrl1_xl, 1); + + switch (ctrl1_xl.odr_xl) + { + case LSM6DS3TR_C_XL_ODR_OFF: + *val = LSM6DS3TR_C_XL_ODR_OFF; + break; + + case LSM6DS3TR_C_XL_ODR_12Hz5: + *val = LSM6DS3TR_C_XL_ODR_12Hz5; + break; + + case LSM6DS3TR_C_XL_ODR_26Hz: + *val = LSM6DS3TR_C_XL_ODR_26Hz; + break; + + case LSM6DS3TR_C_XL_ODR_52Hz: + *val = LSM6DS3TR_C_XL_ODR_52Hz; + break; + + case LSM6DS3TR_C_XL_ODR_104Hz: + *val = LSM6DS3TR_C_XL_ODR_104Hz; + break; + + case LSM6DS3TR_C_XL_ODR_208Hz: + *val = LSM6DS3TR_C_XL_ODR_208Hz; + break; + + case LSM6DS3TR_C_XL_ODR_416Hz: + *val = LSM6DS3TR_C_XL_ODR_416Hz; + break; + + case LSM6DS3TR_C_XL_ODR_833Hz: + *val = LSM6DS3TR_C_XL_ODR_833Hz; + break; + + case LSM6DS3TR_C_XL_ODR_1k66Hz: + *val = LSM6DS3TR_C_XL_ODR_1k66Hz; + break; + + case LSM6DS3TR_C_XL_ODR_3k33Hz: + *val = LSM6DS3TR_C_XL_ODR_3k33Hz; + break; + + case LSM6DS3TR_C_XL_ODR_6k66Hz: + *val = LSM6DS3TR_C_XL_ODR_6k66Hz; + break; + + case LSM6DS3TR_C_XL_ODR_1Hz6: + *val = LSM6DS3TR_C_XL_ODR_1Hz6; + break; + + default: + *val = LSM6DS3TR_C_XL_ODR_ND; + break; + } + + return ret; +} + +/** + * @brief Gyroscope chain full-scale selection.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of fs_g in reg CTRL2_G + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_gy_full_scale_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_fs_g_t val) +{ + lsm6ds3tr_c_ctrl2_g_t ctrl2_g; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL2_G, + (uint8_t *)&ctrl2_g, 1); + + if (ret == 0) + { + ctrl2_g.fs_g = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL2_G, + (uint8_t *)&ctrl2_g, 1); + } + + return ret; +} + +/** + * @brief Gyroscope chain full-scale selection.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of fs_g in reg CTRL2_G + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_gy_full_scale_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_fs_g_t *val) +{ + lsm6ds3tr_c_ctrl2_g_t ctrl2_g; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL2_G, + (uint8_t *)&ctrl2_g, 1); + + switch (ctrl2_g.fs_g) + { + case LSM6DS3TR_C_250dps: + *val = LSM6DS3TR_C_250dps; + break; + + case LSM6DS3TR_C_125dps: + *val = LSM6DS3TR_C_125dps; + break; + + case LSM6DS3TR_C_500dps: + *val = LSM6DS3TR_C_500dps; + break; + + case LSM6DS3TR_C_1000dps: + *val = LSM6DS3TR_C_1000dps; + break; + + case LSM6DS3TR_C_2000dps: + *val = LSM6DS3TR_C_2000dps; + break; + + default: + *val = LSM6DS3TR_C_GY_FS_ND; + break; + } + + return ret; +} + +/** + * @brief Gyroscope data rate selection.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of odr_g in reg CTRL2_G + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_gy_data_rate_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_odr_g_t val) +{ + lsm6ds3tr_c_ctrl2_g_t ctrl2_g; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL2_G, + (uint8_t *)&ctrl2_g, 1); + + if (ret == 0) + { + ctrl2_g.odr_g = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL2_G, + (uint8_t *)&ctrl2_g, 1); + } + + return ret; +} + +/** + * @brief Gyroscope data rate selection.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of odr_g in reg CTRL2_G + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_gy_data_rate_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_odr_g_t *val) +{ + lsm6ds3tr_c_ctrl2_g_t ctrl2_g; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL2_G, + (uint8_t *)&ctrl2_g, 1); + + switch (ctrl2_g.odr_g) + { + case LSM6DS3TR_C_GY_ODR_OFF: + *val = LSM6DS3TR_C_GY_ODR_OFF; + break; + + case LSM6DS3TR_C_GY_ODR_12Hz5: + *val = LSM6DS3TR_C_GY_ODR_12Hz5; + break; + + case LSM6DS3TR_C_GY_ODR_26Hz: + *val = LSM6DS3TR_C_GY_ODR_26Hz; + break; + + case LSM6DS3TR_C_GY_ODR_52Hz: + *val = LSM6DS3TR_C_GY_ODR_52Hz; + break; + + case LSM6DS3TR_C_GY_ODR_104Hz: + *val = LSM6DS3TR_C_GY_ODR_104Hz; + break; + + case LSM6DS3TR_C_GY_ODR_208Hz: + *val = LSM6DS3TR_C_GY_ODR_208Hz; + break; + + case LSM6DS3TR_C_GY_ODR_416Hz: + *val = LSM6DS3TR_C_GY_ODR_416Hz; + break; + + case LSM6DS3TR_C_GY_ODR_833Hz: + *val = LSM6DS3TR_C_GY_ODR_833Hz; + break; + + case LSM6DS3TR_C_GY_ODR_1k66Hz: + *val = LSM6DS3TR_C_GY_ODR_1k66Hz; + break; + + case LSM6DS3TR_C_GY_ODR_3k33Hz: + *val = LSM6DS3TR_C_GY_ODR_3k33Hz; + break; + + case LSM6DS3TR_C_GY_ODR_6k66Hz: + *val = LSM6DS3TR_C_GY_ODR_6k66Hz; + break; + + default: + *val = LSM6DS3TR_C_GY_ODR_ND; + break; + } + + return ret; +} + +/** + * @brief Block data update.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of bdu in reg CTRL3_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_block_data_update_set(const stmdev_ctx_t *ctx, + uint8_t val) +{ + lsm6ds3tr_c_ctrl3_c_t ctrl3_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, + (uint8_t *)&ctrl3_c, 1); + + if (ret == 0) + { + ctrl3_c.bdu = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL3_C, + (uint8_t *)&ctrl3_c, 1); + } + + return ret; +} + +/** + * @brief Block data update.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of bdu in reg CTRL3_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_block_data_update_get(const stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6ds3tr_c_ctrl3_c_t ctrl3_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, + (uint8_t *)&ctrl3_c, 1); + *val = ctrl3_c.bdu; + + return ret; +} + +/** + * @brief Weight of XL user offset bits of registers + * X_OFS_USR(73h), Y_OFS_USR(74h), Z_OFS_USR(75h).[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of usr_off_w in reg CTRL6_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_xl_offset_weight_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_usr_off_w_t val) +{ + lsm6ds3tr_c_ctrl6_c_t ctrl6_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL6_C, + (uint8_t *)&ctrl6_c, 1); + + if (ret == 0) + { + ctrl6_c.usr_off_w = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL6_C, + (uint8_t *)&ctrl6_c, 1); + } + + return ret; +} + +/** + * @brief Weight of XL user offset bits of registers + * X_OFS_USR(73h), Y_OFS_USR(74h), Z_OFS_USR(75h).[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of usr_off_w in reg CTRL6_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_xl_offset_weight_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_usr_off_w_t *val) +{ + lsm6ds3tr_c_ctrl6_c_t ctrl6_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL6_C, + (uint8_t *)&ctrl6_c, 1); + + switch (ctrl6_c.usr_off_w) + { + case LSM6DS3TR_C_LSb_1mg: + *val = LSM6DS3TR_C_LSb_1mg; + break; + + case LSM6DS3TR_C_LSb_16mg: + *val = LSM6DS3TR_C_LSb_16mg; + break; + + default: + *val = LSM6DS3TR_C_WEIGHT_ND; + break; + } + + return ret; +} + +/** + * @brief High-performance operating mode for accelerometer[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of xl_hm_mode in reg CTRL6_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_xl_power_mode_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_xl_hm_mode_t val) +{ + lsm6ds3tr_c_ctrl6_c_t ctrl6_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL6_C, + (uint8_t *)&ctrl6_c, 1); + + if (ret == 0) + { + ctrl6_c.xl_hm_mode = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL6_C, + (uint8_t *)&ctrl6_c, 1); + } + + return ret; +} + +/** + * @brief High-performance operating mode for accelerometer.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of xl_hm_mode in reg CTRL6_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_xl_power_mode_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_xl_hm_mode_t *val) +{ + lsm6ds3tr_c_ctrl6_c_t ctrl6_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL6_C, + (uint8_t *)&ctrl6_c, 1); + + switch (ctrl6_c.xl_hm_mode) + { + case LSM6DS3TR_C_XL_HIGH_PERFORMANCE: + *val = LSM6DS3TR_C_XL_HIGH_PERFORMANCE; + break; + + case LSM6DS3TR_C_XL_NORMAL: + *val = LSM6DS3TR_C_XL_NORMAL; + break; + + default: + *val = LSM6DS3TR_C_XL_PW_MODE_ND; + break; + } + + return ret; +} + +/** + * @brief Source register rounding function on WAKE_UP_SRC (1Bh), + * TAP_SRC (1Ch), D6D_SRC (1Dh), STATUS_REG (1Eh) and + * FUNC_SRC1 (53h) registers in the primary interface.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of rounding_status in reg CTRL7_G + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_rounding_on_status_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_rounding_status_t val) +{ + lsm6ds3tr_c_ctrl7_g_t ctrl7_g; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL7_G, + (uint8_t *)&ctrl7_g, 1); + + if (ret == 0) + { + ctrl7_g.rounding_status = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL7_G, + (uint8_t *)&ctrl7_g, 1); + } + + return ret; +} + +/** + * @brief Source register rounding function on WAKE_UP_SRC (1Bh), + * TAP_SRC (1Ch), D6D_SRC (1Dh), STATUS_REG (1Eh) and + * FUNC_SRC1 (53h) registers in the primary interface.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of rounding_status in reg CTRL7_G + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_rounding_on_status_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_rounding_status_t *val) +{ + lsm6ds3tr_c_ctrl7_g_t ctrl7_g; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL7_G, + (uint8_t *)&ctrl7_g, 1); + + switch (ctrl7_g.rounding_status) + { + case LSM6DS3TR_C_STAT_RND_DISABLE: + *val = LSM6DS3TR_C_STAT_RND_DISABLE; + break; + + case LSM6DS3TR_C_STAT_RND_ENABLE: + *val = LSM6DS3TR_C_STAT_RND_ENABLE; + break; + + default: + *val = LSM6DS3TR_C_STAT_RND_ND; + break; + } + + return ret; +} + +/** + * @brief High-performance operating mode disable for gyroscope.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of g_hm_mode in reg CTRL7_G + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_gy_power_mode_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_g_hm_mode_t val) +{ + lsm6ds3tr_c_ctrl7_g_t ctrl7_g; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL7_G, + (uint8_t *)&ctrl7_g, 1); + + if (ret == 0) + { + ctrl7_g.g_hm_mode = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL7_G, + (uint8_t *)&ctrl7_g, 1); + } + + return ret; +} + +/** + * @brief High-performance operating mode disable for gyroscope.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of g_hm_mode in reg CTRL7_G + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_gy_power_mode_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_g_hm_mode_t *val) +{ + lsm6ds3tr_c_ctrl7_g_t ctrl7_g; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL7_G, + (uint8_t *)&ctrl7_g, 1); + + switch (ctrl7_g.g_hm_mode) + { + case LSM6DS3TR_C_GY_HIGH_PERFORMANCE: + *val = LSM6DS3TR_C_GY_HIGH_PERFORMANCE; + break; + + case LSM6DS3TR_C_GY_NORMAL: + *val = LSM6DS3TR_C_GY_NORMAL; + break; + + default: + *val = LSM6DS3TR_C_GY_PW_MODE_ND; + break; + } + + return ret; +} + +/** + * @brief Read all the interrupt/status flag of the device.[get] + * + * @param ctx Read / write interface definitions + * @param val WAKE_UP_SRC, TAP_SRC, D6D_SRC, STATUS_REG, + * FUNC_SRC1, FUNC_SRC2, WRIST_TILT_IA, A_WRIST_TILT_Mask + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_all_sources_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_all_sources_t *val) +{ + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_SRC, + (uint8_t *) & (val->wake_up_src), 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_SRC, + (uint8_t *) & (val->tap_src), 1); + } + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_D6D_SRC, + (uint8_t *) & (val->d6d_src), 1); + } + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_STATUS_REG, + (uint8_t *) & (val->status_reg), 1); + } + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FUNC_SRC1, + (uint8_t *) & (val->func_src1), 1); + } + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FUNC_SRC2, + (uint8_t *) & (val->func_src2), 1); + } + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WRIST_TILT_IA, + (uint8_t *) & (val->wrist_tilt_ia), 1); + } + + if (ret == 0) + { + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_B); + } + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_A_WRIST_TILT_MASK, + (uint8_t *) & (val->a_wrist_tilt_mask), 1); + } + + if (ret == 0) + { + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + + return ret; +} +/** + * @brief The STATUS_REG register is read by the primary interface[get] + * + * @param ctx Read / write interface definitions + * @param val Registers STATUS_REG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_status_reg_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_status_reg_t *val) +{ + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_STATUS_REG, + (uint8_t *) val, 1); + + return ret; +} + +/** + * @brief Accelerometer new data available.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of xlda in reg STATUS_REG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_xl_flag_data_ready_get(const stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6ds3tr_c_status_reg_t status_reg; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_STATUS_REG, + (uint8_t *)&status_reg, 1); + *val = status_reg.xlda; + + return ret; +} + +/** + * @brief Gyroscope new data available.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of gda in reg STATUS_REG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_gy_flag_data_ready_get(const stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6ds3tr_c_status_reg_t status_reg; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_STATUS_REG, + (uint8_t *)&status_reg, 1); + *val = status_reg.gda; + + return ret; +} + +/** + * @brief Temperature new data available.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of tda in reg STATUS_REG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_temp_flag_data_ready_get(const stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6ds3tr_c_status_reg_t status_reg; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_STATUS_REG, + (uint8_t *)&status_reg, 1); + *val = status_reg.tda; + + return ret; +} + +/** + * @brief Accelerometer axis user offset correction expressed in two’s + * complement, weight depends on USR_OFF_W in CTRL6_C. + * The value must be in the range [-127 127].[set] + * + * @param ctx Read / write interface definitions + * @param buff Buffer that contains data to write + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_xl_usr_offset_set(const stmdev_ctx_t *ctx, + uint8_t *buff) +{ + int32_t ret; + + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_X_OFS_USR, buff, 3); + + return ret; +} + +/** + * @brief Accelerometer axis user offset correction xpressed in two’s + * complement, weight depends on USR_OFF_W in CTRL6_C. + * The value must be in the range [-127 127].[get] + * + * @param ctx Read / write interface definitions + * @param buff Buffer that stores data read + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_xl_usr_offset_get(const stmdev_ctx_t *ctx, + uint8_t *buff) +{ + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_X_OFS_USR, buff, 3); + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DS3TR_C_Timestamp + * @brief This section groups all the functions that manage the + * timestamp generation. + * @{ + * + */ + +/** + * @brief Enable timestamp count. The count is saved in TIMESTAMP0_REG (40h), + * TIMESTAMP1_REG (41h) and TIMESTAMP2_REG (42h).[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of timer_en in reg CTRL10_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_timestamp_set(const stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6ds3tr_c_ctrl10_c_t ctrl10_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C, + (uint8_t *)&ctrl10_c, 1); + + if (ret == 0) + { + ctrl10_c.timer_en = val; + + if (val != 0x00U) + { + ctrl10_c.func_en = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL10_C, + (uint8_t *)&ctrl10_c, 1); + } + } + + return ret; +} + +/** + * @brief Enable timestamp count. The count is saved in TIMESTAMP0_REG (40h), + * TIMESTAMP1_REG (41h) and TIMESTAMP2_REG (42h).[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of timer_en in reg CTRL10_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_timestamp_get(const stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6ds3tr_c_ctrl10_c_t ctrl10_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C, + (uint8_t *)&ctrl10_c, 1); + *val = ctrl10_c.timer_en; + + return ret; +} + +/** + * @brief Timestamp register resolution setting. + * Configuration of this bit affects + * TIMESTAMP0_REG(40h), TIMESTAMP1_REG(41h), + * TIMESTAMP2_REG(42h), STEP_TIMESTAMP_L(49h), + * STEP_TIMESTAMP_H(4Ah) and + * STEP_COUNT_DELTA(15h) registers.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of timer_hr in reg WAKE_UP_DUR + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_timestamp_res_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_timer_hr_t val) +{ + lsm6ds3tr_c_wake_up_dur_t wake_up_dur; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR, + (uint8_t *)&wake_up_dur, 1); + + if (ret == 0) + { + wake_up_dur.timer_hr = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR, + (uint8_t *)&wake_up_dur, 1); + } + + return ret; +} + +/** + * @brief Timestamp register resolution setting. + * Configuration of this bit affects + * TIMESTAMP0_REG(40h), TIMESTAMP1_REG(41h), + * TIMESTAMP2_REG(42h), STEP_TIMESTAMP_L(49h), + * STEP_TIMESTAMP_H(4Ah) and + * STEP_COUNT_DELTA(15h) registers.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of timer_hr in reg WAKE_UP_DUR + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_timestamp_res_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_timer_hr_t *val) +{ + lsm6ds3tr_c_wake_up_dur_t wake_up_dur; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR, + (uint8_t *)&wake_up_dur, 1); + + switch (wake_up_dur.timer_hr) + { + case LSM6DS3TR_C_LSB_6ms4: + *val = LSM6DS3TR_C_LSB_6ms4; + break; + + case LSM6DS3TR_C_LSB_25us: + *val = LSM6DS3TR_C_LSB_25us; + break; + + default: + *val = LSM6DS3TR_C_TS_RES_ND; + break; + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DS3TR_C_Dataoutput + * @brief This section groups all the data output functions. + * @{ + * + */ + +/** + * @brief Circular burst-mode (rounding) read from output registers + * through the primary interface.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of rounding in reg CTRL5_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_rounding_mode_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_rounding_t val) +{ + lsm6ds3tr_c_ctrl5_c_t ctrl5_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL5_C, + (uint8_t *)&ctrl5_c, 1); + + if (ret == 0) + { + ctrl5_c.rounding = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL5_C, + (uint8_t *)&ctrl5_c, 1); + } + + return ret; +} + +/** + * @brief Circular burst-mode (rounding) read from output registers + * through the primary interface.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of rounding in reg CTRL5_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_rounding_mode_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_rounding_t *val) +{ + lsm6ds3tr_c_ctrl5_c_t ctrl5_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL5_C, + (uint8_t *)&ctrl5_c, 1); + + switch (ctrl5_c.rounding) + { + case LSM6DS3TR_C_ROUND_DISABLE: + *val = LSM6DS3TR_C_ROUND_DISABLE; + break; + + case LSM6DS3TR_C_ROUND_XL: + *val = LSM6DS3TR_C_ROUND_XL; + break; + + case LSM6DS3TR_C_ROUND_GY: + *val = LSM6DS3TR_C_ROUND_GY; + break; + + case LSM6DS3TR_C_ROUND_GY_XL: + *val = LSM6DS3TR_C_ROUND_GY_XL; + break; + + case LSM6DS3TR_C_ROUND_SH1_TO_SH6: + *val = LSM6DS3TR_C_ROUND_SH1_TO_SH6; + break; + + case LSM6DS3TR_C_ROUND_XL_SH1_TO_SH6: + *val = LSM6DS3TR_C_ROUND_XL_SH1_TO_SH6; + break; + + case LSM6DS3TR_C_ROUND_GY_XL_SH1_TO_SH12: + *val = LSM6DS3TR_C_ROUND_GY_XL_SH1_TO_SH12; + break; + + case LSM6DS3TR_C_ROUND_GY_XL_SH1_TO_SH6: + *val = LSM6DS3TR_C_ROUND_GY_XL_SH1_TO_SH6; + break; + + default: + *val = LSM6DS3TR_C_ROUND_OUT_ND; + break; + } + + return ret; +} + +/** + * @brief Temperature data output register (r). L and H registers together + * express a 16-bit word in two’s complement.[get] + * + * @param ctx Read / write interface definitions + * @param buff Buffer that stores data read + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_temperature_raw_get(const stmdev_ctx_t *ctx, + int16_t *val) +{ + uint8_t buff[2]; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_OUT_TEMP_L, buff, 2); + *val = (int16_t)buff[1]; + *val = (*val * 256) + (int16_t)buff[0]; + + return ret; +} + +/** + * @brief Angular rate sensor. The value is expressed as a 16-bit word in + * two’s complement.[get] + * + * @param ctx Read / write interface definitions + * @param buff Buffer that stores data read + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_angular_rate_raw_get(const stmdev_ctx_t *ctx, + int16_t *val) +{ + uint8_t buff[6]; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_OUTX_L_G, buff, 6); + val[0] = (int16_t)buff[1]; + val[0] = (val[0] * 256) + (int16_t)buff[0]; + val[1] = (int16_t)buff[3]; + val[1] = (val[1] * 256) + (int16_t)buff[2]; + val[2] = (int16_t)buff[5]; + val[2] = (val[2] * 256) + (int16_t)buff[4]; + + return ret; +} + +/** + * @brief Linear acceleration output register. The value is expressed + * as a 16-bit word in two’s complement.[get] + * + * @param ctx Read / write interface definitions + * @param buff Buffer that stores data read + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_acceleration_raw_get(const stmdev_ctx_t *ctx, + int16_t *val) +{ + uint8_t buff[6]; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_OUTX_L_XL, buff, 6); + val[0] = (int16_t)buff[1]; + val[0] = (val[0] * 256) + (int16_t)buff[0]; + val[1] = (int16_t)buff[3]; + val[1] = (val[1] * 256) + (int16_t)buff[2]; + val[2] = (int16_t)buff[5]; + val[2] = (val[2] * 256) + (int16_t)buff[4]; + + return ret; +} + +/** + * @brief External magnetometer raw data.[get] + * + * @param ctx Read / write interface definitions + * @param buff Buffer that stores data read + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_mag_calibrated_raw_get(const stmdev_ctx_t *ctx, + int16_t *val) +{ + uint8_t buff[6]; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_OUT_MAG_RAW_X_L, buff, 6); + val[0] = (int16_t)buff[1]; + val[0] = (val[0] * 256) + (int16_t)buff[0]; + val[1] = (int16_t)buff[3]; + val[1] = (val[1] * 256) + (int16_t)buff[2]; + val[2] = (int16_t)buff[5]; + val[2] = (val[2] * 256) + (int16_t)buff[4]; + + return ret; +} + +/** + * @brief Read data in FIFO.[get] + * + * @param ctx Read / write interface definitions + * @param buffer Data buffer to store FIFO data. + * @param len Number of data to read from FIFO. + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_fifo_raw_data_get(const stmdev_ctx_t *ctx, + uint8_t *buffer, + uint8_t len) +{ + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_DATA_OUT_L, buffer, + len); + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DS3TR_C_common + * @brief This section groups common useful functions. + * @{ + * + */ + +/** + * @brief Enable access to the embedded functions/sensor hub + * configuration registers[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of func_cfg_en in reg FUNC_CFG_ACCESS + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_mem_bank_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_func_cfg_en_t val) +{ + lsm6ds3tr_c_func_cfg_access_t func_cfg_access; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FUNC_CFG_ACCESS, + (uint8_t *)&func_cfg_access, 1); + + if (ret == 0) + { + func_cfg_access.func_cfg_en = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FUNC_CFG_ACCESS, + (uint8_t *)&func_cfg_access, 1); + } + + return ret; +} + +/** + * @brief Enable access to the embedded functions/sensor hub configuration + * registers[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of func_cfg_en in reg FUNC_CFG_ACCESS + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_mem_bank_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_func_cfg_en_t *val) +{ + lsm6ds3tr_c_func_cfg_access_t func_cfg_access; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FUNC_CFG_ACCESS, + (uint8_t *)&func_cfg_access, 1); + + switch (func_cfg_access.func_cfg_en) + { + case LSM6DS3TR_C_USER_BANK: + *val = LSM6DS3TR_C_USER_BANK; + break; + + case LSM6DS3TR_C_BANK_B: + *val = LSM6DS3TR_C_BANK_B; + break; + + default: + *val = LSM6DS3TR_C_BANK_ND; + break; + } + + return ret; +} + +/** + * @brief Data-ready pulsed / letched mode[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of drdy_pulsed in reg DRDY_PULSE_CFG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_data_ready_mode_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_drdy_pulsed_g_t val) +{ + lsm6ds3tr_c_drdy_pulse_cfg_g_t drdy_pulse_cfg_g; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_DRDY_PULSE_CFG_G, + (uint8_t *)&drdy_pulse_cfg_g, 1); + + if (ret == 0) + { + drdy_pulse_cfg_g.drdy_pulsed = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_DRDY_PULSE_CFG_G, + (uint8_t *)&drdy_pulse_cfg_g, 1); + } + + return ret; +} + +/** + * @brief Data-ready pulsed / letched mode[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of drdy_pulsed in reg DRDY_PULSE_CFG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_data_ready_mode_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_drdy_pulsed_g_t *val) +{ + lsm6ds3tr_c_drdy_pulse_cfg_g_t drdy_pulse_cfg_g; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_DRDY_PULSE_CFG_G, + (uint8_t *)&drdy_pulse_cfg_g, 1); + + switch (drdy_pulse_cfg_g.drdy_pulsed) + { + case LSM6DS3TR_C_DRDY_LATCHED: + *val = LSM6DS3TR_C_DRDY_LATCHED; + break; + + case LSM6DS3TR_C_DRDY_PULSED: + *val = LSM6DS3TR_C_DRDY_PULSED; + break; + + default: + *val = LSM6DS3TR_C_DRDY_ND; + break; + } + + return ret; +} + +/** + * @brief DeviceWhoamI.[get] + * + * @param ctx Read / write interface definitions + * @param buff Buffer that stores data read + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_device_id_get(const stmdev_ctx_t *ctx, uint8_t *buff) +{ + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WHO_AM_I, buff, 1); + + return ret; +} + +/** + * @brief Software reset. Restore the default values in user registers[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of sw_reset in reg CTRL3_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_reset_set(const stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6ds3tr_c_ctrl3_c_t ctrl3_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, + (uint8_t *)&ctrl3_c, 1); + + if (ret == 0) + { + ctrl3_c.sw_reset = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL3_C, + (uint8_t *)&ctrl3_c, 1); + } + + return ret; +} + +/** + * @brief Software reset. Restore the default values in user registers[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of sw_reset in reg CTRL3_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_reset_get(const stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6ds3tr_c_ctrl3_c_t ctrl3_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, + (uint8_t *)&ctrl3_c, 1); + *val = ctrl3_c.sw_reset; + + return ret; +} + +/** + * @brief Big/Little Endian Data selection.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of ble in reg CTRL3_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_data_format_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_ble_t val) +{ + lsm6ds3tr_c_ctrl3_c_t ctrl3_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, + (uint8_t *)&ctrl3_c, 1); + + if (ret == 0) + { + ctrl3_c.ble = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL3_C, + (uint8_t *)&ctrl3_c, 1); + } + + return ret; +} + +/** + * @brief Big/Little Endian Data selection.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of ble in reg CTRL3_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_data_format_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_ble_t *val) +{ + lsm6ds3tr_c_ctrl3_c_t ctrl3_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, + (uint8_t *)&ctrl3_c, 1); + + switch (ctrl3_c.ble) + { + case LSM6DS3TR_C_LSB_AT_LOW_ADD: + *val = LSM6DS3TR_C_LSB_AT_LOW_ADD; + break; + + case LSM6DS3TR_C_MSB_AT_LOW_ADD: + *val = LSM6DS3TR_C_MSB_AT_LOW_ADD; + break; + + default: + *val = LSM6DS3TR_C_DATA_FMT_ND; + break; + } + + return ret; +} + +/** + * @brief Register address automatically incremented during a multiple byte + * access with a serial interface.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of if_inc in reg CTRL3_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_auto_increment_set(const stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6ds3tr_c_ctrl3_c_t ctrl3_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, + (uint8_t *)&ctrl3_c, 1); + + if (ret == 0) + { + ctrl3_c.if_inc = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL3_C, + (uint8_t *)&ctrl3_c, 1); + } + + return ret; +} + +/** + * @brief Register address automatically incremented during a multiple byte + * access with a serial interface.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of if_inc in reg CTRL3_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_auto_increment_get(const stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6ds3tr_c_ctrl3_c_t ctrl3_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, + (uint8_t *)&ctrl3_c, 1); + *val = ctrl3_c.if_inc; + + return ret; +} + +/** + * @brief Reboot memory content. Reload the calibration parameters.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of boot in reg CTRL3_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_boot_set(const stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6ds3tr_c_ctrl3_c_t ctrl3_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, + (uint8_t *)&ctrl3_c, 1); + + if (ret == 0) + { + ctrl3_c.boot = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL3_C, + (uint8_t *)&ctrl3_c, 1); + } + + return ret; +} + +/** + * @brief Reboot memory content. Reload the calibration parameters.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of boot in reg CTRL3_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_boot_get(const stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6ds3tr_c_ctrl3_c_t ctrl3_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, + (uint8_t *)&ctrl3_c, 1); + *val = ctrl3_c.boot; + + return ret; +} + +/** + * @brief Linear acceleration sensor self-test enable.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of st_xl in reg CTRL5_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_xl_self_test_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_st_xl_t val) +{ + lsm6ds3tr_c_ctrl5_c_t ctrl5_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL5_C, + (uint8_t *)&ctrl5_c, 1); + + if (ret == 0) + { + ctrl5_c.st_xl = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL5_C, + (uint8_t *)&ctrl5_c, 1); + } + + return ret; +} + +/** + * @brief Linear acceleration sensor self-test enable.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of st_xl in reg CTRL5_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_xl_self_test_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_st_xl_t *val) +{ + lsm6ds3tr_c_ctrl5_c_t ctrl5_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL5_C, + (uint8_t *)&ctrl5_c, 1); + + switch (ctrl5_c.st_xl) + { + case LSM6DS3TR_C_XL_ST_DISABLE: + *val = LSM6DS3TR_C_XL_ST_DISABLE; + break; + + case LSM6DS3TR_C_XL_ST_POSITIVE: + *val = LSM6DS3TR_C_XL_ST_POSITIVE; + break; + + case LSM6DS3TR_C_XL_ST_NEGATIVE: + *val = LSM6DS3TR_C_XL_ST_NEGATIVE; + break; + + default: + *val = LSM6DS3TR_C_XL_ST_ND; + break; + } + + return ret; +} + +/** + * @brief Angular rate sensor self-test enable.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of st_g in reg CTRL5_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_gy_self_test_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_st_g_t val) +{ + lsm6ds3tr_c_ctrl5_c_t ctrl5_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL5_C, + (uint8_t *)&ctrl5_c, 1); + + if (ret == 0) + { + ctrl5_c.st_g = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL5_C, + (uint8_t *)&ctrl5_c, 1); + } + + return ret; +} + +/** + * @brief Angular rate sensor self-test enable.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of st_g in reg CTRL5_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_gy_self_test_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_st_g_t *val) +{ + lsm6ds3tr_c_ctrl5_c_t ctrl5_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL5_C, + (uint8_t *)&ctrl5_c, 1); + + switch (ctrl5_c.st_g) + { + case LSM6DS3TR_C_GY_ST_DISABLE: + *val = LSM6DS3TR_C_GY_ST_DISABLE; + break; + + case LSM6DS3TR_C_GY_ST_POSITIVE: + *val = LSM6DS3TR_C_GY_ST_POSITIVE; + break; + + case LSM6DS3TR_C_GY_ST_NEGATIVE: + *val = LSM6DS3TR_C_GY_ST_NEGATIVE; + break; + + default: + *val = LSM6DS3TR_C_GY_ST_ND; + break; + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DS3TR_C_filters + * @brief This section group all the functions concerning the filters + * configuration that impact both accelerometer and gyro. + * @{ + * + */ + +/** + * @brief Mask DRDY on pin (both XL & Gyro) until filter settling ends + * (XL and Gyro independently masked).[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of drdy_mask in reg CTRL4_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_filter_settling_mask_set(const stmdev_ctx_t *ctx, + uint8_t val) +{ + lsm6ds3tr_c_ctrl4_c_t ctrl4_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C, + (uint8_t *)&ctrl4_c, 1); + + if (ret == 0) + { + ctrl4_c.drdy_mask = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL4_C, + (uint8_t *)&ctrl4_c, 1); + } + + return ret; +} + +/** + * @brief Mask DRDY on pin (both XL & Gyro) until filter settling ends + * (XL and Gyro independently masked).[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of drdy_mask in reg CTRL4_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_filter_settling_mask_get(const stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6ds3tr_c_ctrl4_c_t ctrl4_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C, + (uint8_t *)&ctrl4_c, 1); + *val = ctrl4_c.drdy_mask; + + return ret; +} + +/** + * @brief HPF or SLOPE filter selection on wake-up and Activity/Inactivity + * functions.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of slope_fds in reg TAP_CFG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_xl_hp_path_internal_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_slope_fds_t val) +{ + lsm6ds3tr_c_tap_cfg_t tap_cfg; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG, + (uint8_t *)&tap_cfg, 1); + + if (ret == 0) + { + tap_cfg.slope_fds = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_CFG, + (uint8_t *)&tap_cfg, 1); + } + + return ret; +} + +/** + * @brief HPF or SLOPE filter selection on wake-up and Activity/Inactivity + * functions.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of slope_fds in reg TAP_CFG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_xl_hp_path_internal_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_slope_fds_t *val) +{ + lsm6ds3tr_c_tap_cfg_t tap_cfg; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG, + (uint8_t *)&tap_cfg, 1); + + switch (tap_cfg.slope_fds) + { + case LSM6DS3TR_C_USE_SLOPE: + *val = LSM6DS3TR_C_USE_SLOPE; + break; + + case LSM6DS3TR_C_USE_HPF: + *val = LSM6DS3TR_C_USE_HPF; + break; + + default: + *val = LSM6DS3TR_C_HP_PATH_ND; + break; + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DS3TR_C_accelerometer_filters + * @brief This section group all the functions concerning the filters + * configuration that impact accelerometer in every mode. + * @{ + * + */ + +/** + * @brief Accelerometer analog chain bandwidth selection (only for + * accelerometer ODR ≥ 1.67 kHz).[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of bw0_xl in reg CTRL1_XL + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_xl_filter_analog_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_bw0_xl_t val) +{ + lsm6ds3tr_c_ctrl1_xl_t ctrl1_xl; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL1_XL, + (uint8_t *)&ctrl1_xl, 1); + + if (ret == 0) + { + ctrl1_xl.bw0_xl = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL1_XL, + (uint8_t *)&ctrl1_xl, 1); + } + + return ret; +} + +/** + * @brief Accelerometer analog chain bandwidth selection (only for + * accelerometer ODR ≥ 1.67 kHz).[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of bw0_xl in reg CTRL1_XL + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_xl_filter_analog_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_bw0_xl_t *val) +{ + lsm6ds3tr_c_ctrl1_xl_t ctrl1_xl; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL1_XL, + (uint8_t *)&ctrl1_xl, 1); + + switch (ctrl1_xl.bw0_xl) + { + case LSM6DS3TR_C_XL_ANA_BW_1k5Hz: + *val = LSM6DS3TR_C_XL_ANA_BW_1k5Hz; + break; + + case LSM6DS3TR_C_XL_ANA_BW_400Hz: + *val = LSM6DS3TR_C_XL_ANA_BW_400Hz; + break; + + default: + *val = LSM6DS3TR_C_XL_ANA_BW_ND; + break; + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DS3TR_C_accelerometer_filters + * @brief This section group all the functions concerning the filters + * configuration that impact accelerometer. + * @{ + * + */ + +/** + * @brief Accelerometer digital LPF (LPF1) bandwidth selection LPF2 is + * not used.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of lpf1_bw_sel in reg CTRL1_XL + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_xl_lp1_bandwidth_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_lpf1_bw_sel_t val) +{ + lsm6ds3tr_c_ctrl1_xl_t ctrl1_xl; + lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL1_XL, + (uint8_t *)&ctrl1_xl, 1); + + if (ret == 0) + { + ctrl1_xl.lpf1_bw_sel = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL1_XL, + (uint8_t *)&ctrl1_xl, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL8_XL, + (uint8_t *)&ctrl8_xl, 1); + + if (ret == 0) + { + ctrl8_xl.lpf2_xl_en = 0; + ctrl8_xl.hp_slope_xl_en = 0; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL8_XL, + (uint8_t *)&ctrl8_xl, 1); + } + } + } + + return ret; +} + +/** + * @brief Accelerometer digital LPF (LPF1) bandwidth selection LPF2 + * is not used.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of lpf1_bw_sel in reg CTRL1_XL + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_xl_lp1_bandwidth_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_lpf1_bw_sel_t *val) +{ + lsm6ds3tr_c_ctrl1_xl_t ctrl1_xl; + lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL8_XL, + (uint8_t *)&ctrl8_xl, 1); + + if (ret == 0) + { + if ((ctrl8_xl.lpf2_xl_en != 0x00U) || + (ctrl8_xl.hp_slope_xl_en != 0x00U)) + { + *val = LSM6DS3TR_C_XL_LP1_NA; + } + + else + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL1_XL, + (uint8_t *)&ctrl1_xl, 1); + + switch (ctrl1_xl.lpf1_bw_sel) + { + case LSM6DS3TR_C_XL_LP1_ODR_DIV_2: + *val = LSM6DS3TR_C_XL_LP1_ODR_DIV_2; + break; + + case LSM6DS3TR_C_XL_LP1_ODR_DIV_4: + *val = LSM6DS3TR_C_XL_LP1_ODR_DIV_4; + break; + + default: + *val = LSM6DS3TR_C_XL_LP1_NA; + break; + } + } + } + + return ret; +} + +/** + * @brief LPF2 on outputs[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of input_composite in reg CTRL8_XL + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_xl_lp2_bandwidth_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_input_composite_t val) +{ + lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL8_XL, + (uint8_t *)&ctrl8_xl, 1); + + if (ret == 0) + { + ctrl8_xl.input_composite = ((uint8_t) val & 0x10U) >> 4; + ctrl8_xl.hpcf_xl = (uint8_t) val & 0x03U; + ctrl8_xl.lpf2_xl_en = 1; + ctrl8_xl.hp_slope_xl_en = 0; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL8_XL, + (uint8_t *)&ctrl8_xl, 1); + } + + return ret; +} + +/** + * @brief LPF2 on outputs[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of input_composite in reg CTRL8_XL + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_xl_lp2_bandwidth_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_input_composite_t *val) +{ + lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL8_XL, + (uint8_t *)&ctrl8_xl, 1); + + if (ret == 0) + { + if ((ctrl8_xl.lpf2_xl_en == 0x00U) || + (ctrl8_xl.hp_slope_xl_en != 0x00U)) + { + *val = LSM6DS3TR_C_XL_LP_NA; + } + + else + { + switch ((ctrl8_xl.input_composite << 4) + ctrl8_xl.hpcf_xl) + { + case LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_50: + *val = LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_50; + break; + + case LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_100: + *val = LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_100; + break; + + case LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_9: + *val = LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_9; + break; + + case LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_400: + *val = LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_400; + break; + + case LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_50: + *val = LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_50; + break; + + case LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_100: + *val = LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_100; + break; + + case LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_9: + *val = LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_9; + break; + + case LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_400: + *val = LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_400; + break; + + default: + *val = LSM6DS3TR_C_XL_LP_NA; + break; + } + } + } + + return ret; +} + +/** + * @brief Enable HP filter reference mode.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of hp_ref_mode in reg CTRL8_XL + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_xl_reference_mode_set(const stmdev_ctx_t *ctx, + uint8_t val) +{ + lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL8_XL, + (uint8_t *)&ctrl8_xl, 1); + + if (ret == 0) + { + ctrl8_xl.hp_ref_mode = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL8_XL, + (uint8_t *)&ctrl8_xl, 1); + } + + return ret; +} + +/** + * @brief Enable HP filter reference mode.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of hp_ref_mode in reg CTRL8_XL + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_xl_reference_mode_get(const stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL8_XL, + (uint8_t *)&ctrl8_xl, 1); + *val = ctrl8_xl.hp_ref_mode; + + return ret; +} + +/** + * @brief High pass/Slope on outputs.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of hpcf_xl in reg CTRL8_XL + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_xl_hp_bandwidth_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_hpcf_xl_t val) +{ + lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL8_XL, + (uint8_t *)&ctrl8_xl, 1); + + if (ret == 0) + { + ctrl8_xl.input_composite = 0; + ctrl8_xl.hpcf_xl = (uint8_t)val & 0x03U; + ctrl8_xl.hp_slope_xl_en = 1; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL8_XL, + (uint8_t *)&ctrl8_xl, 1); + } + + return ret; +} + +/** + * @brief High pass/Slope on outputs.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of hpcf_xl in reg CTRL8_XL + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_xl_hp_bandwidth_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_hpcf_xl_t *val) +{ + lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL8_XL, + (uint8_t *)&ctrl8_xl, 1); + + if (ctrl8_xl.hp_slope_xl_en == 0x00U) + { + *val = LSM6DS3TR_C_XL_HP_NA; + } + + switch (ctrl8_xl.hpcf_xl) + { + case LSM6DS3TR_C_XL_HP_ODR_DIV_4: + *val = LSM6DS3TR_C_XL_HP_ODR_DIV_4; + break; + + case LSM6DS3TR_C_XL_HP_ODR_DIV_100: + *val = LSM6DS3TR_C_XL_HP_ODR_DIV_100; + break; + + case LSM6DS3TR_C_XL_HP_ODR_DIV_9: + *val = LSM6DS3TR_C_XL_HP_ODR_DIV_9; + break; + + case LSM6DS3TR_C_XL_HP_ODR_DIV_400: + *val = LSM6DS3TR_C_XL_HP_ODR_DIV_400; + break; + + default: + *val = LSM6DS3TR_C_XL_HP_NA; + break; + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DS3TR_C_gyroscope_filters + * @brief This section group all the functions concerning the filters + * configuration that impact gyroscope. + * @{ + * + */ + +/** + * @brief Gyroscope low pass path bandwidth.[set] + * + * @param ctx Read / write interface definitions + * @param val gyroscope filtering chain configuration. + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_gy_band_pass_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_lpf1_sel_g_t val) +{ + lsm6ds3tr_c_ctrl4_c_t ctrl4_c; + lsm6ds3tr_c_ctrl6_c_t ctrl6_c; + lsm6ds3tr_c_ctrl7_g_t ctrl7_g; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL7_G, + (uint8_t *)&ctrl7_g, 1); + + if (ret == 0) + { + ctrl7_g.hpm_g = ((uint8_t)val & 0x30U) >> 4; + ctrl7_g.hp_en_g = ((uint8_t)val & 0x80U) >> 7; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL7_G, + (uint8_t *)&ctrl7_g, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL6_C, + (uint8_t *)&ctrl6_c, 1); + + if (ret == 0) + { + ctrl6_c.ftype = (uint8_t)val & 0x03U; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL6_C, + (uint8_t *)&ctrl6_c, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C, + (uint8_t *)&ctrl4_c, 1); + + if (ret == 0) + { + ctrl4_c.lpf1_sel_g = ((uint8_t)val & 0x08U) >> 3; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL4_C, + (uint8_t *)&ctrl4_c, 1); + } + } + } + } + } + + return ret; +} + +/** + * @brief Gyroscope low pass path bandwidth.[get] + * + * @param ctx Read / write interface definitions + * @param val gyroscope filtering chain + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_gy_band_pass_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_lpf1_sel_g_t *val) +{ + lsm6ds3tr_c_ctrl4_c_t ctrl4_c; + lsm6ds3tr_c_ctrl6_c_t ctrl6_c; + lsm6ds3tr_c_ctrl7_g_t ctrl7_g; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL6_C, + (uint8_t *)&ctrl6_c, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C, + (uint8_t *)&ctrl4_c, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL7_G, + (uint8_t *)&ctrl7_g, 1); + + switch ((ctrl7_g.hp_en_g << 7) + (ctrl7_g.hpm_g << 4) + + (ctrl4_c.lpf1_sel_g << 3) + ctrl6_c.ftype) + { + case LSM6DS3TR_C_HP_16mHz_LP2: + *val = LSM6DS3TR_C_HP_16mHz_LP2; + break; + + case LSM6DS3TR_C_HP_65mHz_LP2: + *val = LSM6DS3TR_C_HP_65mHz_LP2; + break; + + case LSM6DS3TR_C_HP_260mHz_LP2: + *val = LSM6DS3TR_C_HP_260mHz_LP2; + break; + + case LSM6DS3TR_C_HP_1Hz04_LP2: + *val = LSM6DS3TR_C_HP_1Hz04_LP2; + break; + + case LSM6DS3TR_C_HP_DISABLE_LP1_LIGHT: + *val = LSM6DS3TR_C_HP_DISABLE_LP1_LIGHT; + break; + + case LSM6DS3TR_C_HP_DISABLE_LP1_NORMAL: + *val = LSM6DS3TR_C_HP_DISABLE_LP1_NORMAL; + break; + + case LSM6DS3TR_C_HP_DISABLE_LP_STRONG: + *val = LSM6DS3TR_C_HP_DISABLE_LP_STRONG; + break; + + case LSM6DS3TR_C_HP_DISABLE_LP1_AGGRESSIVE: + *val = LSM6DS3TR_C_HP_DISABLE_LP1_AGGRESSIVE; + break; + + case LSM6DS3TR_C_HP_16mHz_LP1_LIGHT: + *val = LSM6DS3TR_C_HP_16mHz_LP1_LIGHT; + break; + + case LSM6DS3TR_C_HP_65mHz_LP1_NORMAL: + *val = LSM6DS3TR_C_HP_65mHz_LP1_NORMAL; + break; + + case LSM6DS3TR_C_HP_260mHz_LP1_STRONG: + *val = LSM6DS3TR_C_HP_260mHz_LP1_STRONG; + break; + + case LSM6DS3TR_C_HP_1Hz04_LP1_AGGRESSIVE: + *val = LSM6DS3TR_C_HP_1Hz04_LP1_AGGRESSIVE; + break; + + default: + *val = LSM6DS3TR_C_HP_GY_BAND_NA; + break; + } + } + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DS3TR_C_serial_interface + * @brief This section groups all the functions concerning serial + * interface management + * @{ + * + */ + +/** + * @brief SPI Serial Interface Mode selection.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of sim in reg CTRL3_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_spi_mode_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_sim_t val) +{ + lsm6ds3tr_c_ctrl3_c_t ctrl3_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, + (uint8_t *)&ctrl3_c, 1); + + if (ret == 0) + { + ctrl3_c.sim = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL3_C, + (uint8_t *)&ctrl3_c, 1); + } + + return ret; +} + +/** + * @brief SPI Serial Interface Mode selection.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of sim in reg CTRL3_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_spi_mode_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_sim_t *val) +{ + lsm6ds3tr_c_ctrl3_c_t ctrl3_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, + (uint8_t *)&ctrl3_c, 1); + + switch (ctrl3_c.sim) + { + case LSM6DS3TR_C_SPI_4_WIRE: + *val = LSM6DS3TR_C_SPI_4_WIRE; + break; + + case LSM6DS3TR_C_SPI_3_WIRE: + *val = LSM6DS3TR_C_SPI_3_WIRE; + break; + + default: + *val = LSM6DS3TR_C_SPI_MODE_ND; + break; + } + + return ret; +} + +/** + * @brief Disable / Enable I2C interface.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of i2c_disable in reg CTRL4_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_i2c_interface_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_i2c_disable_t val) +{ + lsm6ds3tr_c_ctrl4_c_t ctrl4_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C, + (uint8_t *)&ctrl4_c, 1); + + if (ret == 0) + { + ctrl4_c.i2c_disable = (uint8_t)val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL4_C, + (uint8_t *)&ctrl4_c, 1); + } + + return ret; +} + +/** + * @brief Disable / Enable I2C interface.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of i2c_disable in reg CTRL4_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_i2c_interface_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_i2c_disable_t *val) +{ + lsm6ds3tr_c_ctrl4_c_t ctrl4_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C, + (uint8_t *)&ctrl4_c, 1); + + switch (ctrl4_c.i2c_disable) + { + case LSM6DS3TR_C_I2C_ENABLE: + *val = LSM6DS3TR_C_I2C_ENABLE; + break; + + case LSM6DS3TR_C_I2C_DISABLE: + *val = LSM6DS3TR_C_I2C_DISABLE; + break; + + default: + *val = LSM6DS3TR_C_I2C_MODE_ND; + break; + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DS3TR_C_interrupt_pins + * @brief This section groups all the functions that manage + * interrupt pins + * @{ + * + */ + +/** + * @brief Select the signal that need to route on int1 pad[set] + * + * @param ctx Read / write interface definitions + * @param val configure INT1_CTRL, MD1_CFG, CTRL4_C(den_drdy_int1), + * MASTER_CONFIG(drdy_on_int1) + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_pin_int1_route_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_int1_route_t val) +{ + lsm6ds3tr_c_master_config_t master_config; + lsm6ds3tr_c_int1_ctrl_t int1_ctrl; + lsm6ds3tr_c_md1_cfg_t md1_cfg; + lsm6ds3tr_c_md2_cfg_t md2_cfg; + lsm6ds3tr_c_ctrl4_c_t ctrl4_c; + lsm6ds3tr_c_tap_cfg_t tap_cfg; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_INT1_CTRL, + (uint8_t *)&int1_ctrl, 1); + + if (ret == 0) + { + int1_ctrl.int1_drdy_xl = val.int1_drdy_xl; + int1_ctrl.int1_drdy_g = val.int1_drdy_g; + int1_ctrl.int1_boot = val.int1_boot; + int1_ctrl.int1_fth = val.int1_fth; + int1_ctrl.int1_fifo_ovr = val.int1_fifo_ovr; + int1_ctrl.int1_full_flag = val.int1_full_flag; + int1_ctrl.int1_sign_mot = val.int1_sign_mot; + int1_ctrl.int1_step_detector = val.int1_step_detector; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_INT1_CTRL, + (uint8_t *)&int1_ctrl, 1); + } + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MD1_CFG, + (uint8_t *)&md1_cfg, 1); + } + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MD2_CFG, + (uint8_t *)&md2_cfg, 1); + } + + if (ret == 0) + { + md1_cfg.int1_timer = val.int1_timer; + md1_cfg.int1_tilt = val.int1_tilt; + md1_cfg.int1_6d = val.int1_6d; + md1_cfg.int1_double_tap = val.int1_double_tap; + md1_cfg.int1_ff = val.int1_ff; + md1_cfg.int1_wu = val.int1_wu; + md1_cfg.int1_single_tap = val.int1_single_tap; + md1_cfg.int1_inact_state = val.int1_inact_state; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MD1_CFG, + (uint8_t *)&md1_cfg, 1); + } + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C, + (uint8_t *)&ctrl4_c, 1); + } + + if (ret == 0) + { + ctrl4_c.den_drdy_int1 = val.den_drdy_int1; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL4_C, + (uint8_t *)&ctrl4_c, 1); + } + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, + (uint8_t *)&master_config, 1); + } + + if (ret == 0) + { + master_config.drdy_on_int1 = val.den_drdy_int1; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, + (uint8_t *)&master_config, 1); + } + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG, + (uint8_t *)&tap_cfg, 1); + + if ((val.int1_6d != 0x00U) || + (val.int1_ff != 0x00U) || + (val.int1_wu != 0x00U) || + (val.int1_single_tap != 0x00U) || + (val.int1_double_tap != 0x00U) || + (val.int1_inact_state != 0x00U) || + (md2_cfg.int2_6d != 0x00U) || + (md2_cfg.int2_ff != 0x00U) || + (md2_cfg.int2_wu != 0x00U) || + (md2_cfg.int2_single_tap != 0x00U) || + (md2_cfg.int2_double_tap != 0x00U) || + (md2_cfg.int2_inact_state != 0x00U)) + { + tap_cfg.interrupts_enable = PROPERTY_ENABLE; + } + + else + { + tap_cfg.interrupts_enable = PROPERTY_DISABLE; + } + } + + if (ret == 0) + { + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_CFG, + (uint8_t *)&tap_cfg, 1); + } + + return ret; +} + +/** + * @brief Select the signal that need to route on int1 pad[get] + * + * @param ctx Read / write interface definitions + * @param val read INT1_CTRL, MD1_CFG, CTRL4_C(den_drdy_int1), + * MASTER_CONFIG(drdy_on_int1) + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_pin_int1_route_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_int1_route_t *val) +{ + lsm6ds3tr_c_master_config_t master_config; + lsm6ds3tr_c_int1_ctrl_t int1_ctrl; + lsm6ds3tr_c_md1_cfg_t md1_cfg; + lsm6ds3tr_c_ctrl4_c_t ctrl4_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_INT1_CTRL, + (uint8_t *)&int1_ctrl, 1); + + if (ret == 0) + { + val->int1_drdy_xl = int1_ctrl.int1_drdy_xl; + val->int1_drdy_g = int1_ctrl.int1_drdy_g; + val->int1_boot = int1_ctrl.int1_boot; + val->int1_fth = int1_ctrl.int1_fth; + val->int1_fifo_ovr = int1_ctrl.int1_fifo_ovr; + val->int1_full_flag = int1_ctrl.int1_full_flag; + val->int1_sign_mot = int1_ctrl.int1_sign_mot; + val->int1_step_detector = int1_ctrl.int1_step_detector ; + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MD1_CFG, + (uint8_t *)&md1_cfg, 1); + + if (ret == 0) + { + val->int1_timer = md1_cfg.int1_timer; + val->int1_tilt = md1_cfg.int1_tilt; + val->int1_6d = md1_cfg.int1_6d; + val->int1_double_tap = md1_cfg.int1_double_tap; + val->int1_ff = md1_cfg.int1_ff; + val->int1_wu = md1_cfg.int1_wu; + val->int1_single_tap = md1_cfg.int1_single_tap; + val->int1_inact_state = md1_cfg.int1_inact_state; + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C, + (uint8_t *)&ctrl4_c, 1); + + if (ret == 0) + { + val->den_drdy_int1 = ctrl4_c.den_drdy_int1; + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, + (uint8_t *)&master_config, 1); + val->den_drdy_int1 = master_config.drdy_on_int1; + } + } + } + + return ret; +} + +/** + * @brief Select the signal that need to route on int2 pad[set] + * + * @param ctx Read / write interface definitions + * @param val INT2_CTRL, DRDY_PULSE_CFG(int2_wrist_tilt), MD2_CFG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_pin_int2_route_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_int2_route_t val) +{ + lsm6ds3tr_c_int2_ctrl_t int2_ctrl; + lsm6ds3tr_c_md1_cfg_t md1_cfg; + lsm6ds3tr_c_md2_cfg_t md2_cfg; + lsm6ds3tr_c_drdy_pulse_cfg_g_t drdy_pulse_cfg_g; + lsm6ds3tr_c_tap_cfg_t tap_cfg; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_INT2_CTRL, + (uint8_t *)&int2_ctrl, 1); + + if (ret == 0) + { + int2_ctrl.int2_drdy_xl = val.int2_drdy_xl; + int2_ctrl.int2_drdy_g = val.int2_drdy_g; + int2_ctrl.int2_drdy_temp = val.int2_drdy_temp; + int2_ctrl.int2_fth = val.int2_fth; + int2_ctrl.int2_fifo_ovr = val.int2_fifo_ovr; + int2_ctrl.int2_full_flag = val.int2_full_flag; + int2_ctrl.int2_step_count_ov = val.int2_step_count_ov; + int2_ctrl.int2_step_delta = val.int2_step_delta; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_INT2_CTRL, + (uint8_t *)&int2_ctrl, 1); + } + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MD1_CFG, + (uint8_t *)&md1_cfg, 1); + } + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MD2_CFG, + (uint8_t *)&md2_cfg, 1); + } + + if (ret == 0) + { + md2_cfg.int2_iron = val.int2_iron; + md2_cfg.int2_tilt = val.int2_tilt; + md2_cfg.int2_6d = val.int2_6d; + md2_cfg.int2_double_tap = val.int2_double_tap; + md2_cfg.int2_ff = val.int2_ff; + md2_cfg.int2_wu = val.int2_wu; + md2_cfg.int2_single_tap = val.int2_single_tap; + md2_cfg.int2_inact_state = val.int2_inact_state; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MD2_CFG, + (uint8_t *)&md2_cfg, 1); + } + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_DRDY_PULSE_CFG_G, + (uint8_t *)&drdy_pulse_cfg_g, 1); + } + + if (ret == 0) + { + drdy_pulse_cfg_g.int2_wrist_tilt = val.int2_wrist_tilt; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_DRDY_PULSE_CFG_G, + (uint8_t *)&drdy_pulse_cfg_g, 1); + } + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG, + (uint8_t *)&tap_cfg, 1); + + if ((md1_cfg.int1_6d != 0x00U) || + (md1_cfg.int1_ff != 0x00U) || + (md1_cfg.int1_wu != 0x00U) || + (md1_cfg.int1_single_tap != 0x00U) || + (md1_cfg.int1_double_tap != 0x00U) || + (md1_cfg.int1_inact_state != 0x00U) || + (val.int2_6d != 0x00U) || + (val.int2_ff != 0x00U) || + (val.int2_wu != 0x00U) || + (val.int2_single_tap != 0x00U) || + (val.int2_double_tap != 0x00U) || + (val.int2_inact_state != 0x00U)) + { + tap_cfg.interrupts_enable = PROPERTY_ENABLE; + } + + else + { + tap_cfg.interrupts_enable = PROPERTY_DISABLE; + } + } + + if (ret == 0) + { + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_CFG, + (uint8_t *)&tap_cfg, 1); + } + + return ret; +} + +/** + * @brief Select the signal that need to route on int2 pad[get] + * + * @param ctx Read / write interface definitions + * @param val INT2_CTRL, DRDY_PULSE_CFG(int2_wrist_tilt), MD2_CFG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_pin_int2_route_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_int2_route_t *val) +{ + lsm6ds3tr_c_int2_ctrl_t int2_ctrl; + lsm6ds3tr_c_md2_cfg_t md2_cfg; + lsm6ds3tr_c_drdy_pulse_cfg_g_t drdy_pulse_cfg_g; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_INT2_CTRL, + (uint8_t *)&int2_ctrl, 1); + + if (ret == 0) + { + val->int2_drdy_xl = int2_ctrl.int2_drdy_xl; + val->int2_drdy_g = int2_ctrl.int2_drdy_g; + val->int2_drdy_temp = int2_ctrl.int2_drdy_temp; + val->int2_fth = int2_ctrl.int2_fth; + val->int2_fifo_ovr = int2_ctrl.int2_fifo_ovr; + val->int2_full_flag = int2_ctrl.int2_full_flag; + val->int2_step_count_ov = int2_ctrl.int2_step_count_ov; + val->int2_step_delta = int2_ctrl.int2_step_delta; + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MD2_CFG, + (uint8_t *)&md2_cfg, 1); + + if (ret == 0) + { + val->int2_iron = md2_cfg.int2_iron; + val->int2_tilt = md2_cfg.int2_tilt; + val->int2_6d = md2_cfg.int2_6d; + val->int2_double_tap = md2_cfg.int2_double_tap; + val->int2_ff = md2_cfg.int2_ff; + val->int2_wu = md2_cfg.int2_wu; + val->int2_single_tap = md2_cfg.int2_single_tap; + val->int2_inact_state = md2_cfg.int2_inact_state; + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_DRDY_PULSE_CFG_G, + (uint8_t *)&drdy_pulse_cfg_g, 1); + val->int2_wrist_tilt = drdy_pulse_cfg_g.int2_wrist_tilt; + } + } + + return ret; +} + +/** + * @brief Push-pull/open drain selection on interrupt pads.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of pp_od in reg CTRL3_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_pin_mode_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_pp_od_t val) +{ + lsm6ds3tr_c_ctrl3_c_t ctrl3_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, + (uint8_t *)&ctrl3_c, 1); + + if (ret == 0) + { + ctrl3_c.pp_od = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL3_C, + (uint8_t *)&ctrl3_c, 1); + } + + return ret; +} + +/** + * @brief Push-pull/open drain selection on interrupt pads.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of pp_od in reg CTRL3_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_pin_mode_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_pp_od_t *val) +{ + lsm6ds3tr_c_ctrl3_c_t ctrl3_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, + (uint8_t *)&ctrl3_c, 1); + + switch (ctrl3_c.pp_od) + { + case LSM6DS3TR_C_PUSH_PULL: + *val = LSM6DS3TR_C_PUSH_PULL; + break; + + case LSM6DS3TR_C_OPEN_DRAIN: + *val = LSM6DS3TR_C_OPEN_DRAIN; + break; + + default: + *val = LSM6DS3TR_C_PIN_MODE_ND; + break; + } + + return ret; +} + +/** + * @brief Interrupt active-high/low.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of h_lactive in reg CTRL3_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_pin_polarity_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_h_lactive_t val) +{ + lsm6ds3tr_c_ctrl3_c_t ctrl3_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, + (uint8_t *)&ctrl3_c, 1); + + if (ret == 0) + { + ctrl3_c.h_lactive = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL3_C, + (uint8_t *)&ctrl3_c, 1); + } + + return ret; +} + +/** + * @brief Interrupt active-high/low.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of h_lactive in reg CTRL3_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_pin_polarity_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_h_lactive_t *val) +{ + lsm6ds3tr_c_ctrl3_c_t ctrl3_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, + (uint8_t *)&ctrl3_c, 1); + + switch (ctrl3_c.h_lactive) + { + case LSM6DS3TR_C_ACTIVE_HIGH: + *val = LSM6DS3TR_C_ACTIVE_HIGH; + break; + + case LSM6DS3TR_C_ACTIVE_LOW: + *val = LSM6DS3TR_C_ACTIVE_LOW; + break; + + default: + *val = LSM6DS3TR_C_POLARITY_ND; + break; + } + + return ret; +} + +/** + * @brief All interrupt signals become available on INT1 pin.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of int2_on_int1 in reg CTRL4_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_all_on_int1_set(const stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6ds3tr_c_ctrl4_c_t ctrl4_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C, + (uint8_t *)&ctrl4_c, 1); + + if (ret == 0) + { + ctrl4_c.int2_on_int1 = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL4_C, + (uint8_t *)&ctrl4_c, 1); + } + + return ret; +} + +/** + * @brief All interrupt signals become available on INT1 pin.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of int2_on_int1 in reg CTRL4_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_all_on_int1_get(const stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6ds3tr_c_ctrl4_c_t ctrl4_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C, + (uint8_t *)&ctrl4_c, 1); + *val = ctrl4_c.int2_on_int1; + + return ret; +} + +/** + * @brief Latched/pulsed interrupt.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of lir in reg TAP_CFG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_int_notification_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_lir_t val) +{ + lsm6ds3tr_c_tap_cfg_t tap_cfg; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG, + (uint8_t *)&tap_cfg, 1); + + if (ret == 0) + { + tap_cfg.lir = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_CFG, + (uint8_t *)&tap_cfg, 1); + } + + return ret; +} + +/** + * @brief Latched/pulsed interrupt.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of lir in reg TAP_CFG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_int_notification_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_lir_t *val) +{ + lsm6ds3tr_c_tap_cfg_t tap_cfg; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG, + (uint8_t *)&tap_cfg, 1); + + switch (tap_cfg.lir) + { + case LSM6DS3TR_C_INT_PULSED: + *val = LSM6DS3TR_C_INT_PULSED; + break; + + case LSM6DS3TR_C_INT_LATCHED: + *val = LSM6DS3TR_C_INT_LATCHED; + break; + + default: + *val = LSM6DS3TR_C_INT_MODE; + break; + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DS3TR_C_Wake_Up_event + * @brief This section groups all the functions that manage the + * Wake Up event generation. + * @{ + * + */ + +/** + * @brief Threshold for wakeup.1 LSB = FS_XL / 64.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of wk_ths in reg WAKE_UP_THS + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_wkup_threshold_set(const stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6ds3tr_c_wake_up_ths_t wake_up_ths; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_THS, + (uint8_t *)&wake_up_ths, 1); + + if (ret == 0) + { + wake_up_ths.wk_ths = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_WAKE_UP_THS, + (uint8_t *)&wake_up_ths, 1); + } + + return ret; +} + +/** + * @brief Threshold for wakeup.1 LSB = FS_XL / 64.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of wk_ths in reg WAKE_UP_THS + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_wkup_threshold_get(const stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6ds3tr_c_wake_up_ths_t wake_up_ths; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_THS, + (uint8_t *)&wake_up_ths, 1); + *val = wake_up_ths.wk_ths; + + return ret; +} + +/** + * @brief Wake up duration event.1LSb = 1 / ODR[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of wake_dur in reg WAKE_UP_DUR + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_wkup_dur_set(const stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6ds3tr_c_wake_up_dur_t wake_up_dur; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR, + (uint8_t *)&wake_up_dur, 1); + + if (ret == 0) + { + wake_up_dur.wake_dur = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR, + (uint8_t *)&wake_up_dur, 1); + } + + return ret; +} + +/** + * @brief Wake up duration event.1LSb = 1 / ODR[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of wake_dur in reg WAKE_UP_DUR + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_wkup_dur_get(const stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6ds3tr_c_wake_up_dur_t wake_up_dur; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR, + (uint8_t *)&wake_up_dur, 1); + *val = wake_up_dur.wake_dur; + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DS3TR_C_Activity/Inactivity_detection + * @brief This section groups all the functions concerning + * activity/inactivity detection. + * @{ + * + */ + +/** + * @brief Enables gyroscope Sleep mode.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of sleep in reg CTRL4_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_gy_sleep_mode_set(const stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6ds3tr_c_ctrl4_c_t ctrl4_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C, + (uint8_t *)&ctrl4_c, 1); + + if (ret == 0) + { + ctrl4_c.sleep = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL4_C, + (uint8_t *)&ctrl4_c, 1); + } + + return ret; +} + +/** + * @brief Enables gyroscope Sleep mode.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of sleep in reg CTRL4_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_gy_sleep_mode_get(const stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6ds3tr_c_ctrl4_c_t ctrl4_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C, + (uint8_t *)&ctrl4_c, 1); + *val = ctrl4_c.sleep; + + return ret; +} + +/** + * @brief Enable inactivity function.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of inact_en in reg TAP_CFG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_act_mode_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_inact_en_t val) +{ + lsm6ds3tr_c_tap_cfg_t tap_cfg; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG, + (uint8_t *)&tap_cfg, 1); + + if (ret == 0) + { + tap_cfg.inact_en = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_CFG, + (uint8_t *)&tap_cfg, 1); + } + + return ret; +} + +/** + * @brief Enable inactivity function.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of inact_en in reg TAP_CFG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_act_mode_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_inact_en_t *val) +{ + lsm6ds3tr_c_tap_cfg_t tap_cfg; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG, + (uint8_t *)&tap_cfg, 1); + + switch (tap_cfg.inact_en) + { + case LSM6DS3TR_C_PROPERTY_DISABLE: + *val = LSM6DS3TR_C_PROPERTY_DISABLE; + break; + + case LSM6DS3TR_C_XL_12Hz5_GY_NOT_AFFECTED: + *val = LSM6DS3TR_C_XL_12Hz5_GY_NOT_AFFECTED; + break; + + case LSM6DS3TR_C_XL_12Hz5_GY_SLEEP: + *val = LSM6DS3TR_C_XL_12Hz5_GY_SLEEP; + break; + + case LSM6DS3TR_C_XL_12Hz5_GY_PD: + *val = LSM6DS3TR_C_XL_12Hz5_GY_PD; + break; + + default: + *val = LSM6DS3TR_C_ACT_MODE_ND; + break; + } + + return ret; +} + +/** + * @brief Duration to go in sleep mode.1 LSb = 512 / ODR[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of sleep_dur in reg WAKE_UP_DUR + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_act_sleep_dur_set(const stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6ds3tr_c_wake_up_dur_t wake_up_dur; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR, + (uint8_t *)&wake_up_dur, 1); + + if (ret == 0) + { + wake_up_dur.sleep_dur = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR, + (uint8_t *)&wake_up_dur, 1); + } + + return ret; +} + +/** + * @brief Duration to go in sleep mode. 1 LSb = 512 / ODR[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of sleep_dur in reg WAKE_UP_DUR + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_act_sleep_dur_get(const stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6ds3tr_c_wake_up_dur_t wake_up_dur; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR, + (uint8_t *)&wake_up_dur, 1); + *val = wake_up_dur.sleep_dur; + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DS3TR_C_tap_generator + * @brief This section groups all the functions that manage the + * tap and double tap event generation. + * @{ + * + */ + +/** + * @brief Read the tap / double tap source register.[get] + * + * @param ctx Read / write interface definitions + * @param val Structure of registers from TAP_SRC + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_tap_src_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_tap_src_t *val) +{ + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_SRC, (uint8_t *) val, 1); + + return ret; +} + +/** + * @brief Enable Z direction in tap recognition.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of tap_z_en in reg TAP_CFG + * + */ +int32_t lsm6ds3tr_c_tap_detection_on_z_set(const stmdev_ctx_t *ctx, + uint8_t val) +{ + lsm6ds3tr_c_tap_cfg_t tap_cfg; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG, + (uint8_t *)&tap_cfg, 1); + + if (ret == 0) + { + tap_cfg.tap_z_en = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_CFG, + (uint8_t *)&tap_cfg, 1); + } + + return ret; +} + +/** + * @brief Enable Z direction in tap recognition.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of tap_z_en in reg TAP_CFG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_tap_detection_on_z_get(const stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6ds3tr_c_tap_cfg_t tap_cfg; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG, + (uint8_t *)&tap_cfg, 1); + *val = tap_cfg.tap_z_en; + + return ret; +} + +/** + * @brief Enable Y direction in tap recognition.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of tap_y_en in reg TAP_CFG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_tap_detection_on_y_set(const stmdev_ctx_t *ctx, + uint8_t val) +{ + lsm6ds3tr_c_tap_cfg_t tap_cfg; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG, + (uint8_t *)&tap_cfg, 1); + + if (ret == 0) + { + tap_cfg.tap_y_en = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_CFG, + (uint8_t *)&tap_cfg, 1); + } + + return ret; +} + +/** + * @brief Enable Y direction in tap recognition.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of tap_y_en in reg TAP_CFG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_tap_detection_on_y_get(const stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6ds3tr_c_tap_cfg_t tap_cfg; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG, + (uint8_t *)&tap_cfg, 1); + *val = tap_cfg.tap_y_en; + + return ret; +} + +/** + * @brief Enable X direction in tap recognition.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of tap_x_en in reg TAP_CFG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_tap_detection_on_x_set(const stmdev_ctx_t *ctx, + uint8_t val) +{ + lsm6ds3tr_c_tap_cfg_t tap_cfg; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG, + (uint8_t *)&tap_cfg, 1); + + if (ret == 0) + { + tap_cfg.tap_x_en = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_CFG, + (uint8_t *)&tap_cfg, 1); + } + + return ret; +} + +/** + * @brief Enable X direction in tap recognition.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of tap_x_en in reg TAP_CFG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_tap_detection_on_x_get(const stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6ds3tr_c_tap_cfg_t tap_cfg; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG, + (uint8_t *)&tap_cfg, 1); + *val = tap_cfg.tap_x_en; + + return ret; +} + +/** + * @brief Threshold for tap recognition.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of tap_ths in reg TAP_THS_6D + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_tap_threshold_x_set(const stmdev_ctx_t *ctx, + uint8_t val) +{ + lsm6ds3tr_c_tap_ths_6d_t tap_ths_6d; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_THS_6D, + (uint8_t *)&tap_ths_6d, 1); + + if (ret == 0) + { + tap_ths_6d.tap_ths = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_THS_6D, + (uint8_t *)&tap_ths_6d, 1); + } + + return ret; +} + +/** + * @brief Threshold for tap recognition.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of tap_ths in reg TAP_THS_6D + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_tap_threshold_x_get(const stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6ds3tr_c_tap_ths_6d_t tap_ths_6d; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_THS_6D, + (uint8_t *)&tap_ths_6d, 1); + *val = tap_ths_6d.tap_ths; + + return ret; +} + +/** + * @brief Maximum duration is the maximum time of an overthreshold signal + * detection to be recognized as a tap event. + * The default value of these bits is 00b which corresponds to + * 4*ODR_XL time. + * If the SHOCK[1:0] bits are set to a different + * value, 1LSB corresponds to 8*ODR_XL time.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of shock in reg INT_DUR2 + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_tap_shock_set(const stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6ds3tr_c_int_dur2_t int_dur2; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_INT_DUR2, + (uint8_t *)&int_dur2, 1); + + if (ret == 0) + { + int_dur2.shock = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_INT_DUR2, + (uint8_t *)&int_dur2, 1); + } + + return ret; +} + +/** + * @brief Maximum duration is the maximum time of an overthreshold signal + * detection to be recognized as a tap event. + * The default value of these bits is 00b which corresponds to + * 4*ODR_XL time. + * If the SHOCK[1:0] bits are set to a different value, 1LSB + * corresponds to 8*ODR_XL time.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of shock in reg INT_DUR2 + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_tap_shock_get(const stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6ds3tr_c_int_dur2_t int_dur2; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_INT_DUR2, + (uint8_t *)&int_dur2, 1); + *val = int_dur2.shock; + + return ret; +} + +/** + * @brief Quiet time is the time after the first detected tap in which there + * must not be any overthreshold event. + * The default value of these bits is 00b which corresponds to + * 2*ODR_XL time. + * If the QUIET[1:0] bits are set to a different value, 1LSB + * corresponds to 4*ODR_XL time.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of quiet in reg INT_DUR2 + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_tap_quiet_set(const stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6ds3tr_c_int_dur2_t int_dur2; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_INT_DUR2, + (uint8_t *)&int_dur2, 1); + + if (ret == 0) + { + int_dur2.quiet = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_INT_DUR2, + (uint8_t *)&int_dur2, 1); + } + + return ret; +} + +/** + * @brief Quiet time is the time after the first detected tap in which there + * must not be any overthreshold event. + * The default value of these bits is 00b which corresponds to + * 2*ODR_XL time. + * If the QUIET[1:0] bits are set to a different value, 1LSB + * corresponds to 4*ODR_XL time.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of quiet in reg INT_DUR2 + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_tap_quiet_get(const stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6ds3tr_c_int_dur2_t int_dur2; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_INT_DUR2, + (uint8_t *)&int_dur2, 1); + *val = int_dur2.quiet; + + return ret; +} + +/** + * @brief When double tap recognition is enabled, this register expresses the + * maximum time between two consecutive detected taps to determine a + * double tap event. + * The default value of these bits is 0000b which corresponds to + * 16*ODR_XL time. + * If the DUR[3:0] bits are set to a different value,1LSB corresponds + * to 32*ODR_XL time.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of dur in reg INT_DUR2 + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_tap_dur_set(const stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6ds3tr_c_int_dur2_t int_dur2; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_INT_DUR2, + (uint8_t *)&int_dur2, 1); + + if (ret == 0) + { + int_dur2.dur = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_INT_DUR2, + (uint8_t *)&int_dur2, 1); + } + + return ret; +} + +/** + * @brief When double tap recognition is enabled, this register expresses the + * maximum time between two consecutive detected taps to determine a + * double tap event. + * The default value of these bits is 0000b which corresponds to + * 16*ODR_XL time. + * If the DUR[3:0] bits are set to a different value,1LSB corresponds + * to 32*ODR_XL time.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of dur in reg INT_DUR2 + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_tap_dur_get(const stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6ds3tr_c_int_dur2_t int_dur2; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_INT_DUR2, + (uint8_t *)&int_dur2, 1); + *val = int_dur2.dur; + + return ret; +} + +/** + * @brief Single/double-tap event enable/disable.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of + * single_double_tap in reg WAKE_UP_THS + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_tap_mode_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_single_double_tap_t val) +{ + lsm6ds3tr_c_wake_up_ths_t wake_up_ths; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_THS, + (uint8_t *)&wake_up_ths, 1); + + if (ret == 0) + { + wake_up_ths.single_double_tap = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_WAKE_UP_THS, + (uint8_t *)&wake_up_ths, 1); + } + + return ret; +} + +/** + * @brief Single/double-tap event enable/disable.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of single_double_tap + * in reg WAKE_UP_THS + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_tap_mode_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_single_double_tap_t *val) +{ + lsm6ds3tr_c_wake_up_ths_t wake_up_ths; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_THS, + (uint8_t *)&wake_up_ths, 1); + + switch (wake_up_ths.single_double_tap) + { + case LSM6DS3TR_C_ONLY_SINGLE: + *val = LSM6DS3TR_C_ONLY_SINGLE; + break; + + case LSM6DS3TR_C_BOTH_SINGLE_DOUBLE: + *val = LSM6DS3TR_C_BOTH_SINGLE_DOUBLE; + break; + + default: + *val = LSM6DS3TR_C_TAP_MODE_ND; + break; + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DS3TR_C_ Six_position_detection(6D/4D) + * @brief This section groups all the functions concerning six + * position detection (6D). + * @{ + * + */ + +/** + * @brief LPF2 feed 6D function selection.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of low_pass_on_6d in + * reg CTRL8_XL + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_6d_feed_data_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_low_pass_on_6d_t val) +{ + lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL8_XL, + (uint8_t *)&ctrl8_xl, 1); + + if (ret == 0) + { + ctrl8_xl.low_pass_on_6d = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL8_XL, + (uint8_t *)&ctrl8_xl, 1); + } + + return ret; +} + +/** + * @brief LPF2 feed 6D function selection.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of low_pass_on_6d in reg CTRL8_XL + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_6d_feed_data_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_low_pass_on_6d_t *val) +{ + lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL8_XL, + (uint8_t *)&ctrl8_xl, 1); + + switch (ctrl8_xl.low_pass_on_6d) + { + case LSM6DS3TR_C_ODR_DIV_2_FEED: + *val = LSM6DS3TR_C_ODR_DIV_2_FEED; + break; + + case LSM6DS3TR_C_LPF2_FEED: + *val = LSM6DS3TR_C_LPF2_FEED; + break; + + default: + *val = LSM6DS3TR_C_6D_FEED_ND; + break; + } + + return ret; +} + +/** + * @brief Threshold for 4D/6D function.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of sixd_ths in reg TAP_THS_6D + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_6d_threshold_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_sixd_ths_t val) +{ + lsm6ds3tr_c_tap_ths_6d_t tap_ths_6d; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_THS_6D, + (uint8_t *)&tap_ths_6d, 1); + + if (ret == 0) + { + tap_ths_6d.sixd_ths = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_THS_6D, + (uint8_t *)&tap_ths_6d, 1); + } + + return ret; +} + +/** + * @brief Threshold for 4D/6D function.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of sixd_ths in reg TAP_THS_6D + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_6d_threshold_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_sixd_ths_t *val) +{ + lsm6ds3tr_c_tap_ths_6d_t tap_ths_6d; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_THS_6D, + (uint8_t *)&tap_ths_6d, 1); + + switch (tap_ths_6d.sixd_ths) + { + case LSM6DS3TR_C_DEG_80: + *val = LSM6DS3TR_C_DEG_80; + break; + + case LSM6DS3TR_C_DEG_70: + *val = LSM6DS3TR_C_DEG_70; + break; + + case LSM6DS3TR_C_DEG_60: + *val = LSM6DS3TR_C_DEG_60; + break; + + case LSM6DS3TR_C_DEG_50: + *val = LSM6DS3TR_C_DEG_50; + break; + + default: + *val = LSM6DS3TR_C_6D_TH_ND; + break; + } + + return ret; +} + +/** + * @brief 4D orientation detection enable.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of d4d_en in reg TAP_THS_6D + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_4d_mode_set(const stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6ds3tr_c_tap_ths_6d_t tap_ths_6d; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_THS_6D, + (uint8_t *)&tap_ths_6d, 1); + + if (ret == 0) + { + tap_ths_6d.d4d_en = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_THS_6D, + (uint8_t *)&tap_ths_6d, 1); + } + + return ret; +} + +/** + * @brief 4D orientation detection enable.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of d4d_en in reg TAP_THS_6D + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_4d_mode_get(const stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6ds3tr_c_tap_ths_6d_t tap_ths_6d; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_THS_6D, + (uint8_t *)&tap_ths_6d, 1); + *val = tap_ths_6d.d4d_en; + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DS3TR_C_free_fall + * @brief This section group all the functions concerning the free + * fall detection. + * @{ + * + */ + +/** + * @brief Free-fall duration event. 1LSb = 1 / ODR[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of ff_dur in reg WAKE_UP_DUR + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_ff_dur_set(const stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6ds3tr_c_wake_up_dur_t wake_up_dur; + lsm6ds3tr_c_free_fall_t free_fall; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FREE_FALL, + (uint8_t *)&free_fall, 1); + + if (ret == 0) + { + free_fall.ff_dur = (val & 0x1FU); + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FREE_FALL, + (uint8_t *)&free_fall, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR, + (uint8_t *)&wake_up_dur, 1); + + if (ret == 0) + { + wake_up_dur.ff_dur = (val & 0x20U) >> 5; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR, + (uint8_t *)&wake_up_dur, 1); + } + } + } + + return ret; +} + +/** + * @brief Free-fall duration event. 1LSb = 1 / ODR[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of ff_dur in reg WAKE_UP_DUR + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_ff_dur_get(const stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6ds3tr_c_wake_up_dur_t wake_up_dur; + lsm6ds3tr_c_free_fall_t free_fall; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR, + (uint8_t *)&wake_up_dur, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FREE_FALL, + (uint8_t *)&free_fall, 1); + } + + *val = (wake_up_dur.ff_dur << 5) + free_fall.ff_dur; + + return ret; +} + +/** + * @brief Free fall threshold setting.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of ff_ths in reg FREE_FALL + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_ff_threshold_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_ff_ths_t val) +{ + lsm6ds3tr_c_free_fall_t free_fall; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FREE_FALL, + (uint8_t *)&free_fall, 1); + + if (ret == 0) + { + free_fall.ff_ths = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FREE_FALL, + (uint8_t *)&free_fall, 1); + } + + return ret; +} + +/** + * @brief Free fall threshold setting.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of ff_ths in reg FREE_FALL + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_ff_threshold_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_ff_ths_t *val) +{ + lsm6ds3tr_c_free_fall_t free_fall; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FREE_FALL, + (uint8_t *)&free_fall, 1); + + switch (free_fall.ff_ths) + { + case LSM6DS3TR_C_FF_TSH_156mg: + *val = LSM6DS3TR_C_FF_TSH_156mg; + break; + + case LSM6DS3TR_C_FF_TSH_219mg: + *val = LSM6DS3TR_C_FF_TSH_219mg; + break; + + case LSM6DS3TR_C_FF_TSH_250mg: + *val = LSM6DS3TR_C_FF_TSH_250mg; + break; + + case LSM6DS3TR_C_FF_TSH_312mg: + *val = LSM6DS3TR_C_FF_TSH_312mg; + break; + + case LSM6DS3TR_C_FF_TSH_344mg: + *val = LSM6DS3TR_C_FF_TSH_344mg; + break; + + case LSM6DS3TR_C_FF_TSH_406mg: + *val = LSM6DS3TR_C_FF_TSH_406mg; + break; + + case LSM6DS3TR_C_FF_TSH_469mg: + *val = LSM6DS3TR_C_FF_TSH_469mg; + break; + + case LSM6DS3TR_C_FF_TSH_500mg: + *val = LSM6DS3TR_C_FF_TSH_500mg; + break; + + default: + *val = LSM6DS3TR_C_FF_TSH_ND; + break; + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DS3TR_C_fifo + * @brief This section group all the functions concerning the + * fifo usage + * @{ + * + */ + +/** + * @brief FIFO watermark level selection.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of fth in reg FIFO_CTRL1 + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_fifo_watermark_set(const stmdev_ctx_t *ctx, + uint16_t val) +{ + lsm6ds3tr_c_fifo_ctrl1_t fifo_ctrl1; + lsm6ds3tr_c_fifo_ctrl2_t fifo_ctrl2; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2, + (uint8_t *)&fifo_ctrl2, 1); + + if (ret == 0) + { + fifo_ctrl1.fth = (uint8_t)(0x00FFU & val); + fifo_ctrl2.fth = (uint8_t)((0x0700U & val) >> 8); + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL1, + (uint8_t *)&fifo_ctrl1, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2, + (uint8_t *)&fifo_ctrl2, 1); + } + } + + return ret; +} + +/** + * @brief FIFO watermark level selection.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of fth in reg FIFO_CTRL1 + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_fifo_watermark_get(const stmdev_ctx_t *ctx, + uint16_t *val) +{ + lsm6ds3tr_c_fifo_ctrl1_t fifo_ctrl1; + lsm6ds3tr_c_fifo_ctrl2_t fifo_ctrl2; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL1, + (uint8_t *)&fifo_ctrl1, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2, + (uint8_t *)&fifo_ctrl2, 1); + } + + *val = ((uint16_t)fifo_ctrl2.fth << 8) + (uint16_t)fifo_ctrl1.fth; + + return ret; +} + +/** + * @brief FIFO data level.[get] + * + * @param ctx Read / write interface definitions + * @param val get the values of diff_fifo in reg FIFO_STATUS1 and + * FIFO_STATUS2(diff_fifo), it is recommended to set the + * BDU bit. + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_fifo_data_level_get(const stmdev_ctx_t *ctx, + uint16_t *val) +{ + lsm6ds3tr_c_fifo_status1_t fifo_status1; + lsm6ds3tr_c_fifo_status2_t fifo_status2; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_STATUS1, + (uint8_t *)&fifo_status1, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_STATUS2, + (uint8_t *)&fifo_status2, 1); + *val = ((uint16_t) fifo_status2.diff_fifo << 8) + + (uint16_t) fifo_status1.diff_fifo; + } + + return ret; +} + +/** + * @brief FIFO watermark.[get] + * + * @param ctx Read / write interface definitions + * @param val get the values of watermark in reg FIFO_STATUS2 and + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_fifo_wtm_flag_get(const stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6ds3tr_c_fifo_status2_t fifo_status2; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_STATUS2, + (uint8_t *)&fifo_status2, 1); + *val = fifo_status2.waterm; + + return ret; +} + +/** + * @brief FIFO pattern.[get] + * + * @param ctx Read / write interface definitions + * @param val get the values of fifo_pattern in reg FIFO_STATUS3 and + * FIFO_STATUS4, it is recommended to set the BDU bit + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_fifo_pattern_get(const stmdev_ctx_t *ctx, uint16_t *val) +{ + lsm6ds3tr_c_fifo_status3_t fifo_status3; + lsm6ds3tr_c_fifo_status4_t fifo_status4; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_STATUS3, + (uint8_t *)&fifo_status3, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_STATUS4, + (uint8_t *)&fifo_status4, 1); + *val = ((uint16_t)fifo_status4.fifo_pattern << 8) + + fifo_status3.fifo_pattern; + } + + return ret; +} + +/** + * @brief Batching of temperature data[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of fifo_temp_en in reg FIFO_CTRL2 + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_fifo_temp_batch_set(const stmdev_ctx_t *ctx, + uint8_t val) +{ + lsm6ds3tr_c_fifo_ctrl2_t fifo_ctrl2; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2, + (uint8_t *)&fifo_ctrl2, 1); + + if (ret == 0) + { + fifo_ctrl2.fifo_temp_en = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2, + (uint8_t *)&fifo_ctrl2, 1); + } + + return ret; +} + +/** + * @brief Batching of temperature data[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of fifo_temp_en in reg FIFO_CTRL2 + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_fifo_temp_batch_get(const stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6ds3tr_c_fifo_ctrl2_t fifo_ctrl2; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2, + (uint8_t *)&fifo_ctrl2, 1); + *val = fifo_ctrl2.fifo_temp_en; + + return ret; +} + +/** + * @brief Trigger signal for FIFO write operation.[set] + * + * @param ctx Read / write interface definitions + * @param val act on FIFO_CTRL2(timer_pedo_fifo_drdy) + * and MASTER_CONFIG(data_valid_sel_fifo) + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_fifo_write_trigger_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_trigger_fifo_t val) +{ + lsm6ds3tr_c_fifo_ctrl2_t fifo_ctrl2; + lsm6ds3tr_c_master_config_t master_config; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2, + (uint8_t *)&fifo_ctrl2, 1); + + if (ret == 0) + { + fifo_ctrl2.timer_pedo_fifo_drdy = (uint8_t)val & 0x01U; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2, + (uint8_t *)&fifo_ctrl2, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, + (uint8_t *)&master_config, 1); + + if (ret == 0) + { + master_config.data_valid_sel_fifo = (((uint8_t)val & 0x02U) >> 1); + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, + (uint8_t *)&master_config, 1); + } + } + } + + return ret; +} + +/** + * @brief Trigger signal for FIFO write operation.[get] + * + * @param ctx Read / write interface definitions + * @param val act on FIFO_CTRL2(timer_pedo_fifo_drdy) + * and MASTER_CONFIG(data_valid_sel_fifo) + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_fifo_write_trigger_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_trigger_fifo_t *val) +{ + lsm6ds3tr_c_fifo_ctrl2_t fifo_ctrl2; + lsm6ds3tr_c_master_config_t master_config; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2, + (uint8_t *)&fifo_ctrl2, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, + (uint8_t *)&master_config, 1); + + switch ((fifo_ctrl2.timer_pedo_fifo_drdy << 1) + + fifo_ctrl2. timer_pedo_fifo_drdy) + { + case LSM6DS3TR_C_TRG_XL_GY_DRDY: + *val = LSM6DS3TR_C_TRG_XL_GY_DRDY; + break; + + case LSM6DS3TR_C_TRG_STEP_DETECT: + *val = LSM6DS3TR_C_TRG_STEP_DETECT; + break; + + case LSM6DS3TR_C_TRG_SH_DRDY: + *val = LSM6DS3TR_C_TRG_SH_DRDY; + break; + + default: + *val = LSM6DS3TR_C_TRG_SH_ND; + break; + } + } + + return ret; +} + +/** + * @brief Enable pedometer step counter and timestamp as 4th + * FIFO data set.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of timer_pedo_fifo_en in reg FIFO_CTRL2 + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_fifo_pedo_and_timestamp_batch_set( + stmdev_ctx_t *ctx, + uint8_t val) +{ + lsm6ds3tr_c_fifo_ctrl2_t fifo_ctrl2; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2, + (uint8_t *)&fifo_ctrl2, 1); + + if (ret == 0) + { + fifo_ctrl2.timer_pedo_fifo_en = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2, + (uint8_t *)&fifo_ctrl2, 1); + } + + return ret; +} + +/** + * @brief Enable pedometer step counter and timestamp as 4th + * FIFO data set.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of timer_pedo_fifo_en in reg FIFO_CTRL2 + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_fifo_pedo_and_timestamp_batch_get( + stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6ds3tr_c_fifo_ctrl2_t fifo_ctrl2; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2, + (uint8_t *)&fifo_ctrl2, 1); + *val = fifo_ctrl2.timer_pedo_fifo_en; + + return ret; +} + +/** + * @brief Selects Batching Data Rate (writing frequency in FIFO) for + * accelerometer data.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of dec_fifo_xl in reg FIFO_CTRL3 + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_fifo_xl_batch_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_dec_fifo_xl_t val) +{ + lsm6ds3tr_c_fifo_ctrl3_t fifo_ctrl3; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL3, + (uint8_t *)&fifo_ctrl3, 1); + + if (ret == 0) + { + fifo_ctrl3.dec_fifo_xl = (uint8_t)val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL3, + (uint8_t *)&fifo_ctrl3, 1); + } + + return ret; +} + +/** + * @brief Selects Batching Data Rate (writing frequency in FIFO) for + * accelerometer data.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of dec_fifo_xl in reg FIFO_CTRL3 + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_fifo_xl_batch_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_dec_fifo_xl_t *val) +{ + lsm6ds3tr_c_fifo_ctrl3_t fifo_ctrl3; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL3, + (uint8_t *)&fifo_ctrl3, 1); + + switch (fifo_ctrl3.dec_fifo_xl) + { + case LSM6DS3TR_C_FIFO_XL_DISABLE: + *val = LSM6DS3TR_C_FIFO_XL_DISABLE; + break; + + case LSM6DS3TR_C_FIFO_XL_NO_DEC: + *val = LSM6DS3TR_C_FIFO_XL_NO_DEC; + break; + + case LSM6DS3TR_C_FIFO_XL_DEC_2: + *val = LSM6DS3TR_C_FIFO_XL_DEC_2; + break; + + case LSM6DS3TR_C_FIFO_XL_DEC_3: + *val = LSM6DS3TR_C_FIFO_XL_DEC_3; + break; + + case LSM6DS3TR_C_FIFO_XL_DEC_4: + *val = LSM6DS3TR_C_FIFO_XL_DEC_4; + break; + + case LSM6DS3TR_C_FIFO_XL_DEC_8: + *val = LSM6DS3TR_C_FIFO_XL_DEC_8; + break; + + case LSM6DS3TR_C_FIFO_XL_DEC_16: + *val = LSM6DS3TR_C_FIFO_XL_DEC_16; + break; + + case LSM6DS3TR_C_FIFO_XL_DEC_32: + *val = LSM6DS3TR_C_FIFO_XL_DEC_32; + break; + + default: + *val = LSM6DS3TR_C_FIFO_XL_DEC_ND; + break; + } + + return ret; +} + +/** + * @brief Selects Batching Data Rate (writing frequency in FIFO) + * for gyroscope data.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of dec_fifo_gyro in reg FIFO_CTRL3 + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_fifo_gy_batch_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_dec_fifo_gyro_t val) +{ + lsm6ds3tr_c_fifo_ctrl3_t fifo_ctrl3; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL3, + (uint8_t *)&fifo_ctrl3, 1); + + if (ret == 0) + { + fifo_ctrl3.dec_fifo_gyro = (uint8_t)val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL3, + (uint8_t *)&fifo_ctrl3, 1); + } + + return ret; +} + +/** + * @brief Selects Batching Data Rate (writing frequency in FIFO) + * for gyroscope data.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of dec_fifo_gyro in reg FIFO_CTRL3 + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_fifo_gy_batch_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_dec_fifo_gyro_t *val) +{ + lsm6ds3tr_c_fifo_ctrl3_t fifo_ctrl3; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL3, + (uint8_t *)&fifo_ctrl3, 1); + + switch (fifo_ctrl3.dec_fifo_gyro) + { + case LSM6DS3TR_C_FIFO_GY_DISABLE: + *val = LSM6DS3TR_C_FIFO_GY_DISABLE; + break; + + case LSM6DS3TR_C_FIFO_GY_NO_DEC: + *val = LSM6DS3TR_C_FIFO_GY_NO_DEC; + break; + + case LSM6DS3TR_C_FIFO_GY_DEC_2: + *val = LSM6DS3TR_C_FIFO_GY_DEC_2; + break; + + case LSM6DS3TR_C_FIFO_GY_DEC_3: + *val = LSM6DS3TR_C_FIFO_GY_DEC_3; + break; + + case LSM6DS3TR_C_FIFO_GY_DEC_4: + *val = LSM6DS3TR_C_FIFO_GY_DEC_4; + break; + + case LSM6DS3TR_C_FIFO_GY_DEC_8: + *val = LSM6DS3TR_C_FIFO_GY_DEC_8; + break; + + case LSM6DS3TR_C_FIFO_GY_DEC_16: + *val = LSM6DS3TR_C_FIFO_GY_DEC_16; + break; + + case LSM6DS3TR_C_FIFO_GY_DEC_32: + *val = LSM6DS3TR_C_FIFO_GY_DEC_32; + break; + + default: + *val = LSM6DS3TR_C_FIFO_GY_DEC_ND; + break; + } + + return ret; +} + +/** + * @brief Selects Batching Data Rate (writing frequency in FIFO) + * for third data set.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of dec_ds3_fifo in reg FIFO_CTRL4 + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_fifo_dataset_3_batch_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_dec_ds3_fifo_t val) +{ + lsm6ds3tr_c_fifo_ctrl4_t fifo_ctrl4; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4, + (uint8_t *)&fifo_ctrl4, 1); + + if (ret == 0) + { + fifo_ctrl4.dec_ds3_fifo = (uint8_t)val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4, + (uint8_t *)&fifo_ctrl4, 1); + } + + return ret; +} + +/** + * @brief Selects Batching Data Rate (writing frequency in FIFO) + * for third data set.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of dec_ds3_fifo in reg FIFO_CTRL4 + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_fifo_dataset_3_batch_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_dec_ds3_fifo_t *val) +{ + lsm6ds3tr_c_fifo_ctrl4_t fifo_ctrl4; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4, + (uint8_t *)&fifo_ctrl4, 1); + + switch (fifo_ctrl4.dec_ds3_fifo) + { + case LSM6DS3TR_C_FIFO_DS3_DISABLE: + *val = LSM6DS3TR_C_FIFO_DS3_DISABLE; + break; + + case LSM6DS3TR_C_FIFO_DS3_NO_DEC: + *val = LSM6DS3TR_C_FIFO_DS3_NO_DEC; + break; + + case LSM6DS3TR_C_FIFO_DS3_DEC_2: + *val = LSM6DS3TR_C_FIFO_DS3_DEC_2; + break; + + case LSM6DS3TR_C_FIFO_DS3_DEC_3: + *val = LSM6DS3TR_C_FIFO_DS3_DEC_3; + break; + + case LSM6DS3TR_C_FIFO_DS3_DEC_4: + *val = LSM6DS3TR_C_FIFO_DS3_DEC_4; + break; + + case LSM6DS3TR_C_FIFO_DS3_DEC_8: + *val = LSM6DS3TR_C_FIFO_DS3_DEC_8; + break; + + case LSM6DS3TR_C_FIFO_DS3_DEC_16: + *val = LSM6DS3TR_C_FIFO_DS3_DEC_16; + break; + + case LSM6DS3TR_C_FIFO_DS3_DEC_32: + *val = LSM6DS3TR_C_FIFO_DS3_DEC_32; + break; + + default: + *val = LSM6DS3TR_C_FIFO_DS3_DEC_ND; + break; + } + + return ret; +} + +/** + * @brief Selects Batching Data Rate (writing frequency in FIFO) + * for fourth data set.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of dec_ds4_fifo in reg FIFO_CTRL4 + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_fifo_dataset_4_batch_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_dec_ds4_fifo_t val) +{ + lsm6ds3tr_c_fifo_ctrl4_t fifo_ctrl4; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4, + (uint8_t *)&fifo_ctrl4, 1); + + if (ret == 0) + { + fifo_ctrl4.dec_ds4_fifo = (uint8_t)val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4, + (uint8_t *)&fifo_ctrl4, 1); + } + + return ret; +} + +/** + * @brief Selects Batching Data Rate (writing frequency in FIFO) for + * fourth data set.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of dec_ds4_fifo in reg FIFO_CTRL4 + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_fifo_dataset_4_batch_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_dec_ds4_fifo_t *val) +{ + lsm6ds3tr_c_fifo_ctrl4_t fifo_ctrl4; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4, + (uint8_t *)&fifo_ctrl4, 1); + + switch (fifo_ctrl4.dec_ds4_fifo) + { + case LSM6DS3TR_C_FIFO_DS4_DISABLE: + *val = LSM6DS3TR_C_FIFO_DS4_DISABLE; + break; + + case LSM6DS3TR_C_FIFO_DS4_NO_DEC: + *val = LSM6DS3TR_C_FIFO_DS4_NO_DEC; + break; + + case LSM6DS3TR_C_FIFO_DS4_DEC_2: + *val = LSM6DS3TR_C_FIFO_DS4_DEC_2; + break; + + case LSM6DS3TR_C_FIFO_DS4_DEC_3: + *val = LSM6DS3TR_C_FIFO_DS4_DEC_3; + break; + + case LSM6DS3TR_C_FIFO_DS4_DEC_4: + *val = LSM6DS3TR_C_FIFO_DS4_DEC_4; + break; + + case LSM6DS3TR_C_FIFO_DS4_DEC_8: + *val = LSM6DS3TR_C_FIFO_DS4_DEC_8; + break; + + case LSM6DS3TR_C_FIFO_DS4_DEC_16: + *val = LSM6DS3TR_C_FIFO_DS4_DEC_16; + break; + + case LSM6DS3TR_C_FIFO_DS4_DEC_32: + *val = LSM6DS3TR_C_FIFO_DS4_DEC_32; + break; + + default: + *val = LSM6DS3TR_C_FIFO_DS4_DEC_ND; + break; + } + + return ret; +} + +/** + * @brief 8-bit data storage in FIFO.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of only_high_data in reg FIFO_CTRL4 + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_fifo_xl_gy_8bit_format_set(const stmdev_ctx_t *ctx, + uint8_t val) +{ + lsm6ds3tr_c_fifo_ctrl4_t fifo_ctrl4; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4, + (uint8_t *)&fifo_ctrl4, 1); + + if (ret == 0) + { + fifo_ctrl4.only_high_data = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4, + (uint8_t *)&fifo_ctrl4, 1); + } + + return ret; +} + +/** + * @brief 8-bit data storage in FIFO.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of only_high_data in reg FIFO_CTRL4 + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_fifo_xl_gy_8bit_format_get(const stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6ds3tr_c_fifo_ctrl4_t fifo_ctrl4; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4, + (uint8_t *)&fifo_ctrl4, 1); + *val = fifo_ctrl4.only_high_data; + + return ret; +} + +/** + * @brief Sensing chain FIFO stop values memorization at threshold + * level.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of stop_on_fth in reg FIFO_CTRL4 + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_fifo_stop_on_wtm_set(const stmdev_ctx_t *ctx, + uint8_t val) +{ + lsm6ds3tr_c_fifo_ctrl4_t fifo_ctrl4; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4, + (uint8_t *)&fifo_ctrl4, 1); + + if (ret == 0) + { + fifo_ctrl4.stop_on_fth = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4, + (uint8_t *)&fifo_ctrl4, 1); + } + + return ret; +} + +/** + * @brief Sensing chain FIFO stop values memorization at threshold + * level.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of stop_on_fth in reg FIFO_CTRL4 + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_fifo_stop_on_wtm_get(const stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6ds3tr_c_fifo_ctrl4_t fifo_ctrl4; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4, + (uint8_t *)&fifo_ctrl4, 1); + *val = fifo_ctrl4.stop_on_fth; + + return ret; +} + +/** + * @brief FIFO mode selection.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of fifo_mode in reg FIFO_CTRL5 + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_fifo_mode_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_fifo_mode_t val) +{ + lsm6ds3tr_c_fifo_ctrl5_t fifo_ctrl5; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL5, + (uint8_t *)&fifo_ctrl5, 1); + + if (ret == 0) + { + fifo_ctrl5.fifo_mode = (uint8_t)val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL5, + (uint8_t *)&fifo_ctrl5, 1); + } + + return ret; +} + +/** + * @brief FIFO mode selection.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of fifo_mode in reg FIFO_CTRL5 + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_fifo_mode_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_fifo_mode_t *val) +{ + lsm6ds3tr_c_fifo_ctrl5_t fifo_ctrl5; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL5, + (uint8_t *)&fifo_ctrl5, 1); + + switch (fifo_ctrl5.fifo_mode) + { + case LSM6DS3TR_C_BYPASS_MODE: + *val = LSM6DS3TR_C_BYPASS_MODE; + break; + + case LSM6DS3TR_C_FIFO_MODE: + *val = LSM6DS3TR_C_FIFO_MODE; + break; + + case LSM6DS3TR_C_STREAM_TO_FIFO_MODE: + *val = LSM6DS3TR_C_STREAM_TO_FIFO_MODE; + break; + + case LSM6DS3TR_C_BYPASS_TO_STREAM_MODE: + *val = LSM6DS3TR_C_BYPASS_TO_STREAM_MODE; + break; + + case LSM6DS3TR_C_STREAM_MODE: + *val = LSM6DS3TR_C_STREAM_MODE; + break; + + default: + *val = LSM6DS3TR_C_FIFO_MODE_ND; + break; + } + + return ret; +} + +/** + * @brief FIFO ODR selection, setting FIFO_MODE also.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of odr_fifo in reg FIFO_CTRL5 + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_fifo_data_rate_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_odr_fifo_t val) +{ + lsm6ds3tr_c_fifo_ctrl5_t fifo_ctrl5; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL5, + (uint8_t *)&fifo_ctrl5, 1); + + if (ret == 0) + { + fifo_ctrl5.odr_fifo = (uint8_t)val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL5, + (uint8_t *)&fifo_ctrl5, 1); + } + + return ret; +} + +/** + * @brief FIFO ODR selection, setting FIFO_MODE also.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of odr_fifo in reg FIFO_CTRL5 + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_fifo_data_rate_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_odr_fifo_t *val) +{ + lsm6ds3tr_c_fifo_ctrl5_t fifo_ctrl5; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL5, + (uint8_t *)&fifo_ctrl5, 1); + + switch (fifo_ctrl5.odr_fifo) + { + case LSM6DS3TR_C_FIFO_DISABLE: + *val = LSM6DS3TR_C_FIFO_DISABLE; + break; + + case LSM6DS3TR_C_FIFO_12Hz5: + *val = LSM6DS3TR_C_FIFO_12Hz5; + break; + + case LSM6DS3TR_C_FIFO_26Hz: + *val = LSM6DS3TR_C_FIFO_26Hz; + break; + + case LSM6DS3TR_C_FIFO_52Hz: + *val = LSM6DS3TR_C_FIFO_52Hz; + break; + + case LSM6DS3TR_C_FIFO_104Hz: + *val = LSM6DS3TR_C_FIFO_104Hz; + break; + + case LSM6DS3TR_C_FIFO_208Hz: + *val = LSM6DS3TR_C_FIFO_208Hz; + break; + + case LSM6DS3TR_C_FIFO_416Hz: + *val = LSM6DS3TR_C_FIFO_416Hz; + break; + + case LSM6DS3TR_C_FIFO_833Hz: + *val = LSM6DS3TR_C_FIFO_833Hz; + break; + + case LSM6DS3TR_C_FIFO_1k66Hz: + *val = LSM6DS3TR_C_FIFO_1k66Hz; + break; + + case LSM6DS3TR_C_FIFO_3k33Hz: + *val = LSM6DS3TR_C_FIFO_3k33Hz; + break; + + case LSM6DS3TR_C_FIFO_6k66Hz: + *val = LSM6DS3TR_C_FIFO_6k66Hz; + break; + + default: + *val = LSM6DS3TR_C_FIFO_RATE_ND; + break; + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DS3TR_C_DEN_functionality + * @brief This section groups all the functions concerning DEN + * functionality. + * @{ + * + */ + +/** + * @brief DEN active level configuration.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of den_lh in reg CTRL5_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_den_polarity_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_den_lh_t val) +{ + lsm6ds3tr_c_ctrl5_c_t ctrl5_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL5_C, + (uint8_t *)&ctrl5_c, 1); + + if (ret == 0) + { + ctrl5_c.den_lh = (uint8_t)val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL5_C, + (uint8_t *)&ctrl5_c, 1); + } + + return ret; +} + +/** + * @brief DEN active level configuration.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of den_lh in reg CTRL5_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_den_polarity_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_den_lh_t *val) +{ + lsm6ds3tr_c_ctrl5_c_t ctrl5_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL5_C, + (uint8_t *)&ctrl5_c, 1); + + switch (ctrl5_c.den_lh) + { + case LSM6DS3TR_C_DEN_ACT_LOW: + *val = LSM6DS3TR_C_DEN_ACT_LOW; + break; + + case LSM6DS3TR_C_DEN_ACT_HIGH: + *val = LSM6DS3TR_C_DEN_ACT_HIGH; + break; + + default: + *val = LSM6DS3TR_C_DEN_POL_ND; + break; + } + + return ret; +} + +/** + * @brief DEN functionality marking mode[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of den_mode in reg CTRL6_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_den_mode_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_den_mode_t val) +{ + lsm6ds3tr_c_ctrl6_c_t ctrl6_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL6_C, + (uint8_t *)&ctrl6_c, 1); + + if (ret == 0) + { + ctrl6_c.den_mode = (uint8_t)val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL6_C, + (uint8_t *)&ctrl6_c, 1); + } + + return ret; +} + +/** + * @brief DEN functionality marking mode[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of den_mode in reg CTRL6_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_den_mode_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_den_mode_t *val) +{ + lsm6ds3tr_c_ctrl6_c_t ctrl6_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL6_C, + (uint8_t *)&ctrl6_c, 1); + + switch (ctrl6_c.den_mode) + { + case LSM6DS3TR_C_DEN_DISABLE: + *val = LSM6DS3TR_C_DEN_DISABLE; + break; + + case LSM6DS3TR_C_LEVEL_LETCHED: + *val = LSM6DS3TR_C_LEVEL_LETCHED; + break; + + case LSM6DS3TR_C_LEVEL_TRIGGER: + *val = LSM6DS3TR_C_LEVEL_TRIGGER; + break; + + case LSM6DS3TR_C_EDGE_TRIGGER: + *val = LSM6DS3TR_C_EDGE_TRIGGER; + break; + + default: + *val = LSM6DS3TR_C_DEN_MODE_ND; + break; + } + + return ret; +} + +/** + * @brief Extend DEN functionality to accelerometer sensor.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of den_xl_g in reg CTRL9_XL + * and den_xl_en in CTRL4_C. + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_den_enable_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_den_xl_en_t val) +{ + lsm6ds3tr_c_ctrl4_c_t ctrl4_c; + lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL9_XL, + (uint8_t *)&ctrl9_xl, 1); + + if (ret == 0) + { + ctrl9_xl.den_xl_g = (uint8_t)val & 0x01U; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL9_XL, + (uint8_t *)&ctrl9_xl, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C, + (uint8_t *)&ctrl4_c, 1); + + if (ret == 0) + { + ctrl4_c.den_xl_en = (uint8_t)val & 0x02U; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL4_C, + (uint8_t *)&ctrl4_c, 1); + } + } + } + + return ret; +} + +/** + * @brief Extend DEN functionality to accelerometer sensor. [get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of den_xl_g in reg CTRL9_XL + * and den_xl_en in CTRL4_C. + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_den_enable_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_den_xl_en_t *val) +{ + lsm6ds3tr_c_ctrl4_c_t ctrl4_c; + lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C, + (uint8_t *)&ctrl4_c, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL9_XL, + (uint8_t *)&ctrl9_xl, 1); + + switch ((ctrl4_c.den_xl_en << 1) + ctrl9_xl.den_xl_g) + { + case LSM6DS3TR_C_STAMP_IN_GY_DATA: + *val = LSM6DS3TR_C_STAMP_IN_GY_DATA; + break; + + case LSM6DS3TR_C_STAMP_IN_XL_DATA: + *val = LSM6DS3TR_C_STAMP_IN_XL_DATA; + break; + + case LSM6DS3TR_C_STAMP_IN_GY_XL_DATA: + *val = LSM6DS3TR_C_STAMP_IN_GY_XL_DATA; + break; + + default: + *val = LSM6DS3TR_C_DEN_STAMP_ND; + break; + } + } + + return ret; +} + +/** + * @brief DEN value stored in LSB of Z-axis.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of den_z in reg CTRL9_XL + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_den_mark_axis_z_set(const stmdev_ctx_t *ctx, + uint8_t val) +{ + lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL9_XL, + (uint8_t *)&ctrl9_xl, 1); + + if (ret == 0) + { + ctrl9_xl.den_z = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL9_XL, + (uint8_t *)&ctrl9_xl, 1); + } + + return ret; +} + +/** + * @brief DEN value stored in LSB of Z-axis.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of den_z in reg CTRL9_XL + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_den_mark_axis_z_get(const stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL9_XL, + (uint8_t *)&ctrl9_xl, 1); + *val = ctrl9_xl.den_z; + + return ret; +} + +/** + * @brief DEN value stored in LSB of Y-axis.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of den_y in reg CTRL9_XL + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_den_mark_axis_y_set(const stmdev_ctx_t *ctx, + uint8_t val) +{ + lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL9_XL, + (uint8_t *)&ctrl9_xl, 1); + + if (ret == 0) + { + ctrl9_xl.den_y = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL9_XL, + (uint8_t *)&ctrl9_xl, 1); + } + + return ret; +} + +/** + * @brief DEN value stored in LSB of Y-axis.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of den_y in reg CTRL9_XL + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_den_mark_axis_y_get(const stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL9_XL, + (uint8_t *)&ctrl9_xl, 1); + *val = ctrl9_xl.den_y; + + return ret; +} + +/** + * @brief DEN value stored in LSB of X-axis.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of den_x in reg CTRL9_XL + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_den_mark_axis_x_set(const stmdev_ctx_t *ctx, + uint8_t val) +{ + lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL9_XL, + (uint8_t *)&ctrl9_xl, 1); + + if (ret == 0) + { + ctrl9_xl.den_x = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL9_XL, + (uint8_t *)&ctrl9_xl, 1); + } + + return ret; +} + +/** + * @brief DEN value stored in LSB of X-axis.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of den_x in reg CTRL9_XL + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_den_mark_axis_x_get(const stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL9_XL, + (uint8_t *)&ctrl9_xl, 1); + *val = ctrl9_xl.den_x; + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DS3TR_C_Pedometer + * @brief This section groups all the functions that manage pedometer. + * @{ + * + */ + +/** + * @brief Reset pedometer step counter.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of pedo_rst_step in reg CTRL10_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_pedo_step_reset_set(const stmdev_ctx_t *ctx, + uint8_t val) +{ + lsm6ds3tr_c_ctrl10_c_t ctrl10_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C, + (uint8_t *)&ctrl10_c, 1); + + if (ret == 0) + { + ctrl10_c.pedo_rst_step = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL10_C, + (uint8_t *)&ctrl10_c, 1); + } + + return ret; +} + +/** + * @brief Reset pedometer step counter.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of pedo_rst_step in reg CTRL10_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_pedo_step_reset_get(const stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6ds3tr_c_ctrl10_c_t ctrl10_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C, + (uint8_t *)&ctrl10_c, 1); + *val = ctrl10_c.pedo_rst_step; + + return ret; +} + +/** + * @brief Enable pedometer algorithm.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of pedo_en in reg CTRL10_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_pedo_sens_set(const stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6ds3tr_c_ctrl10_c_t ctrl10_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C, + (uint8_t *)&ctrl10_c, 1); + + if (ret == 0) + { + ctrl10_c.pedo_en = val; + + if (val != 0x00U) + { + ctrl10_c.func_en = val; + } + + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL10_C, + (uint8_t *)&ctrl10_c, 1); + } + + return ret; +} + +/** + * @brief pedo_sens: Enable pedometer algorithm.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of pedo_en in reg CTRL10_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_pedo_sens_get(const stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6ds3tr_c_ctrl10_c_t ctrl10_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C, + (uint8_t *)&ctrl10_c, 1); + *val = ctrl10_c.pedo_en; + + return ret; +} + +/** + * @brief Minimum threshold to detect a peak. Default is 10h.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of ths_min in reg + * CONFIG_PEDO_THS_MIN + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_pedo_threshold_set(const stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6ds3tr_c_config_pedo_ths_min_t config_pedo_ths_min; + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CONFIG_PEDO_THS_MIN, + (uint8_t *)&config_pedo_ths_min, 1); + + if (ret == 0) + { + config_pedo_ths_min.ths_min = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CONFIG_PEDO_THS_MIN, + (uint8_t *)&config_pedo_ths_min, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + } + + return ret; +} + +/** + * @brief Minimum threshold to detect a peak. Default is 10h.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of ths_min in reg CONFIG_PEDO_THS_MIN + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_pedo_threshold_get(const stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6ds3tr_c_config_pedo_ths_min_t config_pedo_ths_min; + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CONFIG_PEDO_THS_MIN, + (uint8_t *)&config_pedo_ths_min, 1); + + if (ret == 0) + { + *val = config_pedo_ths_min.ths_min; + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + + return ret; +} + +/** + * @brief pedo_full_scale: Pedometer data range.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of pedo_fs in + * reg CONFIG_PEDO_THS_MIN + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_pedo_full_scale_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_pedo_fs_t val) +{ + lsm6ds3tr_c_config_pedo_ths_min_t config_pedo_ths_min; + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CONFIG_PEDO_THS_MIN, + (uint8_t *)&config_pedo_ths_min, 1); + + if (ret == 0) + { + config_pedo_ths_min.pedo_fs = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CONFIG_PEDO_THS_MIN, + (uint8_t *)&config_pedo_ths_min, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + } + + return ret; +} + +/** + * @brief Pedometer data range.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of pedo_fs in + * reg CONFIG_PEDO_THS_MIN + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_pedo_full_scale_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_pedo_fs_t *val) +{ + lsm6ds3tr_c_config_pedo_ths_min_t config_pedo_ths_min; + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CONFIG_PEDO_THS_MIN, + (uint8_t *)&config_pedo_ths_min, 1); + + if (ret == 0) + { + switch (config_pedo_ths_min.pedo_fs) + { + case LSM6DS3TR_C_PEDO_AT_2g: + *val = LSM6DS3TR_C_PEDO_AT_2g; + break; + + case LSM6DS3TR_C_PEDO_AT_4g: + *val = LSM6DS3TR_C_PEDO_AT_4g; + break; + + default: + *val = LSM6DS3TR_C_PEDO_FS_ND; + break; + } + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + + return ret; +} + +/** + * @brief Pedometer debounce configuration register (r/w).[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of deb_step in reg PEDO_DEB_REG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_pedo_debounce_steps_set(const stmdev_ctx_t *ctx, + uint8_t val) +{ + lsm6ds3tr_c_pedo_deb_reg_t pedo_deb_reg; + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_PEDO_DEB_REG, + (uint8_t *)&pedo_deb_reg, 1); + + if (ret == 0) + { + pedo_deb_reg.deb_step = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_PEDO_DEB_REG, + (uint8_t *)&pedo_deb_reg, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + } + + return ret; +} + +/** + * @brief Pedometer debounce configuration register (r/w).[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of deb_step in reg PEDO_DEB_REG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_pedo_debounce_steps_get(const stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6ds3tr_c_pedo_deb_reg_t pedo_deb_reg; + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_PEDO_DEB_REG, + (uint8_t *)&pedo_deb_reg, 1); + + if (ret == 0) + { + *val = pedo_deb_reg.deb_step; + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + + return ret; +} + +/** + * @brief Debounce time. If the time between two consecutive steps is + * greater than DEB_TIME*80ms, the debouncer is reactivated. + * Default value: 01101[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of deb_time in reg PEDO_DEB_REG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_pedo_timeout_set(const stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6ds3tr_c_pedo_deb_reg_t pedo_deb_reg; + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_PEDO_DEB_REG, + (uint8_t *)&pedo_deb_reg, 1); + + if (ret == 0) + { + pedo_deb_reg.deb_time = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_PEDO_DEB_REG, + (uint8_t *)&pedo_deb_reg, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + } + + return ret; +} + +/** + * @brief Debounce time. If the time between two consecutive steps is + * greater than DEB_TIME*80ms, the debouncer is reactivated. + * Default value: 01101[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of deb_time in reg PEDO_DEB_REG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_pedo_timeout_get(const stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6ds3tr_c_pedo_deb_reg_t pedo_deb_reg; + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_PEDO_DEB_REG, + (uint8_t *)&pedo_deb_reg, 1); + + if (ret == 0) + { + *val = pedo_deb_reg.deb_time; + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + + return ret; +} + +/** + * @brief Time period register for step detection on delta time (r/w).[set] + * + * @param ctx Read / write interface definitions + * @param buff Buffer that contains data to write + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_pedo_steps_period_set(const stmdev_ctx_t *ctx, + uint8_t *buff) +{ + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_STEP_COUNT_DELTA, buff, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + + return ret; +} + +/** + * @brief Time period register for step detection on delta time (r/w).[get] + * + * @param ctx Read / write interface definitions + * @param buff Buffer that stores data read + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_pedo_steps_period_get(const stmdev_ctx_t *ctx, + uint8_t *buff) +{ + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_STEP_COUNT_DELTA, buff, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DS3TR_C_significant_motion + * @brief This section groups all the functions that manage the + * significant motion detection. + * @{ + * + */ + +/** + * @brief Enable significant motion detection function.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of sign_motion_en in reg CTRL10_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_motion_sens_set(const stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6ds3tr_c_ctrl10_c_t ctrl10_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C, + (uint8_t *)&ctrl10_c, 1); + + if (ret == 0) + { + ctrl10_c.sign_motion_en = val; + + if (val != 0x00U) + { + ctrl10_c.func_en = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL10_C, + (uint8_t *)&ctrl10_c, 1); + } + } + + return ret; +} + +/** + * @brief Enable significant motion detection function.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of sign_motion_en in reg CTRL10_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_motion_sens_get(const stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6ds3tr_c_ctrl10_c_t ctrl10_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C, + (uint8_t *)&ctrl10_c, 1); + *val = ctrl10_c.sign_motion_en; + + return ret; +} + +/** + * @brief Significant motion threshold.[set] + * + * @param ctx Read / write interface definitions + * @param buff Buffer that store significant motion threshold. + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_motion_threshold_set(const stmdev_ctx_t *ctx, + uint8_t *buff) +{ + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SM_THS, buff, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + + return ret; +} + +/** + * @brief Significant motion threshold.[get] + * + * @param ctx Read / write interface definitions + * @param buff Buffer that store significant motion threshold. + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_motion_threshold_get(const stmdev_ctx_t *ctx, + uint8_t *buff) +{ + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SM_THS, buff, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DS3TR_C_tilt_detection + * @brief This section groups all the functions that manage the tilt + * event detection. + * @{ + * + */ + +/** + * @brief Enable tilt calculation.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of tilt_en in reg CTRL10_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_tilt_sens_set(const stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6ds3tr_c_ctrl10_c_t ctrl10_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C, + (uint8_t *)&ctrl10_c, 1); + + if (ret == 0) + { + ctrl10_c.tilt_en = val; + + if (val != 0x00U) + { + ctrl10_c.func_en = val; + } + + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL10_C, + (uint8_t *)&ctrl10_c, 1); + } + + return ret; +} + +/** + * @brief Enable tilt calculation.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of tilt_en in reg CTRL10_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_tilt_sens_get(const stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6ds3tr_c_ctrl10_c_t ctrl10_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C, + (uint8_t *)&ctrl10_c, 1); + *val = ctrl10_c.tilt_en; + + return ret; +} + +/** + * @brief Enable tilt calculation.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of tilt_en in reg CTRL10_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_wrist_tilt_sens_set(const stmdev_ctx_t *ctx, + uint8_t val) +{ + lsm6ds3tr_c_ctrl10_c_t ctrl10_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C, + (uint8_t *)&ctrl10_c, 1); + + if (ret == 0) + { + ctrl10_c.wrist_tilt_en = val; + + if (val != 0x00U) + { + ctrl10_c.func_en = val; + } + + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL10_C, + (uint8_t *)&ctrl10_c, 1); + } + + return ret; +} + +/** + * @brief Enable tilt calculation.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of tilt_en in reg CTRL10_C + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_wrist_tilt_sens_get(const stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6ds3tr_c_ctrl10_c_t ctrl10_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C, + (uint8_t *)&ctrl10_c, 1); + *val = ctrl10_c.wrist_tilt_en; + + return ret; +} + +/** + * @brief Absolute Wrist Tilt latency register (r/w). + * Absolute wrist tilt latency parameters. + * 1 LSB = 40 ms. Default value: 0Fh (600 ms).[set] + * + * @param ctx Read / write interface definitions + * @param buff Buffer that contains data to write + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_tilt_latency_set(const stmdev_ctx_t *ctx, uint8_t *buff) +{ + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_B); + + if (ret == 0) + { + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_A_WRIST_TILT_LAT, buff, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + + return ret; +} + +/** + * @brief Absolute Wrist Tilt latency register (r/w). + * Absolute wrist tilt latency parameters. + * 1 LSB = 40 ms. Default value: 0Fh (600 ms).[get] + * + * @param ctx Read / write interface definitions + * @param buff Buffer that stores data read + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_tilt_latency_get(const stmdev_ctx_t *ctx, uint8_t *buff) +{ + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_B); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_A_WRIST_TILT_LAT, buff, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + + return ret; +} + +/** + * @brief Absolute Wrist Tilt threshold register(r/w). + * Absolute wrist tilt threshold parameters. + * 1 LSB = 15.625 mg.Default value: 20h (500 mg).[set] + * + * @param ctx Read / write interface definitions + * @param buff Buffer that contains data to write + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_tilt_threshold_set(const stmdev_ctx_t *ctx, + uint8_t *buff) +{ + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_B); + + if (ret == 0) + { + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_A_WRIST_TILT_THS, buff, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + + return ret; +} + +/** + * @brief Absolute Wrist Tilt threshold register(r/w). + * Absolute wrist tilt threshold parameters. + * 1 LSB = 15.625 mg.Default value: 20h (500 mg).[get] + * + * @param ctx Read / write interface definitions + * @param buff Buffer that stores data read + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_tilt_threshold_get(const stmdev_ctx_t *ctx, + uint8_t *buff) +{ + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_B); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_A_WRIST_TILT_THS, buff, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + + return ret; +} + +/** + * @brief Absolute Wrist Tilt mask register (r/w).[set] + * + * @param ctx Read / write interface definitions + * @param val Registers A_WRIST_TILT_MASK + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_tilt_src_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_a_wrist_tilt_mask_t *val) +{ + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_B); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_A_WRIST_TILT_MASK, + (uint8_t *) val, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + + return ret; +} + +/** + * @brief Absolute Wrist Tilt mask register (r/w).[get] + * + * @param ctx Read / write interface definitions + * @param val Registers A_WRIST_TILT_MASK + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_tilt_src_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_a_wrist_tilt_mask_t *val) +{ + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_B); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_A_WRIST_TILT_MASK, + (uint8_t *) val, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DS3TR_C_ magnetometer_sensor + * @brief This section groups all the functions that manage additional + * magnetometer sensor. + * @{ + * + */ + +/** + * @brief Enable soft-iron correction algorithm for magnetometer.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of soft_en in reg CTRL9_XL + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_mag_soft_iron_set(const stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL9_XL, + (uint8_t *)&ctrl9_xl, 1); + + if (ret == 0) + { + ctrl9_xl.soft_en = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL9_XL, + (uint8_t *)&ctrl9_xl, 1); + } + + return ret; +} + +/** + * @brief Enable soft-iron correction algorithm for magnetometer.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of soft_en in reg CTRL9_XL + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_mag_soft_iron_get(const stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL9_XL, + (uint8_t *)&ctrl9_xl, 1); + *val = ctrl9_xl.soft_en; + + return ret; +} + +/** + * @brief Enable hard-iron correction algorithm for magnetometer.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of iron_en in reg MASTER_CONFIG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_mag_hard_iron_set(const stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6ds3tr_c_master_config_t master_config; + lsm6ds3tr_c_ctrl10_c_t ctrl10_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, + (uint8_t *)&master_config, 1); + + if (ret == 0) + { + master_config.iron_en = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, + (uint8_t *)&master_config, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C, + (uint8_t *)&ctrl10_c, 1); + + if (ret == 0) + { + if (val != 0x00U) + { + ctrl10_c.func_en = val; + } + + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL10_C, + (uint8_t *)&ctrl10_c, 1); + } + } + } + + return ret; +} + +/** + * @brief Enable hard-iron correction algorithm for magnetometer.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of iron_en in reg MASTER_CONFIG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_mag_hard_iron_get(const stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6ds3tr_c_master_config_t master_config; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, + (uint8_t *)&master_config, 1); + *val = master_config.iron_en; + + return ret; +} + +/** + * @brief Soft iron 3x3 matrix. Value are expressed in sign-module format. + * (Es. SVVVVVVVb where S is the sign 0/+1/- and V is the value).[set] + * + * @param ctx Read / write interface definitions + * @param buff Buffer that contains data to write + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_mag_soft_iron_mat_set(const stmdev_ctx_t *ctx, + uint8_t *buff) +{ + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MAG_SI_XX, buff, 9); + + if (ret == 0) + { + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + + return ret; +} + +/** + * @brief Soft iron 3x3 matrix. Value are expressed in sign-module format. + * (Es. SVVVVVVVb where S is the sign 0/+1/- and V is the value).[get] + * + * @param ctx Read / write interface definitions + * @param buff Buffer that stores data read + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_mag_soft_iron_mat_get(const stmdev_ctx_t *ctx, + uint8_t *buff) +{ + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MAG_SI_XX, buff, 9); + + if (ret == 0) + { + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + + return ret; +} + +/** + * @brief Offset for hard-iron compensation register (r/w). The value is + * expressed as a 16-bit word in two’s complement.[set] + * + * @param ctx Read / write interface definitions + * @param buff Buffer that contains data to write + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_mag_offset_set(const stmdev_ctx_t *ctx, int16_t *val) +{ + uint8_t buff[6]; + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + buff[1] = (uint8_t)((uint16_t)val[0] / 256U); + buff[0] = (uint8_t)((uint16_t)val[0] - (buff[1] * 256U)); + buff[3] = (uint8_t)((uint16_t)val[1] / 256U); + buff[2] = (uint8_t)((uint16_t)val[1] - (buff[3] * 256U)); + buff[5] = (uint8_t)((uint16_t)val[2] / 256U); + buff[4] = (uint8_t)((uint16_t)val[2] - (buff[5] * 256U)); + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MAG_OFFX_L, buff, 6); + + if (ret == 0) + { + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + + return ret; +} + +/** + * @brief Offset for hard-iron compensation register(r/w). + * The value is expressed as a 16-bit word in two’s complement.[get] + * + * @param ctx Read / write interface definitions + * @param buff Buffer that stores data read + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_mag_offset_get(const stmdev_ctx_t *ctx, int16_t *val) +{ + uint8_t buff[6]; + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MAG_OFFX_L, buff, 6); + + if (ret == 0) + { + val[0] = (int16_t)buff[1]; + val[0] = (val[0] * 256) + (int16_t)buff[0]; + val[1] = (int16_t)buff[3]; + val[1] = (val[1] * 256) + (int16_t)buff[2]; + val[2] = (int16_t)buff[5]; + val[2] = (val[2] * 256) + (int16_t)buff[4]; + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DS3TR_C_Sensor_hub + * @brief This section groups all the functions that manage the sensor + * hub functionality. + * @{ + * + */ + +/** + * @brief Enable function.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values func_en + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_func_en_set(const stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6ds3tr_c_ctrl10_c_t ctrl10_c; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C, + (uint8_t *)&ctrl10_c, 1); + + if (ret == 0) + { + ctrl10_c.func_en = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL10_C, + (uint8_t *)&ctrl10_c, 1); + } + + return ret; +} + +/** + * @brief Sensor synchronization time frame with the step of 500 ms and + * full range of 5s. Unsigned 8-bit.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of tph in reg SENSOR_SYNC_TIME_FRAME + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_sync_sens_frame_set(const stmdev_ctx_t *ctx, + uint8_t val) +{ + lsm6ds3tr_c_sensor_sync_time_frame_t sensor_sync_time_frame; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SENSOR_SYNC_TIME_FRAME, + (uint8_t *)&sensor_sync_time_frame, 1); + + if (ret == 0) + { + sensor_sync_time_frame.tph = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SENSOR_SYNC_TIME_FRAME, + (uint8_t *)&sensor_sync_time_frame, 1); + } + + return ret; +} + +/** + * @brief Sensor synchronization time frame with the step of 500 ms and + * full range of 5s. Unsigned 8-bit.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of tph in reg SENSOR_SYNC_TIME_FRAME + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_sync_sens_frame_get(const stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6ds3tr_c_sensor_sync_time_frame_t sensor_sync_time_frame; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SENSOR_SYNC_TIME_FRAME, + (uint8_t *)&sensor_sync_time_frame, 1); + *val = sensor_sync_time_frame.tph; + + return ret; +} + +/** + * @brief Resolution ratio of error code for sensor synchronization.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of rr in reg SENSOR_SYNC_RES_RATIO + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_sync_sens_ratio_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_rr_t val) +{ + lsm6ds3tr_c_sensor_sync_res_ratio_t sensor_sync_res_ratio; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SENSOR_SYNC_RES_RATIO, + (uint8_t *)&sensor_sync_res_ratio, 1); + + if (ret == 0) + { + sensor_sync_res_ratio.rr = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SENSOR_SYNC_RES_RATIO, + (uint8_t *)&sensor_sync_res_ratio, 1); + } + + return ret; +} + +/** + * @brief Resolution ratio of error code for sensor synchronization.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of rr in reg SENSOR_SYNC_RES_RATIO + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_sync_sens_ratio_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_rr_t *val) +{ + lsm6ds3tr_c_sensor_sync_res_ratio_t sensor_sync_res_ratio; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SENSOR_SYNC_RES_RATIO, + (uint8_t *)&sensor_sync_res_ratio, 1); + + switch (sensor_sync_res_ratio.rr) + { + case LSM6DS3TR_C_RES_RATIO_2_11: + *val = LSM6DS3TR_C_RES_RATIO_2_11; + break; + + case LSM6DS3TR_C_RES_RATIO_2_12: + *val = LSM6DS3TR_C_RES_RATIO_2_12; + break; + + case LSM6DS3TR_C_RES_RATIO_2_13: + *val = LSM6DS3TR_C_RES_RATIO_2_13; + break; + + case LSM6DS3TR_C_RES_RATIO_2_14: + *val = LSM6DS3TR_C_RES_RATIO_2_14; + break; + + default: + *val = LSM6DS3TR_C_RES_RATIO_ND; + break; + } + + return ret; +} + +/** + * @brief Sensor hub I2C master enable.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of master_on in reg MASTER_CONFIG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_master_set(const stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6ds3tr_c_master_config_t master_config; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, + (uint8_t *)&master_config, 1); + + if (ret == 0) + { + master_config.master_on = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, + (uint8_t *)&master_config, 1); + } + + return ret; +} + +/** + * @brief Sensor hub I2C master enable.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of master_on in reg MASTER_CONFIG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_master_get(const stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6ds3tr_c_master_config_t master_config; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, + (uint8_t *)&master_config, 1); + *val = master_config.master_on; + + return ret; +} + +/** + * @brief I2C interface pass-through.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of pass_through_mode in reg MASTER_CONFIG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_pass_through_set(const stmdev_ctx_t *ctx, + uint8_t val) +{ + lsm6ds3tr_c_master_config_t master_config; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, + (uint8_t *)&master_config, 1); + + if (ret == 0) + { + master_config.pass_through_mode = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, + (uint8_t *)&master_config, 1); + } + + return ret; +} + +/** + * @brief I2C interface pass-through.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of pass_through_mode in reg MASTER_CONFIG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_pass_through_get(const stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6ds3tr_c_master_config_t master_config; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, + (uint8_t *)&master_config, 1); + *val = master_config.pass_through_mode; + + return ret; +} + +/** + * @brief Master I2C pull-up enable/disable.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of pull_up_en in reg MASTER_CONFIG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_pin_mode_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_pull_up_en_t val) +{ + lsm6ds3tr_c_master_config_t master_config; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, + (uint8_t *)&master_config, 1); + + if (ret == 0) + { + master_config.pull_up_en = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, + (uint8_t *)&master_config, 1); + } + + return ret; +} + +/** + * @brief Master I2C pull-up enable/disable.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of pull_up_en in reg MASTER_CONFIG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_pin_mode_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_pull_up_en_t *val) +{ + lsm6ds3tr_c_master_config_t master_config; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, + (uint8_t *)&master_config, 1); + + switch (master_config.pull_up_en) + { + case LSM6DS3TR_C_EXT_PULL_UP: + *val = LSM6DS3TR_C_EXT_PULL_UP; + break; + + case LSM6DS3TR_C_INTERNAL_PULL_UP: + *val = LSM6DS3TR_C_INTERNAL_PULL_UP; + break; + + default: + *val = LSM6DS3TR_C_SH_PIN_MODE; + break; + } + + return ret; +} + +/** + * @brief Sensor hub trigger signal selection.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of start_config in reg MASTER_CONFIG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_syncro_mode_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_start_config_t val) +{ + lsm6ds3tr_c_master_config_t master_config; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, + (uint8_t *)&master_config, 1); + + if (ret == 0) + { + master_config.start_config = (uint8_t)val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, + (uint8_t *)&master_config, 1); + } + + return ret; +} + +/** + * @brief Sensor hub trigger signal selection.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of start_config in reg MASTER_CONFIG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_syncro_mode_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_start_config_t *val) +{ + lsm6ds3tr_c_master_config_t master_config; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, + (uint8_t *)&master_config, 1); + + switch (master_config.start_config) + { + case LSM6DS3TR_C_XL_GY_DRDY: + *val = LSM6DS3TR_C_XL_GY_DRDY; + break; + + case LSM6DS3TR_C_EXT_ON_INT2_PIN: + *val = LSM6DS3TR_C_EXT_ON_INT2_PIN; + break; + + default: + *val = LSM6DS3TR_C_SH_SYNCRO_ND; + break; + } + + return ret; +} + +/** + * @brief Manage the Master DRDY signal on INT1 pad.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of drdy_on_int1 in reg MASTER_CONFIG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_drdy_on_int1_set(const stmdev_ctx_t *ctx, + uint8_t val) +{ + lsm6ds3tr_c_master_config_t master_config; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, + (uint8_t *)&master_config, 1); + + if (ret == 0) + { + master_config.drdy_on_int1 = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, + (uint8_t *)&master_config, 1); + } + + return ret; +} + +/** + * @brief Manage the Master DRDY signal on INT1 pad.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of drdy_on_int1 in reg MASTER_CONFIG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_drdy_on_int1_get(const stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6ds3tr_c_master_config_t master_config; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, + (uint8_t *)&master_config, 1); + *val = master_config.drdy_on_int1; + + return ret; +} + +/** + * @brief Sensor hub output registers.[get] + * + * @param ctx Read / write interface definitions + * @param val Structure of registers from SENSORHUB1_REG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_read_data_raw_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_emb_sh_read_t *val) +{ + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SENSORHUB1_REG, + (uint8_t *) & (val->sh_byte_1), 12); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SENSORHUB13_REG, + (uint8_t *) & (val->sh_byte_13), 6); + } + + return ret; +} + +/** + * @brief Master command code used for stamping for sensor sync.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of master_cmd_code in + * reg MASTER_CMD_CODE + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_cmd_sens_sync_set(const stmdev_ctx_t *ctx, + uint8_t val) +{ + lsm6ds3tr_c_master_cmd_code_t master_cmd_code; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CMD_CODE, + (uint8_t *)&master_cmd_code, 1); + + if (ret == 0) + { + master_cmd_code.master_cmd_code = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MASTER_CMD_CODE, + (uint8_t *)&master_cmd_code, 1); + } + + return ret; +} + +/** + * @brief Master command code used for stamping for sensor sync.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of master_cmd_code in + * reg MASTER_CMD_CODE + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_cmd_sens_sync_get(const stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6ds3tr_c_master_cmd_code_t master_cmd_code; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CMD_CODE, + (uint8_t *)&master_cmd_code, 1); + *val = master_cmd_code.master_cmd_code; + + return ret; +} + +/** + * @brief Error code used for sensor synchronization.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of error_code in + * reg SENS_SYNC_SPI_ERROR_CODE. + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_spi_sync_error_set(const stmdev_ctx_t *ctx, + uint8_t val) +{ + lsm6ds3tr_c_sens_sync_spi_error_code_t sens_sync_spi_error_code; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SENS_SYNC_SPI_ERROR_CODE, + (uint8_t *)&sens_sync_spi_error_code, 1); + + if (ret == 0) + { + sens_sync_spi_error_code.error_code = val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SENS_SYNC_SPI_ERROR_CODE, + (uint8_t *)&sens_sync_spi_error_code, 1); + } + + return ret; +} + +/** + * @brief Error code used for sensor synchronization.[get] + * + * @param ctx Read / write interface definitions + * @param val Change the values of error_code in + * reg SENS_SYNC_SPI_ERROR_CODE. + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_spi_sync_error_get(const stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6ds3tr_c_sens_sync_spi_error_code_t sens_sync_spi_error_code; + int32_t ret; + + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SENS_SYNC_SPI_ERROR_CODE, + (uint8_t *)&sens_sync_spi_error_code, 1); + *val = sens_sync_spi_error_code.error_code; + + return ret; +} + +/** + * @brief Number of external sensors to be read by the sensor hub.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of aux_sens_on in reg SLAVE0_CONFIG. + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_num_of_dev_connected_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_aux_sens_on_t val) +{ + lsm6ds3tr_c_slave0_config_t slave0_config; + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE0_CONFIG, + (uint8_t *)&slave0_config, 1); + + if (ret == 0) + { + slave0_config.aux_sens_on = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLAVE0_CONFIG, + (uint8_t *)&slave0_config, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + } + + return ret; +} + +/** + * @brief Number of external sensors to be read by the sensor hub.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of aux_sens_on in reg SLAVE0_CONFIG. + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_num_of_dev_connected_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_aux_sens_on_t *val) +{ + lsm6ds3tr_c_slave0_config_t slave0_config; + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE0_CONFIG, + (uint8_t *)&slave0_config, 1); + + if (ret == 0) + { + switch (slave0_config.aux_sens_on) + { + case LSM6DS3TR_C_SLV_0: + *val = LSM6DS3TR_C_SLV_0; + break; + + case LSM6DS3TR_C_SLV_0_1: + *val = LSM6DS3TR_C_SLV_0_1; + break; + + case LSM6DS3TR_C_SLV_0_1_2: + *val = LSM6DS3TR_C_SLV_0_1_2; + break; + + case LSM6DS3TR_C_SLV_0_1_2_3: + *val = LSM6DS3TR_C_SLV_0_1_2_3; + break; + + default: + *val = LSM6DS3TR_C_SLV_EN_ND; + break; + } + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + + return ret; +} + +/** + * @brief Configure slave 0 for perform a write.[set] + * + * @param ctx Read / write interface definitions + * @param val Structure that contain: + * - uint8_t slv_add; 8 bit i2c device address + * - uint8_t slv_subadd; 8 bit register device address + * - uint8_t slv_data; 8 bit data to write + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_cfg_write(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_sh_cfg_write_t *val) +{ + lsm6ds3tr_c_slv0_add_t slv0_add; + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + slv0_add.slave0_add = val->slv0_add; + slv0_add.rw_0 = 0; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLV0_ADD, + (uint8_t *)&slv0_add, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLV0_SUBADD, + &(val->slv0_subadd), 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_write_reg(ctx, + LSM6DS3TR_C_DATAWRITE_SRC_MODE_SUB_SLV0, + &(val->slv0_data), 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + } + } + + return ret; +} + +/** + * @brief Configure slave 0 for perform a read.[get] + * + * @param ctx Read / write interface definitions + * @param val Structure that contain: + * - uint8_t slv_add; 8 bit i2c device address + * - uint8_t slv_subadd; 8 bit register device address + * - uint8_t slv_len; num of bit to read + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_slv0_cfg_read(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_sh_cfg_read_t *val) +{ + lsm6ds3tr_c_slave0_config_t slave0_config; + lsm6ds3tr_c_slv0_add_t slv0_add; + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + slv0_add.slave0_add = val->slv_add; + slv0_add.rw_0 = 1; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLV0_ADD, + (uint8_t *)&slv0_add, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLV0_SUBADD, + &(val->slv_subadd), 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE0_CONFIG, + (uint8_t *)&slave0_config, 1); + slave0_config.slave0_numop = val->slv_len; + + if (ret == 0) + { + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLAVE0_CONFIG, + (uint8_t *)&slave0_config, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + } + } + } + + return ret; +} + +/** + * @brief Configure slave 1 for perform a read.[get] + * + * @param ctx Read / write interface definitions + * @param val Structure that contain: + * - uint8_t slv_add; 8 bit i2c device address + * - uint8_t slv_subadd; 8 bit register device address + * - uint8_t slv_len; num of bit to read + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_slv1_cfg_read(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_sh_cfg_read_t *val) +{ + lsm6ds3tr_c_slave1_config_t slave1_config; + lsm6ds3tr_c_slv1_add_t slv1_add; + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + slv1_add.slave1_add = val->slv_add; + slv1_add.r_1 = 1; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLV1_ADD, + (uint8_t *)&slv1_add, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLV1_SUBADD, + &(val->slv_subadd), 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE1_CONFIG, + (uint8_t *)&slave1_config, 1); + slave1_config.slave1_numop = val->slv_len; + + if (ret == 0) + { + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLAVE1_CONFIG, + (uint8_t *)&slave1_config, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + } + } + } + + return ret; +} + +/** + * @brief Configure slave 2 for perform a read.[get] + * + * @param ctx Read / write interface definitions + * @param val Structure that contain: + * - uint8_t slv_add; 8 bit i2c device address + * - uint8_t slv_subadd; 8 bit register device address + * - uint8_t slv_len; num of bit to read + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_slv2_cfg_read(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_sh_cfg_read_t *val) +{ + lsm6ds3tr_c_slv2_add_t slv2_add; + lsm6ds3tr_c_slave2_config_t slave2_config; + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + slv2_add.slave2_add = val->slv_add; + slv2_add.r_2 = 1; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLV2_ADD, + (uint8_t *)&slv2_add, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLV2_SUBADD, + &(val->slv_subadd), 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE2_CONFIG, + (uint8_t *)&slave2_config, 1); + + if (ret == 0) + { + slave2_config.slave2_numop = val->slv_len; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLAVE2_CONFIG, + (uint8_t *)&slave2_config, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + } + } + } + + return ret; +} + +/** + * @brief Configure slave 3 for perform a read.[get] + * + * @param ctx Read / write interface definitions + * @param val Structure that contain: + * - uint8_t slv_add; 8 bit i2c device address + * - uint8_t slv_subadd; 8 bit register device address + * - uint8_t slv_len; num of bit to read + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_slv3_cfg_read(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_sh_cfg_read_t *val) +{ + lsm6ds3tr_c_slave3_config_t slave3_config; + lsm6ds3tr_c_slv3_add_t slv3_add; + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + slv3_add.slave3_add = val->slv_add; + slv3_add.r_3 = 1; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLV3_ADD, + (uint8_t *)&slv3_add, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLV3_SUBADD, + (uint8_t *) & (val->slv_subadd), 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE3_CONFIG, + (uint8_t *)&slave3_config, 1); + + if (ret == 0) + { + slave3_config.slave3_numop = val->slv_len; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLAVE3_CONFIG, + (uint8_t *)&slave3_config, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + } + } + } + + return ret; +} + +/** + * @brief Decimation of read operation on Slave 0 starting from the + * sensor hub trigger.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of slave0_rate in reg SLAVE0_CONFIG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_slave_0_dec_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_slave0_rate_t val) +{ + lsm6ds3tr_c_slave0_config_t slave0_config; + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE0_CONFIG, + (uint8_t *)&slave0_config, 1); + + if (ret == 0) + { + slave0_config.slave0_rate = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLAVE0_CONFIG, + (uint8_t *)&slave0_config, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + } + + return ret; +} + +/** + * @brief Decimation of read operation on Slave 0 starting from the + * sensor hub trigger.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of slave0_rate in reg SLAVE0_CONFIG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_slave_0_dec_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_slave0_rate_t *val) +{ + lsm6ds3tr_c_slave0_config_t slave0_config; + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE0_CONFIG, + (uint8_t *)&slave0_config, 1); + + if (ret == 0) + { + switch (slave0_config.slave0_rate) + { + case LSM6DS3TR_C_SL0_NO_DEC: + *val = LSM6DS3TR_C_SL0_NO_DEC; + break; + + case LSM6DS3TR_C_SL0_DEC_2: + *val = LSM6DS3TR_C_SL0_DEC_2; + break; + + case LSM6DS3TR_C_SL0_DEC_4: + *val = LSM6DS3TR_C_SL0_DEC_4; + break; + + case LSM6DS3TR_C_SL0_DEC_8: + *val = LSM6DS3TR_C_SL0_DEC_8; + break; + + default: + *val = LSM6DS3TR_C_SL0_DEC_ND; + break; + } + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + + return ret; +} + +/** + * @brief Slave 0 write operation is performed only at the first sensor + * hub cycle. + * This is effective if the Aux_sens_on[1:0] field in + * SLAVE0_CONFIG(04h) is set to a value other than 00.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of write_once in reg SLAVE1_CONFIG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_write_mode_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_write_once_t val) +{ + lsm6ds3tr_c_slave1_config_t slave1_config; + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE1_CONFIG, + (uint8_t *)&slave1_config, 1); + slave1_config.write_once = (uint8_t) val; + + if (ret == 0) + { + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLAVE1_CONFIG, + (uint8_t *)&slave1_config, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + } + + return ret; +} + +/** + * @brief Slave 0 write operation is performed only at the first sensor + * hub cycle. + * This is effective if the Aux_sens_on[1:0] field in + * SLAVE0_CONFIG(04h) is set to a value other than 00.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of write_once in reg SLAVE1_CONFIG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_write_mode_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_write_once_t *val) +{ + lsm6ds3tr_c_slave1_config_t slave1_config; + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE1_CONFIG, + (uint8_t *)&slave1_config, 1); + + if (ret == 0) + { + switch (slave1_config.write_once) + { + case LSM6DS3TR_C_EACH_SH_CYCLE: + *val = LSM6DS3TR_C_EACH_SH_CYCLE; + break; + + case LSM6DS3TR_C_ONLY_FIRST_CYCLE: + *val = LSM6DS3TR_C_ONLY_FIRST_CYCLE; + break; + + default: + *val = LSM6DS3TR_C_SH_WR_MODE_ND; + break; + } + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + + return ret; +} + +/** + * @brief Decimation of read operation on Slave 1 starting from the + * sensor hub trigger.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of slave1_rate in reg SLAVE1_CONFIG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_slave_1_dec_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_slave1_rate_t val) +{ + lsm6ds3tr_c_slave1_config_t slave1_config; + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE1_CONFIG, + (uint8_t *)&slave1_config, 1); + + if (ret == 0) + { + slave1_config.slave1_rate = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLAVE1_CONFIG, + (uint8_t *)&slave1_config, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + } + + return ret; +} + +/** + * @brief Decimation of read operation on Slave 1 starting from the + * sensor hub trigger.[get] + * + * @param ctx Read / write interface definitions reg SLAVE1_CONFIG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_slave_1_dec_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_slave1_rate_t *val) +{ + lsm6ds3tr_c_slave1_config_t slave1_config; + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE1_CONFIG, + (uint8_t *)&slave1_config, 1); + + if (ret == 0) + { + switch (slave1_config.slave1_rate) + { + case LSM6DS3TR_C_SL1_NO_DEC: + *val = LSM6DS3TR_C_SL1_NO_DEC; + break; + + case LSM6DS3TR_C_SL1_DEC_2: + *val = LSM6DS3TR_C_SL1_DEC_2; + break; + + case LSM6DS3TR_C_SL1_DEC_4: + *val = LSM6DS3TR_C_SL1_DEC_4; + break; + + case LSM6DS3TR_C_SL1_DEC_8: + *val = LSM6DS3TR_C_SL1_DEC_8; + break; + + default: + *val = LSM6DS3TR_C_SL1_DEC_ND; + break; + } + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + + return ret; +} + +/** + * @brief Decimation of read operation on Slave 2 starting from the + * sensor hub trigger.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of slave2_rate in reg SLAVE2_CONFIG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_slave_2_dec_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_slave2_rate_t val) +{ + lsm6ds3tr_c_slave2_config_t slave2_config; + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE2_CONFIG, + (uint8_t *)&slave2_config, 1); + + if (ret == 0) + { + slave2_config.slave2_rate = (uint8_t) val; + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLAVE2_CONFIG, + (uint8_t *)&slave2_config, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + } + + return ret; +} + +/** + * @brief Decimation of read operation on Slave 2 starting from the + * sensor hub trigger.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of slave2_rate in reg SLAVE2_CONFIG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_slave_2_dec_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_slave2_rate_t *val) +{ + lsm6ds3tr_c_slave2_config_t slave2_config; + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE2_CONFIG, + (uint8_t *)&slave2_config, 1); + + if (ret == 0) + { + switch (slave2_config.slave2_rate) + { + case LSM6DS3TR_C_SL2_NO_DEC: + *val = LSM6DS3TR_C_SL2_NO_DEC; + break; + + case LSM6DS3TR_C_SL2_DEC_2: + *val = LSM6DS3TR_C_SL2_DEC_2; + break; + + case LSM6DS3TR_C_SL2_DEC_4: + *val = LSM6DS3TR_C_SL2_DEC_4; + break; + + case LSM6DS3TR_C_SL2_DEC_8: + *val = LSM6DS3TR_C_SL2_DEC_8; + break; + + default: + *val = LSM6DS3TR_C_SL2_DEC_ND; + break; + } + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + + return ret; +} + +/** + * @brief Decimation of read operation on Slave 3 starting from the + * sensor hub trigger.[set] + * + * @param ctx Read / write interface definitions + * @param val Change the values of slave3_rate in reg SLAVE3_CONFIG + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_slave_3_dec_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_slave3_rate_t val) +{ + lsm6ds3tr_c_slave3_config_t slave3_config; + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE3_CONFIG, + (uint8_t *)&slave3_config, 1); + slave3_config.slave3_rate = (uint8_t)val; + + if (ret == 0) + { + ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLAVE3_CONFIG, + (uint8_t *)&slave3_config, 1); + + if (ret == 0) + { + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + } + + return ret; +} + +/** + * @brief Decimation of read operation on Slave 3 starting from the + * sensor hub trigger.[get] + * + * @param ctx Read / write interface definitions + * @param val Get the values of slave3_rate in reg SLAVE3_CONFIG. + * @retval Interface status (MANDATORY: return 0 -> no Error). + * + */ +int32_t lsm6ds3tr_c_sh_slave_3_dec_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_slave3_rate_t *val) +{ + lsm6ds3tr_c_slave3_config_t slave3_config; + int32_t ret; + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); + + if (ret == 0) + { + ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE3_CONFIG, + (uint8_t *)&slave3_config, 1); + + if (ret == 0) + { + switch (slave3_config.slave3_rate) + { + case LSM6DS3TR_C_SL3_NO_DEC: + *val = LSM6DS3TR_C_SL3_NO_DEC; + break; + + case LSM6DS3TR_C_SL3_DEC_2: + *val = LSM6DS3TR_C_SL3_DEC_2; + break; + + case LSM6DS3TR_C_SL3_DEC_4: + *val = LSM6DS3TR_C_SL3_DEC_4; + break; + + case LSM6DS3TR_C_SL3_DEC_8: + *val = LSM6DS3TR_C_SL3_DEC_8; + break; + + default: + *val = LSM6DS3TR_C_SL3_DEC_ND; + break; + } + + ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); + } + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @} + * + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/airmouse/lib/lsm6ds3tr-api/lsm6ds3tr-c_reg.h b/airmouse/lib/lsm6ds3tr-api/lsm6ds3tr-c_reg.h new file mode 100644 index 00000000000..3411c79091a --- /dev/null +++ b/airmouse/lib/lsm6ds3tr-api/lsm6ds3tr-c_reg.h @@ -0,0 +1,2804 @@ +/** + ****************************************************************************** + * @file lsm6ds3tr_c_reg.h + * @author Sensors Software Solution Team + * @brief This file contains all the functions prototypes for the + * lsm6ds3tr_c_reg.c driver. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef LSM6DS3TR_C_DRIVER_H +#define LSM6DS3TR_C_DRIVER_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include +#include +#include + +/** @addtogroup LSM6DS3TR_C + * @{ + * + */ + +/** @defgroup Endianness definitions + * @{ + * + */ + +#ifndef DRV_BYTE_ORDER +#ifndef __BYTE_ORDER__ + +#define DRV_LITTLE_ENDIAN 1234 +#define DRV_BIG_ENDIAN 4321 + +/** if _BYTE_ORDER is not defined, choose the endianness of your architecture + * by uncommenting the define which fits your platform endianness + */ +//#define DRV_BYTE_ORDER DRV_BIG_ENDIAN +#define DRV_BYTE_ORDER DRV_LITTLE_ENDIAN + +#else /* defined __BYTE_ORDER__ */ + +#define DRV_LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__ +#define DRV_BIG_ENDIAN __ORDER_BIG_ENDIAN__ +#define DRV_BYTE_ORDER __BYTE_ORDER__ + +#endif /* __BYTE_ORDER__*/ +#endif /* DRV_BYTE_ORDER */ + +/** + * @} + * + */ + +/** @defgroup STMicroelectronics sensors common types + * @{ + * + */ + +#ifndef MEMS_SHARED_TYPES +#define MEMS_SHARED_TYPES + +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} bitwise_t; + +#define PROPERTY_DISABLE (0U) +#define PROPERTY_ENABLE (1U) + +/** @addtogroup Interfaces_Functions + * @brief This section provide a set of functions used to read and + * write a generic register of the device. + * MANDATORY: return 0 -> no Error. + * @{ + * + */ + +typedef int32_t (*stmdev_write_ptr)(void *, uint8_t, const uint8_t *, uint16_t); +typedef int32_t (*stmdev_read_ptr)(void *, uint8_t, uint8_t *, uint16_t); +typedef void (*stmdev_mdelay_ptr)(uint32_t millisec); + +typedef struct +{ + /** Component mandatory fields **/ + stmdev_write_ptr write_reg; + stmdev_read_ptr read_reg; + /** Component optional fields **/ + stmdev_mdelay_ptr mdelay; + /** Customizable optional pointer **/ + void *handle; +} stmdev_ctx_t; + +/** + * @} + * + */ + +#endif /* MEMS_SHARED_TYPES */ + +#ifndef MEMS_UCF_SHARED_TYPES +#define MEMS_UCF_SHARED_TYPES + +/** @defgroup Generic address-data structure definition + * @brief This structure is useful to load a predefined configuration + * of a sensor. + * You can create a sensor configuration by your own or using + * Unico / Unicleo tools available on STMicroelectronics + * web site. + * + * @{ + * + */ + +typedef struct +{ + uint8_t address; + uint8_t data; +} ucf_line_t; + +/** + * @} + * + */ + +#endif /* MEMS_UCF_SHARED_TYPES */ + +/** + * @} + * + */ + +/** @defgroup LSM6DS3TR_C_Infos + * @{ + * + */ + +/** I2C Device Address 8 bit format if SA0=0 -> D5 if SA0=1 -> D7 **/ +#define LSM6DS3TR_C_I2C_ADD_L 0xD5U +#define LSM6DS3TR_C_I2C_ADD_H 0xD7U + +/** Device Identification (Who am I) **/ +#define LSM6DS3TR_C_ID 0x6AU + +/** + * @} + * + */ + +#define LSM6DS3TR_C_FUNC_CFG_ACCESS 0x01U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t not_used_01 : 5; + uint8_t func_cfg_en : 3; /* func_cfg_en + func_cfg_en_b */ +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t func_cfg_en : 3; /* func_cfg_en + func_cfg_en_b */ + uint8_t not_used_01 : 5; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_func_cfg_access_t; + +#define LSM6DS3TR_C_SENSOR_SYNC_TIME_FRAME 0x04U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t tph : 4; + uint8_t not_used_01 : 4; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_01 : 4; + uint8_t tph : 4; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_sensor_sync_time_frame_t; + +#define LSM6DS3TR_C_SENSOR_SYNC_RES_RATIO 0x05U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t rr : 2; + uint8_t not_used_01 : 6; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_01 : 6; + uint8_t rr : 2; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_sensor_sync_res_ratio_t; + +#define LSM6DS3TR_C_FIFO_CTRL1 0x06U +typedef struct +{ + uint8_t fth : 8; /* + FIFO_CTRL2(fth) */ +} lsm6ds3tr_c_fifo_ctrl1_t; + +#define LSM6DS3TR_C_FIFO_CTRL2 0x07U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t fth : 3; /* + FIFO_CTRL1(fth) */ + uint8_t fifo_temp_en : 1; + uint8_t not_used_01 : 2; + uint8_t timer_pedo_fifo_drdy : 1; + uint8_t timer_pedo_fifo_en : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t timer_pedo_fifo_en : 1; + uint8_t timer_pedo_fifo_drdy : 1; + uint8_t not_used_01 : 2; + uint8_t fifo_temp_en : 1; + uint8_t fth : 3; /* + FIFO_CTRL1(fth) */ +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_fifo_ctrl2_t; + +#define LSM6DS3TR_C_FIFO_CTRL3 0x08U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t dec_fifo_xl : 3; + uint8_t dec_fifo_gyro : 3; + uint8_t not_used_01 : 2; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_01 : 2; + uint8_t dec_fifo_gyro : 3; + uint8_t dec_fifo_xl : 3; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_fifo_ctrl3_t; + +#define LSM6DS3TR_C_FIFO_CTRL4 0x09U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t dec_ds3_fifo : 3; + uint8_t dec_ds4_fifo : 3; + uint8_t only_high_data : 1; + uint8_t stop_on_fth : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t stop_on_fth : 1; + uint8_t only_high_data : 1; + uint8_t dec_ds4_fifo : 3; + uint8_t dec_ds3_fifo : 3; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_fifo_ctrl4_t; + +#define LSM6DS3TR_C_FIFO_CTRL5 0x0AU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t fifo_mode : 3; + uint8_t odr_fifo : 4; + uint8_t not_used_01 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_01 : 1; + uint8_t odr_fifo : 4; + uint8_t fifo_mode : 3; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_fifo_ctrl5_t; + +#define LSM6DS3TR_C_DRDY_PULSE_CFG_G 0x0BU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t int2_wrist_tilt : 1; + uint8_t not_used_01 : 6; + uint8_t drdy_pulsed : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t drdy_pulsed : 1; + uint8_t not_used_01 : 6; + uint8_t int2_wrist_tilt : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_drdy_pulse_cfg_g_t; + +#define LSM6DS3TR_C_INT1_CTRL 0x0DU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t int1_drdy_xl : 1; + uint8_t int1_drdy_g : 1; + uint8_t int1_boot : 1; + uint8_t int1_fth : 1; + uint8_t int1_fifo_ovr : 1; + uint8_t int1_full_flag : 1; + uint8_t int1_sign_mot : 1; + uint8_t int1_step_detector : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t int1_step_detector : 1; + uint8_t int1_sign_mot : 1; + uint8_t int1_full_flag : 1; + uint8_t int1_fifo_ovr : 1; + uint8_t int1_fth : 1; + uint8_t int1_boot : 1; + uint8_t int1_drdy_g : 1; + uint8_t int1_drdy_xl : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_int1_ctrl_t; + +#define LSM6DS3TR_C_INT2_CTRL 0x0EU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t int2_drdy_xl : 1; + uint8_t int2_drdy_g : 1; + uint8_t int2_drdy_temp : 1; + uint8_t int2_fth : 1; + uint8_t int2_fifo_ovr : 1; + uint8_t int2_full_flag : 1; + uint8_t int2_step_count_ov : 1; + uint8_t int2_step_delta : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t int2_step_delta : 1; + uint8_t int2_step_count_ov : 1; + uint8_t int2_full_flag : 1; + uint8_t int2_fifo_ovr : 1; + uint8_t int2_fth : 1; + uint8_t int2_drdy_temp : 1; + uint8_t int2_drdy_g : 1; + uint8_t int2_drdy_xl : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_int2_ctrl_t; + +#define LSM6DS3TR_C_WHO_AM_I 0x0FU +#define LSM6DS3TR_C_CTRL1_XL 0x10U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bw0_xl : 1; + uint8_t lpf1_bw_sel : 1; + uint8_t fs_xl : 2; + uint8_t odr_xl : 4; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t odr_xl : 4; + uint8_t fs_xl : 2; + uint8_t lpf1_bw_sel : 1; + uint8_t bw0_xl : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_ctrl1_xl_t; + +#define LSM6DS3TR_C_CTRL2_G 0x11U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t not_used_01 : 1; + uint8_t fs_g : 3; /* fs_g + fs_125 */ + uint8_t odr_g : 4; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t odr_g : 4; + uint8_t fs_g : 3; /* fs_g + fs_125 */ + uint8_t not_used_01 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_ctrl2_g_t; + +#define LSM6DS3TR_C_CTRL3_C 0x12U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t sw_reset : 1; + uint8_t ble : 1; + uint8_t if_inc : 1; + uint8_t sim : 1; + uint8_t pp_od : 1; + uint8_t h_lactive : 1; + uint8_t bdu : 1; + uint8_t boot : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t boot : 1; + uint8_t bdu : 1; + uint8_t h_lactive : 1; + uint8_t pp_od : 1; + uint8_t sim : 1; + uint8_t if_inc : 1; + uint8_t ble : 1; + uint8_t sw_reset : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_ctrl3_c_t; + +#define LSM6DS3TR_C_CTRL4_C 0x13U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t not_used_01 : 1; + uint8_t lpf1_sel_g : 1; + uint8_t i2c_disable : 1; + uint8_t drdy_mask : 1; + uint8_t den_drdy_int1 : 1; + uint8_t int2_on_int1 : 1; + uint8_t sleep : 1; + uint8_t den_xl_en : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t den_xl_en : 1; + uint8_t sleep : 1; + uint8_t int2_on_int1 : 1; + uint8_t den_drdy_int1 : 1; + uint8_t drdy_mask : 1; + uint8_t i2c_disable : 1; + uint8_t lpf1_sel_g : 1; + uint8_t not_used_01 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_ctrl4_c_t; + +#define LSM6DS3TR_C_CTRL5_C 0x14U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t st_xl : 2; + uint8_t st_g : 2; + uint8_t den_lh : 1; + uint8_t rounding : 3; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t rounding : 3; + uint8_t den_lh : 1; + uint8_t st_g : 2; + uint8_t st_xl : 2; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_ctrl5_c_t; + +#define LSM6DS3TR_C_CTRL6_C 0x15U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t ftype : 2; + uint8_t not_used_01 : 1; + uint8_t usr_off_w : 1; + uint8_t xl_hm_mode : 1; + uint8_t den_mode : 3; /* trig_en + lvl_en + lvl2_en */ +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t den_mode : 3; /* trig_en + lvl_en + lvl2_en */ + uint8_t xl_hm_mode : 1; + uint8_t usr_off_w : 1; + uint8_t not_used_01 : 1; + uint8_t ftype : 2; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_ctrl6_c_t; + +#define LSM6DS3TR_C_CTRL7_G 0x16U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t not_used_01 : 2; + uint8_t rounding_status : 1; + uint8_t not_used_02 : 1; + uint8_t hpm_g : 2; + uint8_t hp_en_g : 1; + uint8_t g_hm_mode : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t g_hm_mode : 1; + uint8_t hp_en_g : 1; + uint8_t hpm_g : 2; + uint8_t not_used_02 : 1; + uint8_t rounding_status : 1; + uint8_t not_used_01 : 2; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_ctrl7_g_t; + +#define LSM6DS3TR_C_CTRL8_XL 0x17U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t low_pass_on_6d : 1; + uint8_t not_used_01 : 1; + uint8_t hp_slope_xl_en : 1; + uint8_t input_composite : 1; + uint8_t hp_ref_mode : 1; + uint8_t hpcf_xl : 2; + uint8_t lpf2_xl_en : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t lpf2_xl_en : 1; + uint8_t hpcf_xl : 2; + uint8_t hp_ref_mode : 1; + uint8_t input_composite : 1; + uint8_t hp_slope_xl_en : 1; + uint8_t not_used_01 : 1; + uint8_t low_pass_on_6d : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_ctrl8_xl_t; + +#define LSM6DS3TR_C_CTRL9_XL 0x18U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t not_used_01 : 2; + uint8_t soft_en : 1; + uint8_t not_used_02 : 1; + uint8_t den_xl_g : 1; + uint8_t den_z : 1; + uint8_t den_y : 1; + uint8_t den_x : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t den_x : 1; + uint8_t den_y : 1; + uint8_t den_z : 1; + uint8_t den_xl_g : 1; + uint8_t not_used_02 : 1; + uint8_t soft_en : 1; + uint8_t not_used_01 : 2; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_ctrl9_xl_t; + +#define LSM6DS3TR_C_CTRL10_C 0x19U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t sign_motion_en : 1; + uint8_t pedo_rst_step : 1; + uint8_t func_en : 1; + uint8_t tilt_en : 1; + uint8_t pedo_en : 1; + uint8_t timer_en : 1; + uint8_t not_used_01 : 1; + uint8_t wrist_tilt_en : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t wrist_tilt_en : 1; + uint8_t not_used_01 : 1; + uint8_t timer_en : 1; + uint8_t pedo_en : 1; + uint8_t tilt_en : 1; + uint8_t func_en : 1; + uint8_t pedo_rst_step : 1; + uint8_t sign_motion_en : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_ctrl10_c_t; + +#define LSM6DS3TR_C_MASTER_CONFIG 0x1AU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t master_on : 1; + uint8_t iron_en : 1; + uint8_t pass_through_mode : 1; + uint8_t pull_up_en : 1; + uint8_t start_config : 1; + uint8_t not_used_01 : 1; + uint8_t data_valid_sel_fifo : 1; + uint8_t drdy_on_int1 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t drdy_on_int1 : 1; + uint8_t data_valid_sel_fifo : 1; + uint8_t not_used_01 : 1; + uint8_t start_config : 1; + uint8_t pull_up_en : 1; + uint8_t pass_through_mode : 1; + uint8_t iron_en : 1; + uint8_t master_on : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_master_config_t; + +#define LSM6DS3TR_C_WAKE_UP_SRC 0x1BU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t z_wu : 1; + uint8_t y_wu : 1; + uint8_t x_wu : 1; + uint8_t wu_ia : 1; + uint8_t sleep_state_ia : 1; + uint8_t ff_ia : 1; + uint8_t not_used_01 : 2; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_01 : 2; + uint8_t ff_ia : 1; + uint8_t sleep_state_ia : 1; + uint8_t wu_ia : 1; + uint8_t x_wu : 1; + uint8_t y_wu : 1; + uint8_t z_wu : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_wake_up_src_t; + +#define LSM6DS3TR_C_TAP_SRC 0x1CU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t z_tap : 1; + uint8_t y_tap : 1; + uint8_t x_tap : 1; + uint8_t tap_sign : 1; + uint8_t double_tap : 1; + uint8_t single_tap : 1; + uint8_t tap_ia : 1; + uint8_t not_used_01 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_01 : 1; + uint8_t tap_ia : 1; + uint8_t single_tap : 1; + uint8_t double_tap : 1; + uint8_t tap_sign : 1; + uint8_t x_tap : 1; + uint8_t y_tap : 1; + uint8_t z_tap : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_tap_src_t; + +#define LSM6DS3TR_C_D6D_SRC 0x1DU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t xl : 1; + uint8_t xh : 1; + uint8_t yl : 1; + uint8_t yh : 1; + uint8_t zl : 1; + uint8_t zh : 1; + uint8_t d6d_ia : 1; + uint8_t den_drdy : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t den_drdy : 1; + uint8_t d6d_ia : 1; + uint8_t zh : 1; + uint8_t zl : 1; + uint8_t yh : 1; + uint8_t yl : 1; + uint8_t xh : 1; + uint8_t xl : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_d6d_src_t; + +#define LSM6DS3TR_C_STATUS_REG 0x1EU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t xlda : 1; + uint8_t gda : 1; + uint8_t tda : 1; + uint8_t not_used_01 : 5; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_01 : 5; + uint8_t tda : 1; + uint8_t gda : 1; + uint8_t xlda : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_status_reg_t; + +#define LSM6DS3TR_C_OUT_TEMP_L 0x20U +#define LSM6DS3TR_C_OUT_TEMP_H 0x21U +#define LSM6DS3TR_C_OUTX_L_G 0x22U +#define LSM6DS3TR_C_OUTX_H_G 0x23U +#define LSM6DS3TR_C_OUTY_L_G 0x24U +#define LSM6DS3TR_C_OUTY_H_G 0x25U +#define LSM6DS3TR_C_OUTZ_L_G 0x26U +#define LSM6DS3TR_C_OUTZ_H_G 0x27U +#define LSM6DS3TR_C_OUTX_L_XL 0x28U +#define LSM6DS3TR_C_OUTX_H_XL 0x29U +#define LSM6DS3TR_C_OUTY_L_XL 0x2AU +#define LSM6DS3TR_C_OUTY_H_XL 0x2BU +#define LSM6DS3TR_C_OUTZ_L_XL 0x2CU +#define LSM6DS3TR_C_OUTZ_H_XL 0x2DU +#define LSM6DS3TR_C_SENSORHUB1_REG 0x2EU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_sensorhub1_reg_t; + +#define LSM6DS3TR_C_SENSORHUB2_REG 0x2FU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_sensorhub2_reg_t; + +#define LSM6DS3TR_C_SENSORHUB3_REG 0x30U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_sensorhub3_reg_t; + +#define LSM6DS3TR_C_SENSORHUB4_REG 0x31U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_sensorhub4_reg_t; + +#define LSM6DS3TR_C_SENSORHUB5_REG 0x32U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_sensorhub5_reg_t; + +#define LSM6DS3TR_C_SENSORHUB6_REG 0x33U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_sensorhub6_reg_t; + +#define LSM6DS3TR_C_SENSORHUB7_REG 0x34U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_sensorhub7_reg_t; + +#define LSM6DS3TR_C_SENSORHUB8_REG 0x35U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_sensorhub8_reg_t; + +#define LSM6DS3TR_C_SENSORHUB9_REG 0x36U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_sensorhub9_reg_t; + +#define LSM6DS3TR_C_SENSORHUB10_REG 0x37U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_sensorhub10_reg_t; + +#define LSM6DS3TR_C_SENSORHUB11_REG 0x38U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_sensorhub11_reg_t; + +#define LSM6DS3TR_C_SENSORHUB12_REG 0x39U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_sensorhub12_reg_t; + +#define LSM6DS3TR_C_FIFO_STATUS1 0x3AU +typedef struct +{ + uint8_t diff_fifo : 8; /* + FIFO_STATUS2(diff_fifo) */ +} lsm6ds3tr_c_fifo_status1_t; + +#define LSM6DS3TR_C_FIFO_STATUS2 0x3BU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t diff_fifo : 3; /* + FIFO_STATUS1(diff_fifo) */ + uint8_t not_used_01 : 1; + uint8_t fifo_empty : 1; + uint8_t fifo_full_smart : 1; + uint8_t over_run : 1; + uint8_t waterm : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t waterm : 1; + uint8_t over_run : 1; + uint8_t fifo_full_smart : 1; + uint8_t fifo_empty : 1; + uint8_t not_used_01 : 1; + uint8_t diff_fifo : 3; /* + FIFO_STATUS1(diff_fifo) */ +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_fifo_status2_t; + +#define LSM6DS3TR_C_FIFO_STATUS3 0x3CU +typedef struct +{ + uint8_t fifo_pattern : 8; /* + FIFO_STATUS4(fifo_pattern) */ +} lsm6ds3tr_c_fifo_status3_t; + +#define LSM6DS3TR_C_FIFO_STATUS4 0x3DU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t fifo_pattern : 2; /* + FIFO_STATUS3(fifo_pattern) */ + uint8_t not_used_01 : 6; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_01 : 6; + uint8_t fifo_pattern : 2; /* + FIFO_STATUS3(fifo_pattern) */ +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_fifo_status4_t; + +#define LSM6DS3TR_C_FIFO_DATA_OUT_L 0x3EU +#define LSM6DS3TR_C_FIFO_DATA_OUT_H 0x3FU +#define LSM6DS3TR_C_TIMESTAMP0_REG 0x40U +#define LSM6DS3TR_C_TIMESTAMP1_REG 0x41U +#define LSM6DS3TR_C_TIMESTAMP2_REG 0x42U +#define LSM6DS3TR_C_STEP_TIMESTAMP_L 0x49U +#define LSM6DS3TR_C_STEP_TIMESTAMP_H 0x4AU +#define LSM6DS3TR_C_STEP_COUNTER_L 0x4BU +#define LSM6DS3TR_C_STEP_COUNTER_H 0x4CU + +#define LSM6DS3TR_C_SENSORHUB13_REG 0x4DU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_sensorhub13_reg_t; + +#define LSM6DS3TR_C_SENSORHUB14_REG 0x4EU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_sensorhub14_reg_t; + +#define LSM6DS3TR_C_SENSORHUB15_REG 0x4FU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_sensorhub15_reg_t; + +#define LSM6DS3TR_C_SENSORHUB16_REG 0x50U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_sensorhub16_reg_t; + +#define LSM6DS3TR_C_SENSORHUB17_REG 0x51U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_sensorhub17_reg_t; + +#define LSM6DS3TR_C_SENSORHUB18_REG 0x52U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_sensorhub18_reg_t; + +#define LSM6DS3TR_C_FUNC_SRC1 0x53U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t sensorhub_end_op : 1; + uint8_t si_end_op : 1; + uint8_t hi_fail : 1; + uint8_t step_overflow : 1; + uint8_t step_detected : 1; + uint8_t tilt_ia : 1; + uint8_t sign_motion_ia : 1; + uint8_t step_count_delta_ia : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t step_count_delta_ia : 1; + uint8_t sign_motion_ia : 1; + uint8_t tilt_ia : 1; + uint8_t step_detected : 1; + uint8_t step_overflow : 1; + uint8_t hi_fail : 1; + uint8_t si_end_op : 1; + uint8_t sensorhub_end_op : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_func_src1_t; + +#define LSM6DS3TR_C_FUNC_SRC2 0x54U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t wrist_tilt_ia : 1; + uint8_t not_used_01 : 2; + uint8_t slave0_nack : 1; + uint8_t slave1_nack : 1; + uint8_t slave2_nack : 1; + uint8_t slave3_nack : 1; + uint8_t not_used_02 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_02 : 1; + uint8_t slave3_nack : 1; + uint8_t slave2_nack : 1; + uint8_t slave1_nack : 1; + uint8_t slave0_nack : 1; + uint8_t not_used_01 : 2; + uint8_t wrist_tilt_ia : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_func_src2_t; + +#define LSM6DS3TR_C_WRIST_TILT_IA 0x55U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t not_used_01 : 2; + uint8_t wrist_tilt_ia_zneg : 1; + uint8_t wrist_tilt_ia_zpos : 1; + uint8_t wrist_tilt_ia_yneg : 1; + uint8_t wrist_tilt_ia_ypos : 1; + uint8_t wrist_tilt_ia_xneg : 1; + uint8_t wrist_tilt_ia_xpos : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t wrist_tilt_ia_xpos : 1; + uint8_t wrist_tilt_ia_xneg : 1; + uint8_t wrist_tilt_ia_ypos : 1; + uint8_t wrist_tilt_ia_yneg : 1; + uint8_t wrist_tilt_ia_zpos : 1; + uint8_t wrist_tilt_ia_zneg : 1; + uint8_t not_used_01 : 2; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_wrist_tilt_ia_t; + +#define LSM6DS3TR_C_TAP_CFG 0x58U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t lir : 1; + uint8_t tap_z_en : 1; + uint8_t tap_y_en : 1; + uint8_t tap_x_en : 1; + uint8_t slope_fds : 1; + uint8_t inact_en : 2; + uint8_t interrupts_enable : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t interrupts_enable : 1; + uint8_t inact_en : 2; + uint8_t slope_fds : 1; + uint8_t tap_x_en : 1; + uint8_t tap_y_en : 1; + uint8_t tap_z_en : 1; + uint8_t lir : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_tap_cfg_t; + +#define LSM6DS3TR_C_TAP_THS_6D 0x59U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t tap_ths : 5; + uint8_t sixd_ths : 2; + uint8_t d4d_en : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t d4d_en : 1; + uint8_t sixd_ths : 2; + uint8_t tap_ths : 5; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_tap_ths_6d_t; + +#define LSM6DS3TR_C_INT_DUR2 0x5AU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t shock : 2; + uint8_t quiet : 2; + uint8_t dur : 4; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t dur : 4; + uint8_t quiet : 2; + uint8_t shock : 2; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_int_dur2_t; + +#define LSM6DS3TR_C_WAKE_UP_THS 0x5BU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t wk_ths : 6; + uint8_t not_used_01 : 1; + uint8_t single_double_tap : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t single_double_tap : 1; + uint8_t not_used_01 : 1; + uint8_t wk_ths : 6; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_wake_up_ths_t; + +#define LSM6DS3TR_C_WAKE_UP_DUR 0x5CU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t sleep_dur : 4; + uint8_t timer_hr : 1; + uint8_t wake_dur : 2; + uint8_t ff_dur : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t ff_dur : 1; + uint8_t wake_dur : 2; + uint8_t timer_hr : 1; + uint8_t sleep_dur : 4; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_wake_up_dur_t; + +#define LSM6DS3TR_C_FREE_FALL 0x5DU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t ff_ths : 3; + uint8_t ff_dur : 5; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t ff_dur : 5; + uint8_t ff_ths : 3; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_free_fall_t; + +#define LSM6DS3TR_C_MD1_CFG 0x5EU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t int1_timer : 1; + uint8_t int1_tilt : 1; + uint8_t int1_6d : 1; + uint8_t int1_double_tap : 1; + uint8_t int1_ff : 1; + uint8_t int1_wu : 1; + uint8_t int1_single_tap : 1; + uint8_t int1_inact_state : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t int1_inact_state : 1; + uint8_t int1_single_tap : 1; + uint8_t int1_wu : 1; + uint8_t int1_ff : 1; + uint8_t int1_double_tap : 1; + uint8_t int1_6d : 1; + uint8_t int1_tilt : 1; + uint8_t int1_timer : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_md1_cfg_t; + +#define LSM6DS3TR_C_MD2_CFG 0x5FU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t int2_iron : 1; + uint8_t int2_tilt : 1; + uint8_t int2_6d : 1; + uint8_t int2_double_tap : 1; + uint8_t int2_ff : 1; + uint8_t int2_wu : 1; + uint8_t int2_single_tap : 1; + uint8_t int2_inact_state : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t int2_inact_state : 1; + uint8_t int2_single_tap : 1; + uint8_t int2_wu : 1; + uint8_t int2_ff : 1; + uint8_t int2_double_tap : 1; + uint8_t int2_6d : 1; + uint8_t int2_tilt : 1; + uint8_t int2_iron : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_md2_cfg_t; + +#define LSM6DS3TR_C_MASTER_CMD_CODE 0x60U +typedef struct +{ + uint8_t master_cmd_code : 8; +} lsm6ds3tr_c_master_cmd_code_t; + +#define LSM6DS3TR_C_SENS_SYNC_SPI_ERROR_CODE 0x61U +typedef struct +{ + uint8_t error_code : 8; +} lsm6ds3tr_c_sens_sync_spi_error_code_t; + +#define LSM6DS3TR_C_OUT_MAG_RAW_X_L 0x66U +#define LSM6DS3TR_C_OUT_MAG_RAW_X_H 0x67U +#define LSM6DS3TR_C_OUT_MAG_RAW_Y_L 0x68U +#define LSM6DS3TR_C_OUT_MAG_RAW_Y_H 0x69U +#define LSM6DS3TR_C_OUT_MAG_RAW_Z_L 0x6AU +#define LSM6DS3TR_C_OUT_MAG_RAW_Z_H 0x6BU +#define LSM6DS3TR_C_X_OFS_USR 0x73U +#define LSM6DS3TR_C_Y_OFS_USR 0x74U +#define LSM6DS3TR_C_Z_OFS_USR 0x75U +#define LSM6DS3TR_C_SLV0_ADD 0x02U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t rw_0 : 1; + uint8_t slave0_add : 7; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t slave0_add : 7; + uint8_t rw_0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_slv0_add_t; + +#define LSM6DS3TR_C_SLV0_SUBADD 0x03U +typedef struct +{ + uint8_t slave0_reg : 8; +} lsm6ds3tr_c_slv0_subadd_t; + +#define LSM6DS3TR_C_SLAVE0_CONFIG 0x04U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t slave0_numop : 3; + uint8_t src_mode : 1; + uint8_t aux_sens_on : 2; + uint8_t slave0_rate : 2; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t slave0_rate : 2; + uint8_t aux_sens_on : 2; + uint8_t src_mode : 1; + uint8_t slave0_numop : 3; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_slave0_config_t; + +#define LSM6DS3TR_C_SLV1_ADD 0x05U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t r_1 : 1; + uint8_t slave1_add : 7; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t slave1_add : 7; + uint8_t r_1 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_slv1_add_t; + +#define LSM6DS3TR_C_SLV1_SUBADD 0x06U +typedef struct +{ + uint8_t slave1_reg : 8; +} lsm6ds3tr_c_slv1_subadd_t; + +#define LSM6DS3TR_C_SLAVE1_CONFIG 0x07U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t slave1_numop : 3; + uint8_t not_used_01 : 2; + uint8_t write_once : 1; + uint8_t slave1_rate : 2; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t slave1_rate : 2; + uint8_t write_once : 1; + uint8_t not_used_01 : 2; + uint8_t slave1_numop : 3; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_slave1_config_t; + +#define LSM6DS3TR_C_SLV2_ADD 0x08U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t r_2 : 1; + uint8_t slave2_add : 7; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t slave2_add : 7; + uint8_t r_2 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_slv2_add_t; + +#define LSM6DS3TR_C_SLV2_SUBADD 0x09U +typedef struct +{ + uint8_t slave2_reg : 8; +} lsm6ds3tr_c_slv2_subadd_t; + +#define LSM6DS3TR_C_SLAVE2_CONFIG 0x0AU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t slave2_numop : 3; + uint8_t not_used_01 : 3; + uint8_t slave2_rate : 2; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t slave2_rate : 2; + uint8_t not_used_01 : 3; + uint8_t slave2_numop : 3; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_slave2_config_t; + +#define LSM6DS3TR_C_SLV3_ADD 0x0BU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t r_3 : 1; + uint8_t slave3_add : 7; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t slave3_add : 7; + uint8_t r_3 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_slv3_add_t; + +#define LSM6DS3TR_C_SLV3_SUBADD 0x0CU +typedef struct +{ + uint8_t slave3_reg : 8; +} lsm6ds3tr_c_slv3_subadd_t; + +#define LSM6DS3TR_C_SLAVE3_CONFIG 0x0DU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t slave3_numop : 3; + uint8_t not_used_01 : 3; + uint8_t slave3_rate : 2; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t slave3_rate : 2; + uint8_t not_used_01 : 3; + uint8_t slave3_numop : 3; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_slave3_config_t; + +#define LSM6DS3TR_C_DATAWRITE_SRC_MODE_SUB_SLV0 0x0EU +typedef struct +{ + uint8_t slave_dataw : 8; +} lsm6ds3tr_c_datawrite_src_mode_sub_slv0_t; + +#define LSM6DS3TR_C_CONFIG_PEDO_THS_MIN 0x0FU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t ths_min : 5; + uint8_t not_used_01 : 2; + uint8_t pedo_fs : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t pedo_fs : 1; + uint8_t not_used_01 : 2; + uint8_t ths_min : 5; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_config_pedo_ths_min_t; + +#define LSM6DS3TR_C_SM_THS 0x13U +#define LSM6DS3TR_C_PEDO_DEB_REG 0x14U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t deb_step : 3; + uint8_t deb_time : 5; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t deb_time : 5; + uint8_t deb_step : 3; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_pedo_deb_reg_t; + +#define LSM6DS3TR_C_STEP_COUNT_DELTA 0x15U +#define LSM6DS3TR_C_MAG_SI_XX 0x24U +#define LSM6DS3TR_C_MAG_SI_XY 0x25U +#define LSM6DS3TR_C_MAG_SI_XZ 0x26U +#define LSM6DS3TR_C_MAG_SI_YX 0x27U +#define LSM6DS3TR_C_MAG_SI_YY 0x28U +#define LSM6DS3TR_C_MAG_SI_YZ 0x29U +#define LSM6DS3TR_C_MAG_SI_ZX 0x2AU +#define LSM6DS3TR_C_MAG_SI_ZY 0x2BU +#define LSM6DS3TR_C_MAG_SI_ZZ 0x2CU +#define LSM6DS3TR_C_MAG_OFFX_L 0x2DU +#define LSM6DS3TR_C_MAG_OFFX_H 0x2EU +#define LSM6DS3TR_C_MAG_OFFY_L 0x2FU +#define LSM6DS3TR_C_MAG_OFFY_H 0x30U +#define LSM6DS3TR_C_MAG_OFFZ_L 0x31U +#define LSM6DS3TR_C_MAG_OFFZ_H 0x32U +#define LSM6DS3TR_C_A_WRIST_TILT_LAT 0x50U +#define LSM6DS3TR_C_A_WRIST_TILT_THS 0x54U +#define LSM6DS3TR_C_A_WRIST_TILT_MASK 0x59U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t not_used_01 : 2; + uint8_t wrist_tilt_mask_zneg : 1; + uint8_t wrist_tilt_mask_zpos : 1; + uint8_t wrist_tilt_mask_yneg : 1; + uint8_t wrist_tilt_mask_ypos : 1; + uint8_t wrist_tilt_mask_xneg : 1; + uint8_t wrist_tilt_mask_xpos : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t wrist_tilt_mask_xpos : 1; + uint8_t wrist_tilt_mask_xneg : 1; + uint8_t wrist_tilt_mask_ypos : 1; + uint8_t wrist_tilt_mask_yneg : 1; + uint8_t wrist_tilt_mask_zpos : 1; + uint8_t wrist_tilt_mask_zneg : 1; + uint8_t not_used_01 : 2; +#endif /* DRV_BYTE_ORDER */ +} lsm6ds3tr_c_a_wrist_tilt_mask_t; + +/** + * @defgroup LSM6DS3TR_C_Register_Union + * @brief This union group all the registers having a bit-field + * description. + * This union is useful but it's not needed by the driver. + * + * REMOVING this union you are compliant with: + * MISRA-C 2012 [Rule 19.2] -> " Union are not allowed " + * + * @{ + * + */ +typedef union +{ + lsm6ds3tr_c_func_cfg_access_t func_cfg_access; + lsm6ds3tr_c_sensor_sync_time_frame_t sensor_sync_time_frame; + lsm6ds3tr_c_sensor_sync_res_ratio_t sensor_sync_res_ratio; + lsm6ds3tr_c_fifo_ctrl1_t fifo_ctrl1; + lsm6ds3tr_c_fifo_ctrl2_t fifo_ctrl2; + lsm6ds3tr_c_fifo_ctrl3_t fifo_ctrl3; + lsm6ds3tr_c_fifo_ctrl4_t fifo_ctrl4; + lsm6ds3tr_c_fifo_ctrl5_t fifo_ctrl5; + lsm6ds3tr_c_drdy_pulse_cfg_g_t drdy_pulse_cfg_g; + lsm6ds3tr_c_int1_ctrl_t int1_ctrl; + lsm6ds3tr_c_int2_ctrl_t int2_ctrl; + lsm6ds3tr_c_ctrl1_xl_t ctrl1_xl; + lsm6ds3tr_c_ctrl2_g_t ctrl2_g; + lsm6ds3tr_c_ctrl3_c_t ctrl3_c; + lsm6ds3tr_c_ctrl4_c_t ctrl4_c; + lsm6ds3tr_c_ctrl5_c_t ctrl5_c; + lsm6ds3tr_c_ctrl6_c_t ctrl6_c; + lsm6ds3tr_c_ctrl7_g_t ctrl7_g; + lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl; + lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl; + lsm6ds3tr_c_ctrl10_c_t ctrl10_c; + lsm6ds3tr_c_master_config_t master_config; + lsm6ds3tr_c_wake_up_src_t wake_up_src; + lsm6ds3tr_c_tap_src_t tap_src; + lsm6ds3tr_c_d6d_src_t d6d_src; + lsm6ds3tr_c_status_reg_t status_reg; + lsm6ds3tr_c_sensorhub1_reg_t sensorhub1_reg; + lsm6ds3tr_c_sensorhub2_reg_t sensorhub2_reg; + lsm6ds3tr_c_sensorhub3_reg_t sensorhub3_reg; + lsm6ds3tr_c_sensorhub4_reg_t sensorhub4_reg; + lsm6ds3tr_c_sensorhub5_reg_t sensorhub5_reg; + lsm6ds3tr_c_sensorhub6_reg_t sensorhub6_reg; + lsm6ds3tr_c_sensorhub7_reg_t sensorhub7_reg; + lsm6ds3tr_c_sensorhub8_reg_t sensorhub8_reg; + lsm6ds3tr_c_sensorhub9_reg_t sensorhub9_reg; + lsm6ds3tr_c_sensorhub10_reg_t sensorhub10_reg; + lsm6ds3tr_c_sensorhub11_reg_t sensorhub11_reg; + lsm6ds3tr_c_sensorhub12_reg_t sensorhub12_reg; + lsm6ds3tr_c_fifo_status1_t fifo_status1; + lsm6ds3tr_c_fifo_status2_t fifo_status2; + lsm6ds3tr_c_fifo_status3_t fifo_status3; + lsm6ds3tr_c_fifo_status4_t fifo_status4; + lsm6ds3tr_c_sensorhub13_reg_t sensorhub13_reg; + lsm6ds3tr_c_sensorhub14_reg_t sensorhub14_reg; + lsm6ds3tr_c_sensorhub15_reg_t sensorhub15_reg; + lsm6ds3tr_c_sensorhub16_reg_t sensorhub16_reg; + lsm6ds3tr_c_sensorhub17_reg_t sensorhub17_reg; + lsm6ds3tr_c_sensorhub18_reg_t sensorhub18_reg; + lsm6ds3tr_c_func_src1_t func_src1; + lsm6ds3tr_c_func_src2_t func_src2; + lsm6ds3tr_c_wrist_tilt_ia_t wrist_tilt_ia; + lsm6ds3tr_c_tap_cfg_t tap_cfg; + lsm6ds3tr_c_tap_ths_6d_t tap_ths_6d; + lsm6ds3tr_c_int_dur2_t int_dur2; + lsm6ds3tr_c_wake_up_ths_t wake_up_ths; + lsm6ds3tr_c_wake_up_dur_t wake_up_dur; + lsm6ds3tr_c_free_fall_t free_fall; + lsm6ds3tr_c_md1_cfg_t md1_cfg; + lsm6ds3tr_c_md2_cfg_t md2_cfg; + lsm6ds3tr_c_master_cmd_code_t master_cmd_code; + lsm6ds3tr_c_sens_sync_spi_error_code_t + sens_sync_spi_error_code; + lsm6ds3tr_c_slv0_add_t slv0_add; + lsm6ds3tr_c_slv0_subadd_t slv0_subadd; + lsm6ds3tr_c_slave0_config_t slave0_config; + lsm6ds3tr_c_slv1_add_t slv1_add; + lsm6ds3tr_c_slv1_subadd_t slv1_subadd; + lsm6ds3tr_c_slave1_config_t slave1_config; + lsm6ds3tr_c_slv2_add_t slv2_add; + lsm6ds3tr_c_slv2_subadd_t slv2_subadd; + lsm6ds3tr_c_slave2_config_t slave2_config; + lsm6ds3tr_c_slv3_add_t slv3_add; + lsm6ds3tr_c_slv3_subadd_t slv3_subadd; + lsm6ds3tr_c_slave3_config_t slave3_config; + lsm6ds3tr_c_datawrite_src_mode_sub_slv0_t + datawrite_src_mode_sub_slv0; + lsm6ds3tr_c_config_pedo_ths_min_t config_pedo_ths_min; + lsm6ds3tr_c_pedo_deb_reg_t pedo_deb_reg; + lsm6ds3tr_c_a_wrist_tilt_mask_t a_wrist_tilt_mask; + bitwise_t bitwise; + uint8_t byte; +} lsm6ds3tr_c_reg_t; + +/** + * @} + * + */ + +#ifndef __weak +#define __weak __attribute__((weak)) +#endif /* __weak */ + +/* + * These are the basic platform dependent I/O routines to read + * and write device registers connected on a standard bus. + * The driver keeps offering a default implementation based on function + * pointers to read/write routines for backward compatibility. + * The __weak directive allows the final application to overwrite + * them with a custom implementation. + */ + +int32_t lsm6ds3tr_c_read_reg(const stmdev_ctx_t *ctx, uint8_t reg, + uint8_t *data, + uint16_t len); +int32_t lsm6ds3tr_c_write_reg(const stmdev_ctx_t *ctx, uint8_t reg, + uint8_t *data, + uint16_t len); + +float_t lsm6ds3tr_c_from_fs2g_to_mg(int16_t lsb); +float_t lsm6ds3tr_c_from_fs4g_to_mg(int16_t lsb); +float_t lsm6ds3tr_c_from_fs8g_to_mg(int16_t lsb); +float_t lsm6ds3tr_c_from_fs16g_to_mg(int16_t lsb); + +float_t lsm6ds3tr_c_from_fs125dps_to_mdps(int16_t lsb); +float_t lsm6ds3tr_c_from_fs250dps_to_mdps(int16_t lsb); +float_t lsm6ds3tr_c_from_fs500dps_to_mdps(int16_t lsb); +float_t lsm6ds3tr_c_from_fs1000dps_to_mdps(int16_t lsb); +float_t lsm6ds3tr_c_from_fs2000dps_to_mdps(int16_t lsb); + +float_t lsm6ds3tr_c_from_lsb_to_celsius(int16_t lsb); + +typedef enum +{ + LSM6DS3TR_C_2g = 0, + LSM6DS3TR_C_16g = 1, + LSM6DS3TR_C_4g = 2, + LSM6DS3TR_C_8g = 3, + LSM6DS3TR_C_XL_FS_ND = 4, /* ERROR CODE */ +} lsm6ds3tr_c_fs_xl_t; +int32_t lsm6ds3tr_c_xl_full_scale_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_fs_xl_t val); +int32_t lsm6ds3tr_c_xl_full_scale_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_fs_xl_t *val); + +typedef enum +{ + LSM6DS3TR_C_XL_ODR_OFF = 0, + LSM6DS3TR_C_XL_ODR_12Hz5 = 1, + LSM6DS3TR_C_XL_ODR_26Hz = 2, + LSM6DS3TR_C_XL_ODR_52Hz = 3, + LSM6DS3TR_C_XL_ODR_104Hz = 4, + LSM6DS3TR_C_XL_ODR_208Hz = 5, + LSM6DS3TR_C_XL_ODR_416Hz = 6, + LSM6DS3TR_C_XL_ODR_833Hz = 7, + LSM6DS3TR_C_XL_ODR_1k66Hz = 8, + LSM6DS3TR_C_XL_ODR_3k33Hz = 9, + LSM6DS3TR_C_XL_ODR_6k66Hz = 10, + LSM6DS3TR_C_XL_ODR_1Hz6 = 11, + LSM6DS3TR_C_XL_ODR_ND = 12, /* ERROR CODE */ +} lsm6ds3tr_c_odr_xl_t; +int32_t lsm6ds3tr_c_xl_data_rate_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_odr_xl_t val); +int32_t lsm6ds3tr_c_xl_data_rate_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_odr_xl_t *val); + +typedef enum +{ + LSM6DS3TR_C_250dps = 0, + LSM6DS3TR_C_125dps = 1, + LSM6DS3TR_C_500dps = 2, + LSM6DS3TR_C_1000dps = 4, + LSM6DS3TR_C_2000dps = 6, + LSM6DS3TR_C_GY_FS_ND = 7, /* ERROR CODE */ +} lsm6ds3tr_c_fs_g_t; +int32_t lsm6ds3tr_c_gy_full_scale_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_fs_g_t val); +int32_t lsm6ds3tr_c_gy_full_scale_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_fs_g_t *val); + +typedef enum +{ + LSM6DS3TR_C_GY_ODR_OFF = 0, + LSM6DS3TR_C_GY_ODR_12Hz5 = 1, + LSM6DS3TR_C_GY_ODR_26Hz = 2, + LSM6DS3TR_C_GY_ODR_52Hz = 3, + LSM6DS3TR_C_GY_ODR_104Hz = 4, + LSM6DS3TR_C_GY_ODR_208Hz = 5, + LSM6DS3TR_C_GY_ODR_416Hz = 6, + LSM6DS3TR_C_GY_ODR_833Hz = 7, + LSM6DS3TR_C_GY_ODR_1k66Hz = 8, + LSM6DS3TR_C_GY_ODR_3k33Hz = 9, + LSM6DS3TR_C_GY_ODR_6k66Hz = 10, + LSM6DS3TR_C_GY_ODR_ND = 11, /* ERROR CODE */ +} lsm6ds3tr_c_odr_g_t; +int32_t lsm6ds3tr_c_gy_data_rate_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_odr_g_t val); +int32_t lsm6ds3tr_c_gy_data_rate_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_odr_g_t *val); + +int32_t lsm6ds3tr_c_block_data_update_set(const stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6ds3tr_c_block_data_update_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +typedef enum +{ + LSM6DS3TR_C_LSb_1mg = 0, + LSM6DS3TR_C_LSb_16mg = 1, + LSM6DS3TR_C_WEIGHT_ND = 2, +} lsm6ds3tr_c_usr_off_w_t; +int32_t lsm6ds3tr_c_xl_offset_weight_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_usr_off_w_t val); +int32_t lsm6ds3tr_c_xl_offset_weight_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_usr_off_w_t *val); + +typedef enum +{ + LSM6DS3TR_C_XL_HIGH_PERFORMANCE = 0, + LSM6DS3TR_C_XL_NORMAL = 1, + LSM6DS3TR_C_XL_PW_MODE_ND = 2, /* ERROR CODE */ +} lsm6ds3tr_c_xl_hm_mode_t; +int32_t lsm6ds3tr_c_xl_power_mode_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_xl_hm_mode_t val); +int32_t lsm6ds3tr_c_xl_power_mode_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_xl_hm_mode_t *val); + +typedef enum +{ + LSM6DS3TR_C_STAT_RND_DISABLE = 0, + LSM6DS3TR_C_STAT_RND_ENABLE = 1, + LSM6DS3TR_C_STAT_RND_ND = 2, /* ERROR CODE */ +} lsm6ds3tr_c_rounding_status_t; +int32_t lsm6ds3tr_c_rounding_on_status_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_rounding_status_t val); +int32_t lsm6ds3tr_c_rounding_on_status_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_rounding_status_t *val); + +typedef enum +{ + LSM6DS3TR_C_GY_HIGH_PERFORMANCE = 0, + LSM6DS3TR_C_GY_NORMAL = 1, + LSM6DS3TR_C_GY_PW_MODE_ND = 2, /* ERROR CODE */ +} lsm6ds3tr_c_g_hm_mode_t; +int32_t lsm6ds3tr_c_gy_power_mode_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_g_hm_mode_t val); +int32_t lsm6ds3tr_c_gy_power_mode_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_g_hm_mode_t *val); + +typedef struct +{ + lsm6ds3tr_c_wake_up_src_t wake_up_src; + lsm6ds3tr_c_tap_src_t tap_src; + lsm6ds3tr_c_d6d_src_t d6d_src; + lsm6ds3tr_c_status_reg_t status_reg; + lsm6ds3tr_c_func_src1_t func_src1; + lsm6ds3tr_c_func_src2_t func_src2; + lsm6ds3tr_c_wrist_tilt_ia_t wrist_tilt_ia; + lsm6ds3tr_c_a_wrist_tilt_mask_t a_wrist_tilt_mask; +} lsm6ds3tr_c_all_sources_t; +int32_t lsm6ds3tr_c_all_sources_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_all_sources_t *val); + +int32_t lsm6ds3tr_c_status_reg_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_status_reg_t *val); + +int32_t lsm6ds3tr_c_xl_flag_data_ready_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6ds3tr_c_gy_flag_data_ready_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6ds3tr_c_temp_flag_data_ready_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6ds3tr_c_xl_usr_offset_set(const stmdev_ctx_t *ctx, + uint8_t *buff); +int32_t lsm6ds3tr_c_xl_usr_offset_get(const stmdev_ctx_t *ctx, + uint8_t *buff); +int32_t lsm6ds3tr_c_timestamp_set(const stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6ds3tr_c_timestamp_get(const stmdev_ctx_t *ctx, uint8_t *val); + +typedef enum +{ + LSM6DS3TR_C_LSB_6ms4 = 0, + LSM6DS3TR_C_LSB_25us = 1, + LSM6DS3TR_C_TS_RES_ND = 2, /* ERROR CODE */ +} lsm6ds3tr_c_timer_hr_t; +int32_t lsm6ds3tr_c_timestamp_res_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_timer_hr_t val); +int32_t lsm6ds3tr_c_timestamp_res_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_timer_hr_t *val); + +typedef enum +{ + LSM6DS3TR_C_ROUND_DISABLE = 0, + LSM6DS3TR_C_ROUND_XL = 1, + LSM6DS3TR_C_ROUND_GY = 2, + LSM6DS3TR_C_ROUND_GY_XL = 3, + LSM6DS3TR_C_ROUND_SH1_TO_SH6 = 4, + LSM6DS3TR_C_ROUND_XL_SH1_TO_SH6 = 5, + LSM6DS3TR_C_ROUND_GY_XL_SH1_TO_SH12 = 6, + LSM6DS3TR_C_ROUND_GY_XL_SH1_TO_SH6 = 7, + LSM6DS3TR_C_ROUND_OUT_ND = 8, /* ERROR CODE */ +} lsm6ds3tr_c_rounding_t; +int32_t lsm6ds3tr_c_rounding_mode_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_rounding_t val); +int32_t lsm6ds3tr_c_rounding_mode_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_rounding_t *val); + +int32_t lsm6ds3tr_c_temperature_raw_get(const stmdev_ctx_t *ctx, + int16_t *val); +int32_t lsm6ds3tr_c_angular_rate_raw_get(const stmdev_ctx_t *ctx, + int16_t *val); +int32_t lsm6ds3tr_c_acceleration_raw_get(const stmdev_ctx_t *ctx, + int16_t *val); + +int32_t lsm6ds3tr_c_mag_calibrated_raw_get(const stmdev_ctx_t *ctx, + int16_t *val); + +int32_t lsm6ds3tr_c_fifo_raw_data_get(const stmdev_ctx_t *ctx, + uint8_t *buffer, + uint8_t len); + +typedef enum +{ + LSM6DS3TR_C_USER_BANK = 0, + LSM6DS3TR_C_BANK_A = 4, + LSM6DS3TR_C_BANK_B = 5, + LSM6DS3TR_C_BANK_ND = 6, /* ERROR CODE */ +} lsm6ds3tr_c_func_cfg_en_t; +int32_t lsm6ds3tr_c_mem_bank_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_func_cfg_en_t val); +int32_t lsm6ds3tr_c_mem_bank_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_func_cfg_en_t *val); + +typedef enum +{ + LSM6DS3TR_C_DRDY_LATCHED = 0, + LSM6DS3TR_C_DRDY_PULSED = 1, + LSM6DS3TR_C_DRDY_ND = 2, /* ERROR CODE */ +} lsm6ds3tr_c_drdy_pulsed_g_t; +int32_t lsm6ds3tr_c_data_ready_mode_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_drdy_pulsed_g_t val); +int32_t lsm6ds3tr_c_data_ready_mode_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_drdy_pulsed_g_t *val); + +int32_t lsm6ds3tr_c_device_id_get(const stmdev_ctx_t *ctx, uint8_t *buff); +int32_t lsm6ds3tr_c_reset_set(const stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6ds3tr_c_reset_get(const stmdev_ctx_t *ctx, uint8_t *val); + +typedef enum +{ + LSM6DS3TR_C_LSB_AT_LOW_ADD = 0, + LSM6DS3TR_C_MSB_AT_LOW_ADD = 1, + LSM6DS3TR_C_DATA_FMT_ND = 2, /* ERROR CODE */ +} lsm6ds3tr_c_ble_t; +int32_t lsm6ds3tr_c_data_format_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_ble_t val); +int32_t lsm6ds3tr_c_data_format_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_ble_t *val); + +int32_t lsm6ds3tr_c_auto_increment_set(const stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6ds3tr_c_auto_increment_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6ds3tr_c_boot_set(const stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6ds3tr_c_boot_get(const stmdev_ctx_t *ctx, uint8_t *val); + +typedef enum +{ + LSM6DS3TR_C_XL_ST_DISABLE = 0, + LSM6DS3TR_C_XL_ST_POSITIVE = 1, + LSM6DS3TR_C_XL_ST_NEGATIVE = 2, + LSM6DS3TR_C_XL_ST_ND = 3, /* ERROR CODE */ +} lsm6ds3tr_c_st_xl_t; +int32_t lsm6ds3tr_c_xl_self_test_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_st_xl_t val); +int32_t lsm6ds3tr_c_xl_self_test_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_st_xl_t *val); + +typedef enum +{ + LSM6DS3TR_C_GY_ST_DISABLE = 0, + LSM6DS3TR_C_GY_ST_POSITIVE = 1, + LSM6DS3TR_C_GY_ST_NEGATIVE = 3, + LSM6DS3TR_C_GY_ST_ND = 4, /* ERROR CODE */ +} lsm6ds3tr_c_st_g_t; +int32_t lsm6ds3tr_c_gy_self_test_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_st_g_t val); +int32_t lsm6ds3tr_c_gy_self_test_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_st_g_t *val); + +int32_t lsm6ds3tr_c_filter_settling_mask_set(const stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6ds3tr_c_filter_settling_mask_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +typedef enum +{ + LSM6DS3TR_C_USE_SLOPE = 0, + LSM6DS3TR_C_USE_HPF = 1, + LSM6DS3TR_C_HP_PATH_ND = 2, /* ERROR CODE */ +} lsm6ds3tr_c_slope_fds_t; +int32_t lsm6ds3tr_c_xl_hp_path_internal_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_slope_fds_t val); +int32_t lsm6ds3tr_c_xl_hp_path_internal_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_slope_fds_t *val); + +typedef enum +{ + LSM6DS3TR_C_XL_ANA_BW_1k5Hz = 0, + LSM6DS3TR_C_XL_ANA_BW_400Hz = 1, + LSM6DS3TR_C_XL_ANA_BW_ND = 2, /* ERROR CODE */ +} lsm6ds3tr_c_bw0_xl_t; +int32_t lsm6ds3tr_c_xl_filter_analog_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_bw0_xl_t val); +int32_t lsm6ds3tr_c_xl_filter_analog_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_bw0_xl_t *val); + +typedef enum +{ + LSM6DS3TR_C_XL_LP1_ODR_DIV_2 = 0, + LSM6DS3TR_C_XL_LP1_ODR_DIV_4 = 1, + LSM6DS3TR_C_XL_LP1_NA = 2, /* ERROR CODE */ +} lsm6ds3tr_c_lpf1_bw_sel_t; +int32_t lsm6ds3tr_c_xl_lp1_bandwidth_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_lpf1_bw_sel_t val); +int32_t lsm6ds3tr_c_xl_lp1_bandwidth_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_lpf1_bw_sel_t *val); + +typedef enum +{ + LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_50 = 0x00, + LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_100 = 0x01, + LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_9 = 0x02, + LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_400 = 0x03, + LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_50 = 0x10, + LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_100 = 0x11, + LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_9 = 0x12, + LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_400 = 0x13, + LSM6DS3TR_C_XL_LP_NA = 0x20, /* ERROR CODE */ +} lsm6ds3tr_c_input_composite_t; +int32_t lsm6ds3tr_c_xl_lp2_bandwidth_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_input_composite_t val); +int32_t lsm6ds3tr_c_xl_lp2_bandwidth_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_input_composite_t *val); + +int32_t lsm6ds3tr_c_xl_reference_mode_set(const stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6ds3tr_c_xl_reference_mode_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +typedef enum +{ + LSM6DS3TR_C_XL_HP_ODR_DIV_4 = 0x00, /* Slope filter */ + LSM6DS3TR_C_XL_HP_ODR_DIV_100 = 0x01, + LSM6DS3TR_C_XL_HP_ODR_DIV_9 = 0x02, + LSM6DS3TR_C_XL_HP_ODR_DIV_400 = 0x03, + LSM6DS3TR_C_XL_HP_NA = 0x10, /* ERROR CODE */ +} lsm6ds3tr_c_hpcf_xl_t; +int32_t lsm6ds3tr_c_xl_hp_bandwidth_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_hpcf_xl_t val); +int32_t lsm6ds3tr_c_xl_hp_bandwidth_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_hpcf_xl_t *val); + +typedef enum +{ + LSM6DS3TR_C_LP2_ONLY = 0x00, + + LSM6DS3TR_C_HP_16mHz_LP2 = 0x80, + LSM6DS3TR_C_HP_65mHz_LP2 = 0x90, + LSM6DS3TR_C_HP_260mHz_LP2 = 0xA0, + LSM6DS3TR_C_HP_1Hz04_LP2 = 0xB0, + + LSM6DS3TR_C_HP_DISABLE_LP1_LIGHT = 0x0A, + LSM6DS3TR_C_HP_DISABLE_LP1_NORMAL = 0x09, + LSM6DS3TR_C_HP_DISABLE_LP_STRONG = 0x08, + LSM6DS3TR_C_HP_DISABLE_LP1_AGGRESSIVE = 0x0B, + + LSM6DS3TR_C_HP_16mHz_LP1_LIGHT = 0x8A, + LSM6DS3TR_C_HP_65mHz_LP1_NORMAL = 0x99, + LSM6DS3TR_C_HP_260mHz_LP1_STRONG = 0xA8, + LSM6DS3TR_C_HP_1Hz04_LP1_AGGRESSIVE = 0xBB, + + LSM6DS3TR_C_HP_GY_BAND_NA = 0xFF, /* ERROR CODE */ +} lsm6ds3tr_c_lpf1_sel_g_t; +int32_t lsm6ds3tr_c_gy_band_pass_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_lpf1_sel_g_t val); +int32_t lsm6ds3tr_c_gy_band_pass_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_lpf1_sel_g_t *val); + +typedef enum +{ + LSM6DS3TR_C_SPI_4_WIRE = 0, + LSM6DS3TR_C_SPI_3_WIRE = 1, + LSM6DS3TR_C_SPI_MODE_ND = 2, /* ERROR CODE */ +} lsm6ds3tr_c_sim_t; +int32_t lsm6ds3tr_c_spi_mode_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_sim_t val); +int32_t lsm6ds3tr_c_spi_mode_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_sim_t *val); + +typedef enum +{ + LSM6DS3TR_C_I2C_ENABLE = 0, + LSM6DS3TR_C_I2C_DISABLE = 1, + LSM6DS3TR_C_I2C_MODE_ND = 2, /* ERROR CODE */ +} lsm6ds3tr_c_i2c_disable_t; +int32_t lsm6ds3tr_c_i2c_interface_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_i2c_disable_t val); +int32_t lsm6ds3tr_c_i2c_interface_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_i2c_disable_t *val); + +typedef struct +{ + uint8_t int1_drdy_xl : 1; + uint8_t int1_drdy_g : 1; + uint8_t int1_boot : 1; + uint8_t int1_fth : 1; + uint8_t int1_fifo_ovr : 1; + uint8_t int1_full_flag : 1; + uint8_t int1_sign_mot : 1; + uint8_t int1_step_detector : 1; + uint8_t int1_timer : 1; + uint8_t int1_tilt : 1; + uint8_t int1_6d : 1; + uint8_t int1_double_tap : 1; + uint8_t int1_ff : 1; + uint8_t int1_wu : 1; + uint8_t int1_single_tap : 1; + uint8_t int1_inact_state : 1; + uint8_t den_drdy_int1 : 1; + uint8_t drdy_on_int1 : 1; +} lsm6ds3tr_c_int1_route_t; +int32_t lsm6ds3tr_c_pin_int1_route_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_int1_route_t val); +int32_t lsm6ds3tr_c_pin_int1_route_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_int1_route_t *val); + +typedef struct +{ + uint8_t int2_drdy_xl : 1; + uint8_t int2_drdy_g : 1; + uint8_t int2_drdy_temp : 1; + uint8_t int2_fth : 1; + uint8_t int2_fifo_ovr : 1; + uint8_t int2_full_flag : 1; + uint8_t int2_step_count_ov : 1; + uint8_t int2_step_delta : 1; + uint8_t int2_iron : 1; + uint8_t int2_tilt : 1; + uint8_t int2_6d : 1; + uint8_t int2_double_tap : 1; + uint8_t int2_ff : 1; + uint8_t int2_wu : 1; + uint8_t int2_single_tap : 1; + uint8_t int2_inact_state : 1; + uint8_t int2_wrist_tilt : 1; +} lsm6ds3tr_c_int2_route_t; +int32_t lsm6ds3tr_c_pin_int2_route_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_int2_route_t val); +int32_t lsm6ds3tr_c_pin_int2_route_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_int2_route_t *val); + +typedef enum +{ + LSM6DS3TR_C_PUSH_PULL = 0, + LSM6DS3TR_C_OPEN_DRAIN = 1, + LSM6DS3TR_C_PIN_MODE_ND = 2, /* ERROR CODE */ +} lsm6ds3tr_c_pp_od_t; +int32_t lsm6ds3tr_c_pin_mode_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_pp_od_t val); +int32_t lsm6ds3tr_c_pin_mode_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_pp_od_t *val); + +typedef enum +{ + LSM6DS3TR_C_ACTIVE_HIGH = 0, + LSM6DS3TR_C_ACTIVE_LOW = 1, + LSM6DS3TR_C_POLARITY_ND = 2, /* ERROR CODE */ +} lsm6ds3tr_c_h_lactive_t; +int32_t lsm6ds3tr_c_pin_polarity_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_h_lactive_t val); +int32_t lsm6ds3tr_c_pin_polarity_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_h_lactive_t *val); + +int32_t lsm6ds3tr_c_all_on_int1_set(const stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6ds3tr_c_all_on_int1_get(const stmdev_ctx_t *ctx, uint8_t *val); + +typedef enum +{ + LSM6DS3TR_C_INT_PULSED = 0, + LSM6DS3TR_C_INT_LATCHED = 1, + LSM6DS3TR_C_INT_MODE = 2, /* ERROR CODE */ +} lsm6ds3tr_c_lir_t; +int32_t lsm6ds3tr_c_int_notification_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_lir_t val); +int32_t lsm6ds3tr_c_int_notification_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_lir_t *val); + +int32_t lsm6ds3tr_c_wkup_threshold_set(const stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6ds3tr_c_wkup_threshold_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6ds3tr_c_wkup_dur_set(const stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6ds3tr_c_wkup_dur_get(const stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6ds3tr_c_gy_sleep_mode_set(const stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6ds3tr_c_gy_sleep_mode_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +typedef enum +{ + LSM6DS3TR_C_PROPERTY_DISABLE = 0, + LSM6DS3TR_C_XL_12Hz5_GY_NOT_AFFECTED = 1, + LSM6DS3TR_C_XL_12Hz5_GY_SLEEP = 2, + LSM6DS3TR_C_XL_12Hz5_GY_PD = 3, + LSM6DS3TR_C_ACT_MODE_ND = 4, /* ERROR CODE */ +} lsm6ds3tr_c_inact_en_t; +int32_t lsm6ds3tr_c_act_mode_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_inact_en_t val); +int32_t lsm6ds3tr_c_act_mode_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_inact_en_t *val); + +int32_t lsm6ds3tr_c_act_sleep_dur_set(const stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6ds3tr_c_act_sleep_dur_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6ds3tr_c_tap_src_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_tap_src_t *val); + +int32_t lsm6ds3tr_c_tap_detection_on_z_set(const stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6ds3tr_c_tap_detection_on_z_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6ds3tr_c_tap_detection_on_y_set(const stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6ds3tr_c_tap_detection_on_y_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6ds3tr_c_tap_detection_on_x_set(const stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6ds3tr_c_tap_detection_on_x_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6ds3tr_c_tap_threshold_x_set(const stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6ds3tr_c_tap_threshold_x_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6ds3tr_c_tap_shock_set(const stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6ds3tr_c_tap_shock_get(const stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6ds3tr_c_tap_quiet_set(const stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6ds3tr_c_tap_quiet_get(const stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6ds3tr_c_tap_dur_set(const stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6ds3tr_c_tap_dur_get(const stmdev_ctx_t *ctx, uint8_t *val); + +typedef enum +{ + LSM6DS3TR_C_ONLY_SINGLE = 0, + LSM6DS3TR_C_BOTH_SINGLE_DOUBLE = 1, + LSM6DS3TR_C_TAP_MODE_ND = 2, /* ERROR CODE */ +} lsm6ds3tr_c_single_double_tap_t; +int32_t lsm6ds3tr_c_tap_mode_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_single_double_tap_t val); +int32_t lsm6ds3tr_c_tap_mode_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_single_double_tap_t *val); + +typedef enum +{ + LSM6DS3TR_C_ODR_DIV_2_FEED = 0, + LSM6DS3TR_C_LPF2_FEED = 1, + LSM6DS3TR_C_6D_FEED_ND = 2, /* ERROR CODE */ +} lsm6ds3tr_c_low_pass_on_6d_t; +int32_t lsm6ds3tr_c_6d_feed_data_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_low_pass_on_6d_t val); +int32_t lsm6ds3tr_c_6d_feed_data_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_low_pass_on_6d_t *val); + +typedef enum +{ + LSM6DS3TR_C_DEG_80 = 0, + LSM6DS3TR_C_DEG_70 = 1, + LSM6DS3TR_C_DEG_60 = 2, + LSM6DS3TR_C_DEG_50 = 3, + LSM6DS3TR_C_6D_TH_ND = 4, /* ERROR CODE */ +} lsm6ds3tr_c_sixd_ths_t; +int32_t lsm6ds3tr_c_6d_threshold_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_sixd_ths_t val); +int32_t lsm6ds3tr_c_6d_threshold_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_sixd_ths_t *val); + +int32_t lsm6ds3tr_c_4d_mode_set(const stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6ds3tr_c_4d_mode_get(const stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6ds3tr_c_ff_dur_set(const stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6ds3tr_c_ff_dur_get(const stmdev_ctx_t *ctx, uint8_t *val); + +typedef enum +{ + LSM6DS3TR_C_FF_TSH_156mg = 0, + LSM6DS3TR_C_FF_TSH_219mg = 1, + LSM6DS3TR_C_FF_TSH_250mg = 2, + LSM6DS3TR_C_FF_TSH_312mg = 3, + LSM6DS3TR_C_FF_TSH_344mg = 4, + LSM6DS3TR_C_FF_TSH_406mg = 5, + LSM6DS3TR_C_FF_TSH_469mg = 6, + LSM6DS3TR_C_FF_TSH_500mg = 7, + LSM6DS3TR_C_FF_TSH_ND = 8, /* ERROR CODE */ +} lsm6ds3tr_c_ff_ths_t; +int32_t lsm6ds3tr_c_ff_threshold_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_ff_ths_t val); +int32_t lsm6ds3tr_c_ff_threshold_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_ff_ths_t *val); + +int32_t lsm6ds3tr_c_fifo_watermark_set(const stmdev_ctx_t *ctx, + uint16_t val); +int32_t lsm6ds3tr_c_fifo_watermark_get(const stmdev_ctx_t *ctx, + uint16_t *val); + +int32_t lsm6ds3tr_c_fifo_data_level_get(const stmdev_ctx_t *ctx, + uint16_t *val); + +int32_t lsm6ds3tr_c_fifo_wtm_flag_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6ds3tr_c_fifo_pattern_get(const stmdev_ctx_t *ctx, + uint16_t *val); + +int32_t lsm6ds3tr_c_fifo_temp_batch_set(const stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6ds3tr_c_fifo_temp_batch_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +typedef enum +{ + LSM6DS3TR_C_TRG_XL_GY_DRDY = 0, + LSM6DS3TR_C_TRG_STEP_DETECT = 1, + LSM6DS3TR_C_TRG_SH_DRDY = 2, + LSM6DS3TR_C_TRG_SH_ND = 3, /* ERROR CODE */ +} lsm6ds3tr_c_trigger_fifo_t; +int32_t lsm6ds3tr_c_fifo_write_trigger_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_trigger_fifo_t val); +int32_t lsm6ds3tr_c_fifo_write_trigger_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_trigger_fifo_t *val); + +int32_t lsm6ds3tr_c_fifo_pedo_and_timestamp_batch_set( + stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6ds3tr_c_fifo_pedo_and_timestamp_batch_get( + stmdev_ctx_t *ctx, + uint8_t *val); + +typedef enum +{ + LSM6DS3TR_C_FIFO_XL_DISABLE = 0, + LSM6DS3TR_C_FIFO_XL_NO_DEC = 1, + LSM6DS3TR_C_FIFO_XL_DEC_2 = 2, + LSM6DS3TR_C_FIFO_XL_DEC_3 = 3, + LSM6DS3TR_C_FIFO_XL_DEC_4 = 4, + LSM6DS3TR_C_FIFO_XL_DEC_8 = 5, + LSM6DS3TR_C_FIFO_XL_DEC_16 = 6, + LSM6DS3TR_C_FIFO_XL_DEC_32 = 7, + LSM6DS3TR_C_FIFO_XL_DEC_ND = 8, /* ERROR CODE */ +} lsm6ds3tr_c_dec_fifo_xl_t; +int32_t lsm6ds3tr_c_fifo_xl_batch_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_dec_fifo_xl_t val); +int32_t lsm6ds3tr_c_fifo_xl_batch_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_dec_fifo_xl_t *val); + +typedef enum +{ + LSM6DS3TR_C_FIFO_GY_DISABLE = 0, + LSM6DS3TR_C_FIFO_GY_NO_DEC = 1, + LSM6DS3TR_C_FIFO_GY_DEC_2 = 2, + LSM6DS3TR_C_FIFO_GY_DEC_3 = 3, + LSM6DS3TR_C_FIFO_GY_DEC_4 = 4, + LSM6DS3TR_C_FIFO_GY_DEC_8 = 5, + LSM6DS3TR_C_FIFO_GY_DEC_16 = 6, + LSM6DS3TR_C_FIFO_GY_DEC_32 = 7, + LSM6DS3TR_C_FIFO_GY_DEC_ND = 8, /* ERROR CODE */ +} lsm6ds3tr_c_dec_fifo_gyro_t; +int32_t lsm6ds3tr_c_fifo_gy_batch_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_dec_fifo_gyro_t val); +int32_t lsm6ds3tr_c_fifo_gy_batch_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_dec_fifo_gyro_t *val); + +typedef enum +{ + LSM6DS3TR_C_FIFO_DS3_DISABLE = 0, + LSM6DS3TR_C_FIFO_DS3_NO_DEC = 1, + LSM6DS3TR_C_FIFO_DS3_DEC_2 = 2, + LSM6DS3TR_C_FIFO_DS3_DEC_3 = 3, + LSM6DS3TR_C_FIFO_DS3_DEC_4 = 4, + LSM6DS3TR_C_FIFO_DS3_DEC_8 = 5, + LSM6DS3TR_C_FIFO_DS3_DEC_16 = 6, + LSM6DS3TR_C_FIFO_DS3_DEC_32 = 7, + LSM6DS3TR_C_FIFO_DS3_DEC_ND = 8, /* ERROR CODE */ +} lsm6ds3tr_c_dec_ds3_fifo_t; +int32_t lsm6ds3tr_c_fifo_dataset_3_batch_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_dec_ds3_fifo_t val); +int32_t lsm6ds3tr_c_fifo_dataset_3_batch_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_dec_ds3_fifo_t *val); + +typedef enum +{ + LSM6DS3TR_C_FIFO_DS4_DISABLE = 0, + LSM6DS3TR_C_FIFO_DS4_NO_DEC = 1, + LSM6DS3TR_C_FIFO_DS4_DEC_2 = 2, + LSM6DS3TR_C_FIFO_DS4_DEC_3 = 3, + LSM6DS3TR_C_FIFO_DS4_DEC_4 = 4, + LSM6DS3TR_C_FIFO_DS4_DEC_8 = 5, + LSM6DS3TR_C_FIFO_DS4_DEC_16 = 6, + LSM6DS3TR_C_FIFO_DS4_DEC_32 = 7, + LSM6DS3TR_C_FIFO_DS4_DEC_ND = 8, /* ERROR CODE */ +} lsm6ds3tr_c_dec_ds4_fifo_t; +int32_t lsm6ds3tr_c_fifo_dataset_4_batch_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_dec_ds4_fifo_t val); +int32_t lsm6ds3tr_c_fifo_dataset_4_batch_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_dec_ds4_fifo_t *val); + +int32_t lsm6ds3tr_c_fifo_xl_gy_8bit_format_set(const stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6ds3tr_c_fifo_xl_gy_8bit_format_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6ds3tr_c_fifo_stop_on_wtm_set(const stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6ds3tr_c_fifo_stop_on_wtm_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +typedef enum +{ + LSM6DS3TR_C_BYPASS_MODE = 0, + LSM6DS3TR_C_FIFO_MODE = 1, + LSM6DS3TR_C_STREAM_TO_FIFO_MODE = 3, + LSM6DS3TR_C_BYPASS_TO_STREAM_MODE = 4, + LSM6DS3TR_C_STREAM_MODE = 6, + LSM6DS3TR_C_FIFO_MODE_ND = 8, /* ERROR CODE */ +} lsm6ds3tr_c_fifo_mode_t; +int32_t lsm6ds3tr_c_fifo_mode_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_fifo_mode_t val); +int32_t lsm6ds3tr_c_fifo_mode_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_fifo_mode_t *val); + +typedef enum +{ + LSM6DS3TR_C_FIFO_DISABLE = 0, + LSM6DS3TR_C_FIFO_12Hz5 = 1, + LSM6DS3TR_C_FIFO_26Hz = 2, + LSM6DS3TR_C_FIFO_52Hz = 3, + LSM6DS3TR_C_FIFO_104Hz = 4, + LSM6DS3TR_C_FIFO_208Hz = 5, + LSM6DS3TR_C_FIFO_416Hz = 6, + LSM6DS3TR_C_FIFO_833Hz = 7, + LSM6DS3TR_C_FIFO_1k66Hz = 8, + LSM6DS3TR_C_FIFO_3k33Hz = 9, + LSM6DS3TR_C_FIFO_6k66Hz = 10, + LSM6DS3TR_C_FIFO_RATE_ND = 11, /* ERROR CODE */ +} lsm6ds3tr_c_odr_fifo_t; +int32_t lsm6ds3tr_c_fifo_data_rate_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_odr_fifo_t val); +int32_t lsm6ds3tr_c_fifo_data_rate_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_odr_fifo_t *val); + +typedef enum +{ + LSM6DS3TR_C_DEN_ACT_LOW = 0, + LSM6DS3TR_C_DEN_ACT_HIGH = 1, + LSM6DS3TR_C_DEN_POL_ND = 2, /* ERROR CODE */ +} lsm6ds3tr_c_den_lh_t; +int32_t lsm6ds3tr_c_den_polarity_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_den_lh_t val); +int32_t lsm6ds3tr_c_den_polarity_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_den_lh_t *val); + +typedef enum +{ + LSM6DS3TR_C_DEN_DISABLE = 0, + LSM6DS3TR_C_LEVEL_FIFO = 6, + LSM6DS3TR_C_LEVEL_LETCHED = 3, + LSM6DS3TR_C_LEVEL_TRIGGER = 2, + LSM6DS3TR_C_EDGE_TRIGGER = 4, + LSM6DS3TR_C_DEN_MODE_ND = 5, /* ERROR CODE */ +} lsm6ds3tr_c_den_mode_t; +int32_t lsm6ds3tr_c_den_mode_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_den_mode_t val); +int32_t lsm6ds3tr_c_den_mode_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_den_mode_t *val); + +typedef enum +{ + LSM6DS3TR_C_STAMP_IN_GY_DATA = 0, + LSM6DS3TR_C_STAMP_IN_XL_DATA = 1, + LSM6DS3TR_C_STAMP_IN_GY_XL_DATA = 2, + LSM6DS3TR_C_DEN_STAMP_ND = 3, /* ERROR CODE */ +} lsm6ds3tr_c_den_xl_en_t; +int32_t lsm6ds3tr_c_den_enable_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_den_xl_en_t val); +int32_t lsm6ds3tr_c_den_enable_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_den_xl_en_t *val); + +int32_t lsm6ds3tr_c_den_mark_axis_z_set(const stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6ds3tr_c_den_mark_axis_z_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6ds3tr_c_den_mark_axis_y_set(const stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6ds3tr_c_den_mark_axis_y_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6ds3tr_c_den_mark_axis_x_set(const stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6ds3tr_c_den_mark_axis_x_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6ds3tr_c_pedo_step_reset_set(const stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6ds3tr_c_pedo_step_reset_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6ds3tr_c_pedo_sens_set(const stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6ds3tr_c_pedo_sens_get(const stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6ds3tr_c_pedo_threshold_set(const stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6ds3tr_c_pedo_threshold_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +typedef enum +{ + LSM6DS3TR_C_PEDO_AT_2g = 0, + LSM6DS3TR_C_PEDO_AT_4g = 1, + LSM6DS3TR_C_PEDO_FS_ND = 2, /* ERROR CODE */ +} lsm6ds3tr_c_pedo_fs_t; +int32_t lsm6ds3tr_c_pedo_full_scale_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_pedo_fs_t val); +int32_t lsm6ds3tr_c_pedo_full_scale_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_pedo_fs_t *val); + +int32_t lsm6ds3tr_c_pedo_debounce_steps_set(const stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6ds3tr_c_pedo_debounce_steps_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6ds3tr_c_pedo_timeout_set(const stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6ds3tr_c_pedo_timeout_get(const stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6ds3tr_c_pedo_steps_period_set(const stmdev_ctx_t *ctx, + uint8_t *buff); +int32_t lsm6ds3tr_c_pedo_steps_period_get(const stmdev_ctx_t *ctx, + uint8_t *buff); + +int32_t lsm6ds3tr_c_motion_sens_set(const stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6ds3tr_c_motion_sens_get(const stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6ds3tr_c_motion_threshold_set(const stmdev_ctx_t *ctx, + uint8_t *buff); +int32_t lsm6ds3tr_c_motion_threshold_get(const stmdev_ctx_t *ctx, + uint8_t *buff); + +int32_t lsm6ds3tr_c_tilt_sens_set(const stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6ds3tr_c_tilt_sens_get(const stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6ds3tr_c_wrist_tilt_sens_set(const stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6ds3tr_c_wrist_tilt_sens_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6ds3tr_c_tilt_latency_set(const stmdev_ctx_t *ctx, + uint8_t *buff); +int32_t lsm6ds3tr_c_tilt_latency_get(const stmdev_ctx_t *ctx, + uint8_t *buff); + +int32_t lsm6ds3tr_c_tilt_threshold_set(const stmdev_ctx_t *ctx, + uint8_t *buff); +int32_t lsm6ds3tr_c_tilt_threshold_get(const stmdev_ctx_t *ctx, + uint8_t *buff); + +int32_t lsm6ds3tr_c_tilt_src_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_a_wrist_tilt_mask_t *val); +int32_t lsm6ds3tr_c_tilt_src_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_a_wrist_tilt_mask_t *val); + +int32_t lsm6ds3tr_c_mag_soft_iron_set(const stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6ds3tr_c_mag_soft_iron_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6ds3tr_c_mag_hard_iron_set(const stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6ds3tr_c_mag_hard_iron_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6ds3tr_c_mag_soft_iron_mat_set(const stmdev_ctx_t *ctx, + uint8_t *buff); +int32_t lsm6ds3tr_c_mag_soft_iron_mat_get(const stmdev_ctx_t *ctx, + uint8_t *buff); + +int32_t lsm6ds3tr_c_mag_offset_set(const stmdev_ctx_t *ctx, int16_t *val); +int32_t lsm6ds3tr_c_mag_offset_get(const stmdev_ctx_t *ctx, int16_t *val); + +int32_t lsm6ds3tr_c_func_en_set(const stmdev_ctx_t *ctx, uint8_t val); + +int32_t lsm6ds3tr_c_sh_sync_sens_frame_set(const stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6ds3tr_c_sh_sync_sens_frame_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +typedef enum +{ + LSM6DS3TR_C_RES_RATIO_2_11 = 0, + LSM6DS3TR_C_RES_RATIO_2_12 = 1, + LSM6DS3TR_C_RES_RATIO_2_13 = 2, + LSM6DS3TR_C_RES_RATIO_2_14 = 3, + LSM6DS3TR_C_RES_RATIO_ND = 4, /* ERROR CODE */ +} lsm6ds3tr_c_rr_t; +int32_t lsm6ds3tr_c_sh_sync_sens_ratio_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_rr_t val); +int32_t lsm6ds3tr_c_sh_sync_sens_ratio_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_rr_t *val); + +int32_t lsm6ds3tr_c_sh_master_set(const stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6ds3tr_c_sh_master_get(const stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6ds3tr_c_sh_pass_through_set(const stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6ds3tr_c_sh_pass_through_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +typedef enum +{ + LSM6DS3TR_C_EXT_PULL_UP = 0, + LSM6DS3TR_C_INTERNAL_PULL_UP = 1, + LSM6DS3TR_C_SH_PIN_MODE = 2, /* ERROR CODE */ +} lsm6ds3tr_c_pull_up_en_t; +int32_t lsm6ds3tr_c_sh_pin_mode_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_pull_up_en_t val); +int32_t lsm6ds3tr_c_sh_pin_mode_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_pull_up_en_t *val); + +typedef enum +{ + LSM6DS3TR_C_XL_GY_DRDY = 0, + LSM6DS3TR_C_EXT_ON_INT2_PIN = 1, + LSM6DS3TR_C_SH_SYNCRO_ND = 2, /* ERROR CODE */ +} lsm6ds3tr_c_start_config_t; +int32_t lsm6ds3tr_c_sh_syncro_mode_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_start_config_t val); +int32_t lsm6ds3tr_c_sh_syncro_mode_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_start_config_t *val); + +int32_t lsm6ds3tr_c_sh_drdy_on_int1_set(const stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6ds3tr_c_sh_drdy_on_int1_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +typedef struct +{ + lsm6ds3tr_c_sensorhub1_reg_t sh_byte_1; + lsm6ds3tr_c_sensorhub2_reg_t sh_byte_2; + lsm6ds3tr_c_sensorhub3_reg_t sh_byte_3; + lsm6ds3tr_c_sensorhub4_reg_t sh_byte_4; + lsm6ds3tr_c_sensorhub5_reg_t sh_byte_5; + lsm6ds3tr_c_sensorhub6_reg_t sh_byte_6; + lsm6ds3tr_c_sensorhub7_reg_t sh_byte_7; + lsm6ds3tr_c_sensorhub8_reg_t sh_byte_8; + lsm6ds3tr_c_sensorhub9_reg_t sh_byte_9; + lsm6ds3tr_c_sensorhub10_reg_t sh_byte_10; + lsm6ds3tr_c_sensorhub11_reg_t sh_byte_11; + lsm6ds3tr_c_sensorhub12_reg_t sh_byte_12; + lsm6ds3tr_c_sensorhub13_reg_t sh_byte_13; + lsm6ds3tr_c_sensorhub14_reg_t sh_byte_14; + lsm6ds3tr_c_sensorhub15_reg_t sh_byte_15; + lsm6ds3tr_c_sensorhub16_reg_t sh_byte_16; + lsm6ds3tr_c_sensorhub17_reg_t sh_byte_17; + lsm6ds3tr_c_sensorhub18_reg_t sh_byte_18; +} lsm6ds3tr_c_emb_sh_read_t; +int32_t lsm6ds3tr_c_sh_read_data_raw_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_emb_sh_read_t *val); + +int32_t lsm6ds3tr_c_sh_cmd_sens_sync_set(const stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6ds3tr_c_sh_cmd_sens_sync_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6ds3tr_c_sh_spi_sync_error_set(const stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6ds3tr_c_sh_spi_sync_error_get(const stmdev_ctx_t *ctx, + uint8_t *val); + +typedef enum +{ + LSM6DS3TR_C_SLV_0 = 0, + LSM6DS3TR_C_SLV_0_1 = 1, + LSM6DS3TR_C_SLV_0_1_2 = 2, + LSM6DS3TR_C_SLV_0_1_2_3 = 3, + LSM6DS3TR_C_SLV_EN_ND = 4, /* ERROR CODE */ +} lsm6ds3tr_c_aux_sens_on_t; +int32_t lsm6ds3tr_c_sh_num_of_dev_connected_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_aux_sens_on_t val); +int32_t lsm6ds3tr_c_sh_num_of_dev_connected_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_aux_sens_on_t *val); + +typedef struct +{ + uint8_t slv0_add; + uint8_t slv0_subadd; + uint8_t slv0_data; +} lsm6ds3tr_c_sh_cfg_write_t; +int32_t lsm6ds3tr_c_sh_cfg_write(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_sh_cfg_write_t *val); + +typedef struct +{ + uint8_t slv_add; + uint8_t slv_subadd; + uint8_t slv_len; +} lsm6ds3tr_c_sh_cfg_read_t; +int32_t lsm6ds3tr_c_sh_slv0_cfg_read(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_sh_cfg_read_t *val); +int32_t lsm6ds3tr_c_sh_slv1_cfg_read(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_sh_cfg_read_t *val); +int32_t lsm6ds3tr_c_sh_slv2_cfg_read(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_sh_cfg_read_t *val); +int32_t lsm6ds3tr_c_sh_slv3_cfg_read(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_sh_cfg_read_t *val); + +typedef enum +{ + LSM6DS3TR_C_SL0_NO_DEC = 0, + LSM6DS3TR_C_SL0_DEC_2 = 1, + LSM6DS3TR_C_SL0_DEC_4 = 2, + LSM6DS3TR_C_SL0_DEC_8 = 3, + LSM6DS3TR_C_SL0_DEC_ND = 4, /* ERROR CODE */ +} lsm6ds3tr_c_slave0_rate_t; +int32_t lsm6ds3tr_c_sh_slave_0_dec_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_slave0_rate_t val); +int32_t lsm6ds3tr_c_sh_slave_0_dec_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_slave0_rate_t *val); + +typedef enum +{ + LSM6DS3TR_C_EACH_SH_CYCLE = 0, + LSM6DS3TR_C_ONLY_FIRST_CYCLE = 1, + LSM6DS3TR_C_SH_WR_MODE_ND = 2, /* ERROR CODE */ +} lsm6ds3tr_c_write_once_t; +int32_t lsm6ds3tr_c_sh_write_mode_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_write_once_t val); +int32_t lsm6ds3tr_c_sh_write_mode_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_write_once_t *val); + +typedef enum +{ + LSM6DS3TR_C_SL1_NO_DEC = 0, + LSM6DS3TR_C_SL1_DEC_2 = 1, + LSM6DS3TR_C_SL1_DEC_4 = 2, + LSM6DS3TR_C_SL1_DEC_8 = 3, + LSM6DS3TR_C_SL1_DEC_ND = 4, /* ERROR CODE */ +} lsm6ds3tr_c_slave1_rate_t; +int32_t lsm6ds3tr_c_sh_slave_1_dec_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_slave1_rate_t val); +int32_t lsm6ds3tr_c_sh_slave_1_dec_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_slave1_rate_t *val); + +typedef enum +{ + LSM6DS3TR_C_SL2_NO_DEC = 0, + LSM6DS3TR_C_SL2_DEC_2 = 1, + LSM6DS3TR_C_SL2_DEC_4 = 2, + LSM6DS3TR_C_SL2_DEC_8 = 3, + LSM6DS3TR_C_SL2_DEC_ND = 4, /* ERROR CODE */ +} lsm6ds3tr_c_slave2_rate_t; +int32_t lsm6ds3tr_c_sh_slave_2_dec_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_slave2_rate_t val); +int32_t lsm6ds3tr_c_sh_slave_2_dec_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_slave2_rate_t *val); + +typedef enum +{ + LSM6DS3TR_C_SL3_NO_DEC = 0, + LSM6DS3TR_C_SL3_DEC_2 = 1, + LSM6DS3TR_C_SL3_DEC_4 = 2, + LSM6DS3TR_C_SL3_DEC_8 = 3, + LSM6DS3TR_C_SL3_DEC_ND = 4, /* ERROR CODE */ +} lsm6ds3tr_c_slave3_rate_t; +int32_t lsm6ds3tr_c_sh_slave_3_dec_set(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_slave3_rate_t val); +int32_t lsm6ds3tr_c_sh_slave_3_dec_get(const stmdev_ctx_t *ctx, + lsm6ds3tr_c_slave3_rate_t *val); + +/** + * @} + * + */ + +#ifdef __cplusplus +} +#endif + +#endif /* LSM6DS3TR_C_DRIVER_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/airmouse/lib/lsm6dso-api/.gitsubtree b/airmouse/lib/lsm6dso-api/.gitsubtree new file mode 100644 index 00000000000..ea6c0e11285 --- /dev/null +++ b/airmouse/lib/lsm6dso-api/.gitsubtree @@ -0,0 +1 @@ +https://github.com/STMicroelectronics/stm32-lsm6dso main / diff --git a/airmouse/lib/lsm6dso-api/CODE_OF_CONDUCT.md b/airmouse/lib/lsm6dso-api/CODE_OF_CONDUCT.md new file mode 100644 index 00000000000..8f8955aa3ad --- /dev/null +++ b/airmouse/lib/lsm6dso-api/CODE_OF_CONDUCT.md @@ -0,0 +1,73 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team via this [link](https://www.st.com/content/st_com/en/contact-us.html). +All complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 1.4, +available [here](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html). + +For answers to common questions about this code of conduct, see the [FAQ section](https://www.contributor-covenant.org/faq). diff --git a/airmouse/lib/lsm6dso-api/CONTRIBUTING.md b/airmouse/lib/lsm6dso-api/CONTRIBUTING.md new file mode 100644 index 00000000000..8668d97cbf3 --- /dev/null +++ b/airmouse/lib/lsm6dso-api/CONTRIBUTING.md @@ -0,0 +1,40 @@ +# Contributing guide + +This guide serves as a checklist before contributing to this repository. It mainly focuses on the steps to follow to submit an issue or a pull-request. + +## 1. Issues + +### 1.1 Before opening an issue + +Please check the following points before posting an issue: +* Make sure you are using the latest commit (major releases are tagged, but corrections are available as new commits). +* Make sure your issue is a question/feedback/suggestions **related to** the software provided in this repository. Otherwise, please refer to section [3](CONTRIBUTING.md#3-support-requests-and-questions) below. +* Make sure your issue is not already reported/fixed on GitHub or discussed on a previous issue. Do not forget to browse into the **closed** issues. + +### 1.2 Posting the issue + +When you have checked the previous points, create a new report from the **Issues** tab of this repository. A template is available [here](../../issues/new/choose) to help you report the issue you are facing or the enhancement you would like to propose. + +## 2. Pull Requests + +### 2.1 Before opening a pull-request + +STMicrolectronics is happy to receive contributions from the community, based on an initial Contributor License Agreement (CLA) procedure. + +* If you are an individual writing original source code and you are sure **you own the intellectual property**, then you need to sign an Individual [CLA](https://cla.st.com). +* If you work for a company that wants also to allow you to contribute with your work, your company needs to provide a Corporate [CLA](https://cla.st.com) mentioning your GitHub account name. +* If you are not sure that a CLA (Individual or Corporate) has been signed for your GitHub account you can check the [CLA](https://cla.st.com) dedicated page. + +Please note that: +* The Corporate CLA will always take precedence over the Individual CLA. +* One CLA submission is sufficient, for any project proposed by STMicroelectronics. + +### 2.2 How to proceed + +* We recommend to engage first a communication thru an issue, in order to present your proposal, just to confirm that it corresponds to STMicroelectronics' domain or scope. +* Then fork the project to your GitHub account to further develop your contribution. Please use the latest commit version. +* Please, submit one pull-request per new feature or proposal. This will ease the analysis and the final merge if accepted. + +## 3. Support requests and questions + +For support requests or any other question related to the product, the tools, the environment, you can submit a post to the **ST Community** on the appropriate topic [page](https://community.st.com/s/topiccatalog). diff --git a/airmouse/lib/lsm6dso-api/LICENSE.md b/airmouse/lib/lsm6dso-api/LICENSE.md new file mode 100644 index 00000000000..e349e2328b7 --- /dev/null +++ b/airmouse/lib/lsm6dso-api/LICENSE.md @@ -0,0 +1,27 @@ +Copyright 2019 STMicroelectronics. +All rights reserved. + +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. diff --git a/airmouse/lib/lsm6dso-api/README.md b/airmouse/lib/lsm6dso-api/README.md new file mode 100644 index 00000000000..1fe67f605fe --- /dev/null +++ b/airmouse/lib/lsm6dso-api/README.md @@ -0,0 +1,34 @@ +# BSP LSM6DSO Component + +![latest tag](https://img.shields.io/github/v/tag/STMicroelectronics/stm32-lsm6dso.svg?color=brightgreen) + +## Overview + +**STM32Cube** is an STMicroelectronics original initiative to ease the developers life by reducing efforts, time and cost. + +**STM32Cube** covers the overall STM32 products portfolio. It includes a comprehensive embedded software platform delivered for each STM32 series. + * The CMSIS modules (core and device) corresponding to the ARM(tm) core implemented in this STM32 product. + * The STM32 HAL-LL drivers, an abstraction layer offering a set of APIs ensuring maximized portability across the STM32 portfolio. + * The BSP drivers of each evaluation, demonstration or nucleo board provided for this STM32 series. + * A consistent set of middleware components such as RTOS, USB, FatFS, graphics, touch sensing library... + * A full set of software projects (basic examples, applications, and demonstrations) for each board provided for this STM32 series. + +Two models of publication are proposed for the STM32Cube embedded software: + * The monolithic **MCU Package**: all STM32Cube software modules of one STM32 series are present (Drivers, Middleware, Projects, Utilities) in the repository (usual name **STM32Cubexx**, xx corresponding to the STM32 series). + * The **MCU component**: each STM32Cube software module being part of the STM32Cube MCU Package, is delivered as an individual repository, allowing the user to select and get only the required software functions. + +## Description + +This **lsm6dso** MCU component repository is one element **common to all** STM32Cube MCU embedded software packages, providing the **LSM6DSO** BSP MEMS component part. + +## Release note + +Details about the content of this release are available in the release note [here](https://htmlpreview.github.io/?https://github.com/STMicroelectronics/lsm6dso/blob/main/Release_Notes.html). + +## Compatibility information + +Please refer to the repository of the BSP **board** driver you are using to know which version of this BSP component driver to use. It is **crucial** that you use a consistent set of versions. + +## Troubleshooting + +Please refer to the [CONTRIBUTING.md](CONTRIBUTING.md) guide. diff --git a/airmouse/lib/lsm6dso-api/Release_Notes.html b/airmouse/lib/lsm6dso-api/Release_Notes.html new file mode 100644 index 00000000000..4da65558c45 --- /dev/null +++ b/airmouse/lib/lsm6dso-api/Release_Notes.html @@ -0,0 +1,257 @@ + + + + + + + Release Notes for LSM6DSO Component + + + + + + +
+
+
+

Release Notes for +LSM6DSO Component Driver

+

Copyright © 2022 STMicroelectronics
+

+ +
+

Purpose

+

This directory contains the LSM6DSO component drivers.

+
+
+

Update history

+
+ + +
+

Main changes

+

Maintenance release

+
    +
  • Synchronized PID with currently latest version on ST GitHub
  • +
  • Added Delay function
  • +
+

+
+
+
+ + +
+

Main changes

+

Maintenance release

+
    +
  • Synchronized PID with currently latest version on ST GitHub
  • +
+

+
+
+
+ + +
+

Main changes

+

Patch release

+
    +
  • Update License to new format
  • +
+

+
+
+
+ + +
+

Main changes

+

Patch release

+
    +
  • Fix C++ compiler errors
  • +
+

+
+
+
+ + +
+

Main changes

+

Patch release

+
    +
  • Update Release Notes to new format
  • +
+

+
+
+
+ + +
+

Main changes

+

Patch release

+
    +
  • Fix issues on INT2 events
  • +
+

+
+
+
+ + +
+

Main changes

+

Maintenance release

+
    +
  • Synchronize PID with latest version on ST GitHub
  • +
+

+
+
+
+ + +
+

Main changes

+

Maintenance release

+
    +
  • Update PID
  • +
+

+
+
+
+ + +
+

Main changes

+

Maintenance release

+
    +
  • Update PID
  • +
  • Add MISRA 2012 compliancy
  • +
+

+
+
+
+ + +
+

Main changes

+

Patch release

+
    +
  • Align ODR values like PID
  • +
+

+
+
+
+ + +
+

Main changes

+

Patch release

+
    +
  • Rename context type to universal stmdev_ctx_t
  • +
  • Move unions from PID to HLD
  • +
+

+
+
+
+ + +
+

Main changes

+

Patch release

+
    +
  • Update license
  • +
+

+
+
+
+ + +
+

Main changes

+

Maintenance release

+
    +
  • PID update from ST GitHub
  • +
  • Add new APIs for VibrationMonitoring to HLD
  • +
  • HLD coding style update
  • +
+

+
+
+
+ + +
+

Main changes

+

Maintenance release

+
    +
  • Add new APIs
  • +
+

+
+
+
+ + +
+

Main changes

+

First release

+
    +
  • First official release
  • +
+

+
+
+
+
+
+
+
+

For complete documentation on LSM6DSO, visit: LSM6DSO

+
+

Info

+
+
+
+ + diff --git a/airmouse/lib/lsm6dso-api/SECURITY.md b/airmouse/lib/lsm6dso-api/SECURITY.md new file mode 100644 index 00000000000..b784d151bde --- /dev/null +++ b/airmouse/lib/lsm6dso-api/SECURITY.md @@ -0,0 +1,31 @@ +# Report potential product security vulnerabilities + +ST places a high priority on security, and our Product Security Incident +Response Team (PSIRT) is committed to rapidly addressing potential security +vulnerabilities affecting our products. PSIRT's long history and vast experience +in security allows ST to perform clear analyses and provide appropriate guidance +on mitigations and solutions when applicable. + +If you wish to report potential security vulnerabilities regarding our products, +**please do not report them through public GitHub issues.** Instead, we +encourage you to report them to our ST PSIRT following the process described at: +**https://www.st.com/content/st_com/en/security/report-vulnerabilities.html** + +### IMPORTANT - READ CAREFULLY: + +STMicroelectronics International N.V., on behalf of itself, its affiliates and +subsidiaries, (collectively “ST”) takes all potential security vulnerability +reports or other related communications (“Report(s)”) seriously. In order to +review Your Report (the terms “You” and “Yours” include your employer, and all +affiliates, subsidiaries and related persons or entities) and take actions as +deemed appropriate, ST requires that we have the rights and Your permission to +do so. + +As such, by submitting Your Report to ST, You agree that You have the right to +do so, and You grant to ST the rights to use the Report for purposes related to +security vulnerability analysis, testing, correction, patching, reporting and +any other related purpose or function. + +By submitting Your Report, You agree that ST’s +[Privacy Policy](https://www.st.com/content/st_com/en/common/privacy-portal.html) +applies to all related communications. diff --git a/airmouse/lib/lsm6dso-api/_htmresc/favicon.png b/airmouse/lib/lsm6dso-api/_htmresc/favicon.png new file mode 100644 index 00000000000..06713eec497 Binary files /dev/null and b/airmouse/lib/lsm6dso-api/_htmresc/favicon.png differ diff --git a/airmouse/lib/lsm6dso-api/_htmresc/mini-st_2020.css b/airmouse/lib/lsm6dso-api/_htmresc/mini-st_2020.css new file mode 100644 index 00000000000..986f4d42050 --- /dev/null +++ b/airmouse/lib/lsm6dso-api/_htmresc/mini-st_2020.css @@ -0,0 +1,1711 @@ +@charset "UTF-8"; +/* + Flavor name: Custom (mini-custom) + Generated online - https://minicss.org/flavors + mini.css version: v3.0.1 +*/ +/* + Browsers resets and base typography. +*/ +/* Core module CSS variable definitions */ +:root { + --fore-color: #03234b; + --secondary-fore-color: #03234b; + --back-color: #ffffff; + --secondary-back-color: #ffffff; + --blockquote-color: #e6007e; + --pre-color: #e6007e; + --border-color: #3cb4e6; + --secondary-border-color: #3cb4e6; + --heading-ratio: 1.2; + --universal-margin: 0.5rem; + --universal-padding: 0.25rem; + --universal-border-radius: 0.075rem; + --background-margin: 1.5%; + --a-link-color: #3cb4e6; + --a-visited-color: #8c0078; } + +html { + font-size: 13.5px; } + +a, b, del, em, i, ins, q, span, strong, u { + font-size: 1em; } + +html, * { + font-family: -apple-system, BlinkMacSystemFont, Helvetica, arial, sans-serif; + line-height: 1.25; + -webkit-text-size-adjust: 100%; } + +* { + font-size: 1rem; } + +body { + margin: 0; + color: var(--fore-color); + @background: var(--back-color); + background: var(--back-color) linear-gradient(#ffd200, #ffd200) repeat-y left top; + background-size: var(--background-margin); + } + +details { + display: block; } + +summary { + display: list-item; } + +abbr[title] { + border-bottom: none; + text-decoration: underline dotted; } + +input { + overflow: visible; } + +img { + max-width: 100%; + height: auto; } + +h1, h2, h3, h4, h5, h6 { + line-height: 1.25; + margin: calc(1.5 * var(--universal-margin)) var(--universal-margin); + font-weight: 400; } + h1 small, h2 small, h3 small, h4 small, h5 small, h6 small { + color: var(--secondary-fore-color); + display: block; + margin-top: -0.25rem; } + +h1 { + font-size: calc(1rem * var(--heading-ratio) * var(--heading-ratio) * var(--heading-ratio)); } + +h2 { + font-size: calc(1rem * var(--heading-ratio) * var(--heading-ratio) ); + border-style: none none solid none ; + border-width: thin; + border-color: var(--border-color); } +h3 { + font-size: calc(1rem * var(--heading-ratio) ); } + +h4 { + font-size: calc(1rem * var(--heading-ratio)); } + +h5 { + font-size: 1rem; } + +h6 { + font-size: calc(1rem / var(--heading-ratio)); } + +p { + margin: var(--universal-margin); } + +ol, ul { + margin: var(--universal-margin); + padding-left: calc(3 * var(--universal-margin)); } + +b, strong { + font-weight: 700; } + +hr { + box-sizing: content-box; + border: 0; + line-height: 1.25em; + margin: var(--universal-margin); + height: 0.0714285714rem; + background: linear-gradient(to right, transparent, var(--border-color) 20%, var(--border-color) 80%, transparent); } + +blockquote { + display: block; + position: relative; + font-style: italic; + color: var(--secondary-fore-color); + margin: var(--universal-margin); + padding: calc(3 * var(--universal-padding)); + border: 0.0714285714rem solid var(--secondary-border-color); + border-left: 0.3rem solid var(--blockquote-color); + border-radius: 0 var(--universal-border-radius) var(--universal-border-radius) 0; } + blockquote:before { + position: absolute; + top: calc(0rem - var(--universal-padding)); + left: 0; + font-family: sans-serif; + font-size: 2rem; + font-weight: 800; + content: "\201c"; + color: var(--blockquote-color); } + blockquote[cite]:after { + font-style: normal; + font-size: 0.75em; + font-weight: 700; + content: "\a— " attr(cite); + white-space: pre; } + +code, kbd, pre, samp { + font-family: Menlo, Consolas, monospace; + font-size: 0.85em; } + +code { + background: var(--secondary-back-color); + border-radius: var(--universal-border-radius); + padding: calc(var(--universal-padding) / 4) calc(var(--universal-padding) / 2); } + +kbd { + background: var(--fore-color); + color: var(--back-color); + border-radius: var(--universal-border-radius); + padding: calc(var(--universal-padding) / 4) calc(var(--universal-padding) / 2); } + +pre { + overflow: auto; + background: var(--secondary-back-color); + padding: calc(1.5 * var(--universal-padding)); + margin: var(--universal-margin); + border: 0.0714285714rem solid var(--secondary-border-color); + border-left: 0.2857142857rem solid var(--pre-color); + border-radius: 0 var(--universal-border-radius) var(--universal-border-radius) 0; } + +sup, sub, code, kbd { + line-height: 0; + position: relative; + vertical-align: baseline; } + +small, sup, sub, figcaption { + font-size: 0.75em; } + +sup { + top: -0.5em; } + +sub { + bottom: -0.25em; } + +figure { + margin: var(--universal-margin); } + +figcaption { + color: var(--secondary-fore-color); } + +a { + text-decoration: none; } + a:link { + color: var(--a-link-color); } + a:visited { + color: var(--a-visited-color); } + a:hover, a:focus { + text-decoration: underline; } + +/* + Definitions for the grid system, cards and containers. +*/ +.container { + margin: 0 auto; + padding: 0 calc(1.5 * var(--universal-padding)); } + +.row { + box-sizing: border-box; + display: flex; + flex: 0 1 auto; + flex-flow: row wrap; + margin: 0 0 0 var(--background-margin); } + +.col-sm, +[class^='col-sm-'], +[class^='col-sm-offset-'], +.row[class*='cols-sm-'] > * { + box-sizing: border-box; + flex: 0 0 auto; + padding: 0 calc(var(--universal-padding) / 2); } + +.col-sm, +.row.cols-sm > * { + max-width: 100%; + flex-grow: 1; + flex-basis: 0; } + +.col-sm-1, +.row.cols-sm-1 > * { + max-width: 8.3333333333%; + flex-basis: 8.3333333333%; } + +.col-sm-offset-0 { + margin-left: 0; } + +.col-sm-2, +.row.cols-sm-2 > * { + max-width: 16.6666666667%; + flex-basis: 16.6666666667%; } + +.col-sm-offset-1 { + margin-left: 8.3333333333%; } + +.col-sm-3, +.row.cols-sm-3 > * { + max-width: 25%; + flex-basis: 25%; } + +.col-sm-offset-2 { + margin-left: 16.6666666667%; } + +.col-sm-4, +.row.cols-sm-4 > * { + max-width: 33.3333333333%; + flex-basis: 33.3333333333%; } + +.col-sm-offset-3 { + margin-left: 25%; } + +.col-sm-5, +.row.cols-sm-5 > * { + max-width: 41.6666666667%; + flex-basis: 41.6666666667%; } + +.col-sm-offset-4 { + margin-left: 33.3333333333%; } + +.col-sm-6, +.row.cols-sm-6 > * { + max-width: 50%; + flex-basis: 50%; } + +.col-sm-offset-5 { + margin-left: 41.6666666667%; } + +.col-sm-7, +.row.cols-sm-7 > * { + max-width: 58.3333333333%; + flex-basis: 58.3333333333%; } + +.col-sm-offset-6 { + margin-left: 50%; } + +.col-sm-8, +.row.cols-sm-8 > * { + max-width: 66.6666666667%; + flex-basis: 66.6666666667%; } + +.col-sm-offset-7 { + margin-left: 58.3333333333%; } + +.col-sm-9, +.row.cols-sm-9 > * { + max-width: 75%; + flex-basis: 75%; } + +.col-sm-offset-8 { + margin-left: 66.6666666667%; } + +.col-sm-10, +.row.cols-sm-10 > * { + max-width: 83.3333333333%; + flex-basis: 83.3333333333%; } + +.col-sm-offset-9 { + margin-left: 75%; } + +.col-sm-11, +.row.cols-sm-11 > * { + max-width: 91.6666666667%; + flex-basis: 91.6666666667%; } + +.col-sm-offset-10 { + margin-left: 83.3333333333%; } + +.col-sm-12, +.row.cols-sm-12 > * { + max-width: 100%; + flex-basis: 100%; } + +.col-sm-offset-11 { + margin-left: 91.6666666667%; } + +.col-sm-normal { + order: initial; } + +.col-sm-first { + order: -999; } + +.col-sm-last { + order: 999; } + +@media screen and (min-width: 500px) { + .col-md, + [class^='col-md-'], + [class^='col-md-offset-'], + .row[class*='cols-md-'] > * { + box-sizing: border-box; + flex: 0 0 auto; + padding: 0 calc(var(--universal-padding) / 2); } + + .col-md, + .row.cols-md > * { + max-width: 100%; + flex-grow: 1; + flex-basis: 0; } + + .col-md-1, + .row.cols-md-1 > * { + max-width: 8.3333333333%; + flex-basis: 8.3333333333%; } + + .col-md-offset-0 { + margin-left: 0; } + + .col-md-2, + .row.cols-md-2 > * { + max-width: 16.6666666667%; + flex-basis: 16.6666666667%; } + + .col-md-offset-1 { + margin-left: 8.3333333333%; } + + .col-md-3, + .row.cols-md-3 > * { + max-width: 25%; + flex-basis: 25%; } + + .col-md-offset-2 { + margin-left: 16.6666666667%; } + + .col-md-4, + .row.cols-md-4 > * { + max-width: 33.3333333333%; + flex-basis: 33.3333333333%; } + + .col-md-offset-3 { + margin-left: 25%; } + + .col-md-5, + .row.cols-md-5 > * { + max-width: 41.6666666667%; + flex-basis: 41.6666666667%; } + + .col-md-offset-4 { + margin-left: 33.3333333333%; } + + .col-md-6, + .row.cols-md-6 > * { + max-width: 50%; + flex-basis: 50%; } + + .col-md-offset-5 { + margin-left: 41.6666666667%; } + + .col-md-7, + .row.cols-md-7 > * { + max-width: 58.3333333333%; + flex-basis: 58.3333333333%; } + + .col-md-offset-6 { + margin-left: 50%; } + + .col-md-8, + .row.cols-md-8 > * { + max-width: 66.6666666667%; + flex-basis: 66.6666666667%; } + + .col-md-offset-7 { + margin-left: 58.3333333333%; } + + .col-md-9, + .row.cols-md-9 > * { + max-width: 75%; + flex-basis: 75%; } + + .col-md-offset-8 { + margin-left: 66.6666666667%; } + + .col-md-10, + .row.cols-md-10 > * { + max-width: 83.3333333333%; + flex-basis: 83.3333333333%; } + + .col-md-offset-9 { + margin-left: 75%; } + + .col-md-11, + .row.cols-md-11 > * { + max-width: 91.6666666667%; + flex-basis: 91.6666666667%; } + + .col-md-offset-10 { + margin-left: 83.3333333333%; } + + .col-md-12, + .row.cols-md-12 > * { + max-width: 100%; + flex-basis: 100%; } + + .col-md-offset-11 { + margin-left: 91.6666666667%; } + + .col-md-normal { + order: initial; } + + .col-md-first { + order: -999; } + + .col-md-last { + order: 999; } } +@media screen and (min-width: 1280px) { + .col-lg, + [class^='col-lg-'], + [class^='col-lg-offset-'], + .row[class*='cols-lg-'] > * { + box-sizing: border-box; + flex: 0 0 auto; + padding: 0 calc(var(--universal-padding) / 2); } + + .col-lg, + .row.cols-lg > * { + max-width: 100%; + flex-grow: 1; + flex-basis: 0; } + + .col-lg-1, + .row.cols-lg-1 > * { + max-width: 8.3333333333%; + flex-basis: 8.3333333333%; } + + .col-lg-offset-0 { + margin-left: 0; } + + .col-lg-2, + .row.cols-lg-2 > * { + max-width: 16.6666666667%; + flex-basis: 16.6666666667%; } + + .col-lg-offset-1 { + margin-left: 8.3333333333%; } + + .col-lg-3, + .row.cols-lg-3 > * { + max-width: 25%; + flex-basis: 25%; } + + .col-lg-offset-2 { + margin-left: 16.6666666667%; } + + .col-lg-4, + .row.cols-lg-4 > * { + max-width: 33.3333333333%; + flex-basis: 33.3333333333%; } + + .col-lg-offset-3 { + margin-left: 25%; } + + .col-lg-5, + .row.cols-lg-5 > * { + max-width: 41.6666666667%; + flex-basis: 41.6666666667%; } + + .col-lg-offset-4 { + margin-left: 33.3333333333%; } + + .col-lg-6, + .row.cols-lg-6 > * { + max-width: 50%; + flex-basis: 50%; } + + .col-lg-offset-5 { + margin-left: 41.6666666667%; } + + .col-lg-7, + .row.cols-lg-7 > * { + max-width: 58.3333333333%; + flex-basis: 58.3333333333%; } + + .col-lg-offset-6 { + margin-left: 50%; } + + .col-lg-8, + .row.cols-lg-8 > * { + max-width: 66.6666666667%; + flex-basis: 66.6666666667%; } + + .col-lg-offset-7 { + margin-left: 58.3333333333%; } + + .col-lg-9, + .row.cols-lg-9 > * { + max-width: 75%; + flex-basis: 75%; } + + .col-lg-offset-8 { + margin-left: 66.6666666667%; } + + .col-lg-10, + .row.cols-lg-10 > * { + max-width: 83.3333333333%; + flex-basis: 83.3333333333%; } + + .col-lg-offset-9 { + margin-left: 75%; } + + .col-lg-11, + .row.cols-lg-11 > * { + max-width: 91.6666666667%; + flex-basis: 91.6666666667%; } + + .col-lg-offset-10 { + margin-left: 83.3333333333%; } + + .col-lg-12, + .row.cols-lg-12 > * { + max-width: 100%; + flex-basis: 100%; } + + .col-lg-offset-11 { + margin-left: 91.6666666667%; } + + .col-lg-normal { + order: initial; } + + .col-lg-first { + order: -999; } + + .col-lg-last { + order: 999; } } +/* Card component CSS variable definitions */ +:root { + --card-back-color: #3cb4e6; + --card-fore-color: #03234b; + --card-border-color: #03234b; } + +.card { + display: flex; + flex-direction: column; + justify-content: space-between; + align-self: center; + position: relative; + width: 100%; + background: var(--card-back-color); + color: var(--card-fore-color); + border: 0.0714285714rem solid var(--card-border-color); + border-radius: var(--universal-border-radius); + margin: var(--universal-margin); + overflow: hidden; } + @media screen and (min-width: 320px) { + .card { + max-width: 320px; } } + .card > .sectione { + background: var(--card-back-color); + color: var(--card-fore-color); + box-sizing: border-box; + margin: 0; + border: 0; + border-radius: 0; + border-bottom: 0.0714285714rem solid var(--card-border-color); + padding: var(--universal-padding); + width: 100%; } + .card > .sectione.media { + height: 200px; + padding: 0; + -o-object-fit: cover; + object-fit: cover; } + .card > .sectione:last-child { + border-bottom: 0; } + +/* + Custom elements for card elements. +*/ +@media screen and (min-width: 240px) { + .card.small { + max-width: 240px; } } +@media screen and (min-width: 480px) { + .card.large { + max-width: 480px; } } +.card.fluid { + max-width: 100%; + width: auto; } + +.card.warning { + --card-back-color: #e5b8b7; + --card-fore-color: #3b234b; + --card-border-color: #8c0078; } + +.card.error { + --card-back-color: #464650; + --card-fore-color: #ffffff; + --card-border-color: #8c0078; } + +.card > .sectione.dark { + --card-back-color: #3b234b; + --card-fore-color: #ffffff; } + +.card > .sectione.double-padded { + padding: calc(1.5 * var(--universal-padding)); } + +/* + Definitions for forms and input elements. +*/ +/* Input_control module CSS variable definitions */ +:root { + --form-back-color: #ffe97f; + --form-fore-color: #03234b; + --form-border-color: #3cb4e6; + --input-back-color: #ffffff; + --input-fore-color: #03234b; + --input-border-color: #3cb4e6; + --input-focus-color: #0288d1; + --input-invalid-color: #d32f2f; + --button-back-color: #e2e2e2; + --button-hover-back-color: #dcdcdc; + --button-fore-color: #212121; + --button-border-color: transparent; + --button-hover-border-color: transparent; + --button-group-border-color: rgba(124, 124, 124, 0.54); } + +form { + background: var(--form-back-color); + color: var(--form-fore-color); + border: 0.0714285714rem solid var(--form-border-color); + border-radius: var(--universal-border-radius); + margin: var(--universal-margin); + padding: calc(2 * var(--universal-padding)) var(--universal-padding); } + +fieldset { + border: 0.0714285714rem solid var(--form-border-color); + border-radius: var(--universal-border-radius); + margin: calc(var(--universal-margin) / 4); + padding: var(--universal-padding); } + +legend { + box-sizing: border-box; + display: table; + max-width: 100%; + white-space: normal; + font-weight: 500; + padding: calc(var(--universal-padding) / 2); } + +label { + padding: calc(var(--universal-padding) / 2) var(--universal-padding); } + +.input-group { + display: inline-block; } + .input-group.fluid { + display: flex; + align-items: center; + justify-content: center; } + .input-group.fluid > input { + max-width: 100%; + flex-grow: 1; + flex-basis: 0px; } + @media screen and (max-width: 499px) { + .input-group.fluid { + align-items: stretch; + flex-direction: column; } } + .input-group.vertical { + display: flex; + align-items: stretch; + flex-direction: column; } + .input-group.vertical > input { + max-width: 100%; + flex-grow: 1; + flex-basis: 0px; } + +[type="number"]::-webkit-inner-spin-button, [type="number"]::-webkit-outer-spin-button { + height: auto; } + +[type="search"] { + -webkit-appearance: textfield; + outline-offset: -2px; } + +[type="search"]::-webkit-search-cancel-button, +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; } + +input:not([type]), [type="text"], [type="email"], [type="number"], [type="search"], +[type="password"], [type="url"], [type="tel"], [type="checkbox"], [type="radio"], textarea, select { + box-sizing: border-box; + background: var(--input-back-color); + color: var(--input-fore-color); + border: 0.0714285714rem solid var(--input-border-color); + border-radius: var(--universal-border-radius); + margin: calc(var(--universal-margin) / 2); + padding: var(--universal-padding) calc(1.5 * var(--universal-padding)); } + +input:not([type="button"]):not([type="submit"]):not([type="reset"]):hover, input:not([type="button"]):not([type="submit"]):not([type="reset"]):focus, textarea:hover, textarea:focus, select:hover, select:focus { + border-color: var(--input-focus-color); + box-shadow: none; } +input:not([type="button"]):not([type="submit"]):not([type="reset"]):invalid, input:not([type="button"]):not([type="submit"]):not([type="reset"]):focus:invalid, textarea:invalid, textarea:focus:invalid, select:invalid, select:focus:invalid { + border-color: var(--input-invalid-color); + box-shadow: none; } +input:not([type="button"]):not([type="submit"]):not([type="reset"])[readonly], textarea[readonly], select[readonly] { + background: var(--secondary-back-color); } + +select { + max-width: 100%; } + +option { + overflow: hidden; + text-overflow: ellipsis; } + +[type="checkbox"], [type="radio"] { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + position: relative; + height: calc(1rem + var(--universal-padding) / 2); + width: calc(1rem + var(--universal-padding) / 2); + vertical-align: text-bottom; + padding: 0; + flex-basis: calc(1rem + var(--universal-padding) / 2) !important; + flex-grow: 0 !important; } + [type="checkbox"]:checked:before, [type="radio"]:checked:before { + position: absolute; } + +[type="checkbox"]:checked:before { + content: '\2713'; + font-family: sans-serif; + font-size: calc(1rem + var(--universal-padding) / 2); + top: calc(0rem - var(--universal-padding)); + left: calc(var(--universal-padding) / 4); } + +[type="radio"] { + border-radius: 100%; } + [type="radio"]:checked:before { + border-radius: 100%; + content: ''; + top: calc(0.0714285714rem + var(--universal-padding) / 2); + left: calc(0.0714285714rem + var(--universal-padding) / 2); + background: var(--input-fore-color); + width: 0.5rem; + height: 0.5rem; } + +:placeholder-shown { + color: var(--input-fore-color); } + +::-ms-placeholder { + color: var(--input-fore-color); + opacity: 0.54; } + +button::-moz-focus-inner, [type="button"]::-moz-focus-inner, [type="reset"]::-moz-focus-inner, [type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; } + +button, html [type="button"], [type="reset"], [type="submit"] { + -webkit-appearance: button; } + +button { + overflow: visible; + text-transform: none; } + +button, [type="button"], [type="submit"], [type="reset"], +a.button, label.button, .button, +a[role="button"], label[role="button"], [role="button"] { + display: inline-block; + background: var(--button-back-color); + color: var(--button-fore-color); + border: 0.0714285714rem solid var(--button-border-color); + border-radius: var(--universal-border-radius); + padding: var(--universal-padding) calc(1.5 * var(--universal-padding)); + margin: var(--universal-margin); + text-decoration: none; + cursor: pointer; + transition: background 0.3s; } + button:hover, button:focus, [type="button"]:hover, [type="button"]:focus, [type="submit"]:hover, [type="submit"]:focus, [type="reset"]:hover, [type="reset"]:focus, + a.button:hover, + a.button:focus, label.button:hover, label.button:focus, .button:hover, .button:focus, + a[role="button"]:hover, + a[role="button"]:focus, label[role="button"]:hover, label[role="button"]:focus, [role="button"]:hover, [role="button"]:focus { + background: var(--button-hover-back-color); + border-color: var(--button-hover-border-color); } + +input:disabled, input[disabled], textarea:disabled, textarea[disabled], select:disabled, select[disabled], button:disabled, button[disabled], .button:disabled, .button[disabled], [role="button"]:disabled, [role="button"][disabled] { + cursor: not-allowed; + opacity: 0.75; } + +.button-group { + display: flex; + border: 0.0714285714rem solid var(--button-group-border-color); + border-radius: var(--universal-border-radius); + margin: var(--universal-margin); } + .button-group > button, .button-group [type="button"], .button-group > [type="submit"], .button-group > [type="reset"], .button-group > .button, .button-group > [role="button"] { + margin: 0; + max-width: 100%; + flex: 1 1 auto; + text-align: center; + border: 0; + border-radius: 0; + box-shadow: none; } + .button-group > :not(:first-child) { + border-left: 0.0714285714rem solid var(--button-group-border-color); } + @media screen and (max-width: 499px) { + .button-group { + flex-direction: column; } + .button-group > :not(:first-child) { + border: 0; + border-top: 0.0714285714rem solid var(--button-group-border-color); } } + +/* + Custom elements for forms and input elements. +*/ +button.primary, [type="button"].primary, [type="submit"].primary, [type="reset"].primary, .button.primary, [role="button"].primary { + --button-back-color: #1976d2; + --button-fore-color: #f8f8f8; } + button.primary:hover, button.primary:focus, [type="button"].primary:hover, [type="button"].primary:focus, [type="submit"].primary:hover, [type="submit"].primary:focus, [type="reset"].primary:hover, [type="reset"].primary:focus, .button.primary:hover, .button.primary:focus, [role="button"].primary:hover, [role="button"].primary:focus { + --button-hover-back-color: #1565c0; } + +button.secondary, [type="button"].secondary, [type="submit"].secondary, [type="reset"].secondary, .button.secondary, [role="button"].secondary { + --button-back-color: #d32f2f; + --button-fore-color: #f8f8f8; } + button.secondary:hover, button.secondary:focus, [type="button"].secondary:hover, [type="button"].secondary:focus, [type="submit"].secondary:hover, [type="submit"].secondary:focus, [type="reset"].secondary:hover, [type="reset"].secondary:focus, .button.secondary:hover, .button.secondary:focus, [role="button"].secondary:hover, [role="button"].secondary:focus { + --button-hover-back-color: #c62828; } + +button.tertiary, [type="button"].tertiary, [type="submit"].tertiary, [type="reset"].tertiary, .button.tertiary, [role="button"].tertiary { + --button-back-color: #308732; + --button-fore-color: #f8f8f8; } + button.tertiary:hover, button.tertiary:focus, [type="button"].tertiary:hover, [type="button"].tertiary:focus, [type="submit"].tertiary:hover, [type="submit"].tertiary:focus, [type="reset"].tertiary:hover, [type="reset"].tertiary:focus, .button.tertiary:hover, .button.tertiary:focus, [role="button"].tertiary:hover, [role="button"].tertiary:focus { + --button-hover-back-color: #277529; } + +button.inverse, [type="button"].inverse, [type="submit"].inverse, [type="reset"].inverse, .button.inverse, [role="button"].inverse { + --button-back-color: #212121; + --button-fore-color: #f8f8f8; } + button.inverse:hover, button.inverse:focus, [type="button"].inverse:hover, [type="button"].inverse:focus, [type="submit"].inverse:hover, [type="submit"].inverse:focus, [type="reset"].inverse:hover, [type="reset"].inverse:focus, .button.inverse:hover, .button.inverse:focus, [role="button"].inverse:hover, [role="button"].inverse:focus { + --button-hover-back-color: #111; } + +button.small, [type="button"].small, [type="submit"].small, [type="reset"].small, .button.small, [role="button"].small { + padding: calc(0.5 * var(--universal-padding)) calc(0.75 * var(--universal-padding)); + margin: var(--universal-margin); } + +button.large, [type="button"].large, [type="submit"].large, [type="reset"].large, .button.large, [role="button"].large { + padding: calc(1.5 * var(--universal-padding)) calc(2 * var(--universal-padding)); + margin: var(--universal-margin); } + +/* + Definitions for navigation elements. +*/ +/* Navigation module CSS variable definitions */ +:root { + --header-back-color: #03234b; + --header-hover-back-color: #ffd200; + --header-fore-color: #ffffff; + --header-border-color: #3cb4e6; + --nav-back-color: #ffffff; + --nav-hover-back-color: #ffe97f; + --nav-fore-color: #e6007e; + --nav-border-color: #3cb4e6; + --nav-link-color: #3cb4e6; + --footer-fore-color: #ffffff; + --footer-back-color: #03234b; + --footer-border-color: #3cb4e6; + --footer-link-color: #3cb4e6; + --drawer-back-color: #ffffff; + --drawer-hover-back-color: #ffe97f; + --drawer-border-color: #3cb4e6; + --drawer-close-color: #e6007e; } + +header { + height: 2.75rem; + background: var(--header-back-color); + color: var(--header-fore-color); + border-bottom: 0.0714285714rem solid var(--header-border-color); + padding: calc(var(--universal-padding) / 4) 0; + white-space: nowrap; + overflow-x: auto; + overflow-y: hidden; } + header.row { + box-sizing: content-box; } + header .logo { + color: var(--header-fore-color); + font-size: 1.75rem; + padding: var(--universal-padding) calc(2 * var(--universal-padding)); + text-decoration: none; } + header button, header [type="button"], header .button, header [role="button"] { + box-sizing: border-box; + position: relative; + top: calc(0rem - var(--universal-padding) / 4); + height: calc(3.1875rem + var(--universal-padding) / 2); + background: var(--header-back-color); + line-height: calc(3.1875rem - var(--universal-padding) * 1.5); + text-align: center; + color: var(--header-fore-color); + border: 0; + border-radius: 0; + margin: 0; + text-transform: uppercase; } + header button:hover, header button:focus, header [type="button"]:hover, header [type="button"]:focus, header .button:hover, header .button:focus, header [role="button"]:hover, header [role="button"]:focus { + background: var(--header-hover-back-color); } + +nav { + background: var(--nav-back-color); + color: var(--nav-fore-color); + border: 0.0714285714rem solid var(--nav-border-color); + border-radius: var(--universal-border-radius); + margin: var(--universal-margin); } + nav * { + padding: var(--universal-padding) calc(1.5 * var(--universal-padding)); } + nav a, nav a:visited { + display: block; + color: var(--nav-link-color); + border-radius: var(--universal-border-radius); + transition: background 0.3s; } + nav a:hover, nav a:focus, nav a:visited:hover, nav a:visited:focus { + text-decoration: none; + background: var(--nav-hover-back-color); } + nav .sublink-1 { + position: relative; + margin-left: calc(2 * var(--universal-padding)); } + nav .sublink-1:before { + position: absolute; + left: calc(var(--universal-padding) - 1 * var(--universal-padding)); + top: -0.0714285714rem; + content: ''; + height: 100%; + border: 0.0714285714rem solid var(--nav-border-color); + border-left: 0; } + nav .sublink-2 { + position: relative; + margin-left: calc(4 * var(--universal-padding)); } + nav .sublink-2:before { + position: absolute; + left: calc(var(--universal-padding) - 3 * var(--universal-padding)); + top: -0.0714285714rem; + content: ''; + height: 100%; + border: 0.0714285714rem solid var(--nav-border-color); + border-left: 0; } + +footer { + background: var(--footer-back-color); + color: var(--footer-fore-color); + border-top: 0.0714285714rem solid var(--footer-border-color); + padding: calc(2 * var(--universal-padding)) var(--universal-padding); + font-size: 0.875rem; } + footer a, footer a:visited { + color: var(--footer-link-color); } + +header.sticky { + position: -webkit-sticky; + position: sticky; + z-index: 1101; + top: 0; } + +footer.sticky { + position: -webkit-sticky; + position: sticky; + z-index: 1101; + bottom: 0; } + +.drawer-toggle:before { + display: inline-block; + position: relative; + vertical-align: bottom; + content: '\00a0\2261\00a0'; + font-family: sans-serif; + font-size: 1.5em; } +@media screen and (min-width: 500px) { + .drawer-toggle:not(.persistent) { + display: none; } } + +[type="checkbox"].drawer { + height: 1px; + width: 1px; + margin: -1px; + overflow: hidden; + position: absolute; + clip: rect(0 0 0 0); + -webkit-clip-path: inset(100%); + clip-path: inset(100%); } + [type="checkbox"].drawer + * { + display: block; + box-sizing: border-box; + position: fixed; + top: 0; + width: 320px; + height: 100vh; + overflow-y: auto; + background: var(--drawer-back-color); + border: 0.0714285714rem solid var(--drawer-border-color); + border-radius: 0; + margin: 0; + z-index: 1110; + right: -320px; + transition: right 0.3s; } + [type="checkbox"].drawer + * .drawer-close { + position: absolute; + top: var(--universal-margin); + right: var(--universal-margin); + z-index: 1111; + width: 2rem; + height: 2rem; + border-radius: var(--universal-border-radius); + padding: var(--universal-padding); + margin: 0; + cursor: pointer; + transition: background 0.3s; } + [type="checkbox"].drawer + * .drawer-close:before { + display: block; + content: '\00D7'; + color: var(--drawer-close-color); + position: relative; + font-family: sans-serif; + font-size: 2rem; + line-height: 1; + text-align: center; } + [type="checkbox"].drawer + * .drawer-close:hover, [type="checkbox"].drawer + * .drawer-close:focus { + background: var(--drawer-hover-back-color); } + @media screen and (max-width: 320px) { + [type="checkbox"].drawer + * { + width: 100%; } } + [type="checkbox"].drawer:checked + * { + right: 0; } + @media screen and (min-width: 500px) { + [type="checkbox"].drawer:not(.persistent) + * { + position: static; + height: 100%; + z-index: 1100; } + [type="checkbox"].drawer:not(.persistent) + * .drawer-close { + display: none; } } + +/* + Definitions for the responsive table component. +*/ +/* Table module CSS variable definitions. */ +:root { + --table-border-color: #03234b; + --table-border-separator-color: #03234b; + --table-head-back-color: #03234b; + --table-head-fore-color: #ffffff; + --table-body-back-color: #ffffff; + --table-body-fore-color: #03234b; + --table-body-alt-back-color: #f4f4f4; } + +table { + border-collapse: separate; + border-spacing: 0; + margin: 0; + display: flex; + flex: 0 1 auto; + flex-flow: row wrap; + padding: var(--universal-padding); + padding-top: 0; } + table caption { + font-size: 1rem; + margin: calc(2 * var(--universal-margin)) 0; + max-width: 100%; + flex: 0 0 100%; } + table thead, table tbody { + display: flex; + flex-flow: row wrap; + border: 0.0714285714rem solid var(--table-border-color); } + table thead { + z-index: 999; + border-radius: var(--universal-border-radius) var(--universal-border-radius) 0 0; + border-bottom: 0.0714285714rem solid var(--table-border-separator-color); } + table tbody { + border-top: 0; + margin-top: calc(0 - var(--universal-margin)); + border-radius: 0 0 var(--universal-border-radius) var(--universal-border-radius); } + table tr { + display: flex; + padding: 0; } + table th, table td { + padding: calc(0.5 * var(--universal-padding)); + font-size: 0.9rem; } + table th { + text-align: left; + background: var(--table-head-back-color); + color: var(--table-head-fore-color); } + table td { + background: var(--table-body-back-color); + color: var(--table-body-fore-color); + border-top: 0.0714285714rem solid var(--table-border-color); } + +table:not(.horizontal) { + overflow: auto; + max-height: 100%; } + table:not(.horizontal) thead, table:not(.horizontal) tbody { + max-width: 100%; + flex: 0 0 100%; } + table:not(.horizontal) tr { + flex-flow: row wrap; + flex: 0 0 100%; } + table:not(.horizontal) th, table:not(.horizontal) td { + flex: 1 0 0%; + overflow: hidden; + text-overflow: ellipsis; } + table:not(.horizontal) thead { + position: sticky; + top: 0; } + table:not(.horizontal) tbody tr:first-child td { + border-top: 0; } + +table.horizontal { + border: 0; } + table.horizontal thead, table.horizontal tbody { + border: 0; + flex: .2 0 0; + flex-flow: row nowrap; } + table.horizontal tbody { + overflow: auto; + justify-content: space-between; + flex: .8 0 0; + margin-left: 0; + padding-bottom: calc(var(--universal-padding) / 4); } + table.horizontal tr { + flex-direction: column; + flex: 1 0 auto; } + table.horizontal th, table.horizontal td { + width: auto; + border: 0; + border-bottom: 0.0714285714rem solid var(--table-border-color); } + table.horizontal th:not(:first-child), table.horizontal td:not(:first-child) { + border-top: 0; } + table.horizontal th { + text-align: right; + border-left: 0.0714285714rem solid var(--table-border-color); + border-right: 0.0714285714rem solid var(--table-border-separator-color); } + table.horizontal thead tr:first-child { + padding-left: 0; } + table.horizontal th:first-child, table.horizontal td:first-child { + border-top: 0.0714285714rem solid var(--table-border-color); } + table.horizontal tbody tr:last-child td { + border-right: 0.0714285714rem solid var(--table-border-color); } + table.horizontal tbody tr:last-child td:first-child { + border-top-right-radius: 0.25rem; } + table.horizontal tbody tr:last-child td:last-child { + border-bottom-right-radius: 0.25rem; } + table.horizontal thead tr:first-child th:first-child { + border-top-left-radius: 0.25rem; } + table.horizontal thead tr:first-child th:last-child { + border-bottom-left-radius: 0.25rem; } + +@media screen and (max-width: 499px) { + table, table.horizontal { + border-collapse: collapse; + border: 0; + width: 100%; + display: table; } + table thead, table th, table.horizontal thead, table.horizontal th { + border: 0; + height: 1px; + width: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + clip: rect(0 0 0 0); + -webkit-clip-path: inset(100%); + clip-path: inset(100%); } + table tbody, table.horizontal tbody { + border: 0; + display: table-row-group; } + table tr, table.horizontal tr { + display: block; + border: 0.0714285714rem solid var(--table-border-color); + border-radius: var(--universal-border-radius); + background: #ffffff; + padding: var(--universal-padding); + margin: var(--universal-margin); + margin-bottom: calc(1 * var(--universal-margin)); } + table th, table td, table.horizontal th, table.horizontal td { + width: auto; } + table td, table.horizontal td { + display: block; + border: 0; + text-align: right; } + table td:before, table.horizontal td:before { + content: attr(data-label); + float: left; + font-weight: 600; } + table th:first-child, table td:first-child, table.horizontal th:first-child, table.horizontal td:first-child { + border-top: 0; } + table tbody tr:last-child td, table.horizontal tbody tr:last-child td { + border-right: 0; } } +table tr:nth-of-type(2n) > td { + background: var(--table-body-alt-back-color); } + +@media screen and (max-width: 500px) { + table tr:nth-of-type(2n) { + background: var(--table-body-alt-back-color); } } +:root { + --table-body-hover-back-color: #90caf9; } + +table.hoverable tr:hover, table.hoverable tr:hover > td, table.hoverable tr:focus, table.hoverable tr:focus > td { + background: var(--table-body-hover-back-color); } + +@media screen and (max-width: 500px) { + table.hoverable tr:hover, table.hoverable tr:hover > td, table.hoverable tr:focus, table.hoverable tr:focus > td { + background: var(--table-body-hover-back-color); } } +/* + Definitions for contextual background elements, toasts and tooltips. +*/ +/* Contextual module CSS variable definitions */ +:root { + --mark-back-color: #3cb4e6; + --mark-fore-color: #ffffff; } + +mark { + background: var(--mark-back-color); + color: var(--mark-fore-color); + font-size: 0.95em; + line-height: 1em; + border-radius: var(--universal-border-radius); + padding: calc(var(--universal-padding) / 4) var(--universal-padding); } + mark.inline-block { + display: inline-block; + font-size: 1em; + line-height: 1.4; + padding: calc(var(--universal-padding) / 2) var(--universal-padding); } + +:root { + --toast-back-color: #424242; + --toast-fore-color: #fafafa; } + +.toast { + position: fixed; + bottom: calc(var(--universal-margin) * 3); + left: 50%; + transform: translate(-50%, -50%); + z-index: 1111; + color: var(--toast-fore-color); + background: var(--toast-back-color); + border-radius: calc(var(--universal-border-radius) * 16); + padding: var(--universal-padding) calc(var(--universal-padding) * 3); } + +:root { + --tooltip-back-color: #212121; + --tooltip-fore-color: #fafafa; } + +.tooltip { + position: relative; + display: inline-block; } + .tooltip:before, .tooltip:after { + position: absolute; + opacity: 0; + clip: rect(0 0 0 0); + -webkit-clip-path: inset(100%); + clip-path: inset(100%); + transition: all 0.3s; + z-index: 1010; + left: 50%; } + .tooltip:not(.bottom):before, .tooltip:not(.bottom):after { + bottom: 75%; } + .tooltip.bottom:before, .tooltip.bottom:after { + top: 75%; } + .tooltip:hover:before, .tooltip:hover:after, .tooltip:focus:before, .tooltip:focus:after { + opacity: 1; + clip: auto; + -webkit-clip-path: inset(0%); + clip-path: inset(0%); } + .tooltip:before { + content: ''; + background: transparent; + border: var(--universal-margin) solid transparent; + left: calc(50% - var(--universal-margin)); } + .tooltip:not(.bottom):before { + border-top-color: #212121; } + .tooltip.bottom:before { + border-bottom-color: #212121; } + .tooltip:after { + content: attr(aria-label); + color: var(--tooltip-fore-color); + background: var(--tooltip-back-color); + border-radius: var(--universal-border-radius); + padding: var(--universal-padding); + white-space: nowrap; + transform: translateX(-50%); } + .tooltip:not(.bottom):after { + margin-bottom: calc(2 * var(--universal-margin)); } + .tooltip.bottom:after { + margin-top: calc(2 * var(--universal-margin)); } + +:root { + --modal-overlay-color: rgba(0, 0, 0, 0.45); + --modal-close-color: #e6007e; + --modal-close-hover-color: #ffe97f; } + +[type="checkbox"].modal { + height: 1px; + width: 1px; + margin: -1px; + overflow: hidden; + position: absolute; + clip: rect(0 0 0 0); + -webkit-clip-path: inset(100%); + clip-path: inset(100%); } + [type="checkbox"].modal + div { + position: fixed; + top: 0; + left: 0; + display: none; + width: 100vw; + height: 100vh; + background: var(--modal-overlay-color); } + [type="checkbox"].modal + div .card { + margin: 0 auto; + max-height: 50vh; + overflow: auto; } + [type="checkbox"].modal + div .card .modal-close { + position: absolute; + top: 0; + right: 0; + width: 1.75rem; + height: 1.75rem; + border-radius: var(--universal-border-radius); + padding: var(--universal-padding); + margin: 0; + cursor: pointer; + transition: background 0.3s; } + [type="checkbox"].modal + div .card .modal-close:before { + display: block; + content: '\00D7'; + color: var(--modal-close-color); + position: relative; + font-family: sans-serif; + font-size: 1.75rem; + line-height: 1; + text-align: center; } + [type="checkbox"].modal + div .card .modal-close:hover, [type="checkbox"].modal + div .card .modal-close:focus { + background: var(--modal-close-hover-color); } + [type="checkbox"].modal:checked + div { + display: flex; + flex: 0 1 auto; + z-index: 1200; } + [type="checkbox"].modal:checked + div .card .modal-close { + z-index: 1211; } + +:root { + --collapse-label-back-color: #03234b; + --collapse-label-fore-color: #ffffff; + --collapse-label-hover-back-color: #3cb4e6; + --collapse-selected-label-back-color: #3cb4e6; + --collapse-border-color: var(--collapse-label-back-color); + --collapse-selected-border-color: #ceecf8; + --collapse-content-back-color: #ffffff; + --collapse-selected-label-border-color: #3cb4e6; } + +.collapse { + width: calc(100% - 2 * var(--universal-margin)); + opacity: 1; + display: flex; + flex-direction: column; + margin: var(--universal-margin); + border-radius: var(--universal-border-radius); } + .collapse > [type="radio"], .collapse > [type="checkbox"] { + height: 1px; + width: 1px; + margin: -1px; + overflow: hidden; + position: absolute; + clip: rect(0 0 0 0); + -webkit-clip-path: inset(100%); + clip-path: inset(100%); } + .collapse > label { + flex-grow: 1; + display: inline-block; + height: 1.25rem; + cursor: pointer; + transition: background 0.2s; + color: var(--collapse-label-fore-color); + background: var(--collapse-label-back-color); + border: 0.0714285714rem solid var(--collapse-selected-border-color); + padding: calc(1.25 * var(--universal-padding)); } + .collapse > label:hover, .collapse > label:focus { + background: var(--collapse-label-hover-back-color); } + .collapse > label + div { + flex-basis: auto; + height: 1px; + width: 1px; + margin: -1px; + overflow: hidden; + position: absolute; + clip: rect(0 0 0 0); + -webkit-clip-path: inset(100%); + clip-path: inset(100%); + transition: max-height 0.3s; + max-height: 1px; } + .collapse > :checked + label { + background: var(--collapse-selected-label-back-color); + border-color: var(--collapse-selected-label-border-color); } + .collapse > :checked + label + div { + box-sizing: border-box; + position: relative; + width: 100%; + height: auto; + overflow: auto; + margin: 0; + background: var(--collapse-content-back-color); + border: 0.0714285714rem solid var(--collapse-selected-border-color); + border-top: 0; + padding: var(--universal-padding); + clip: auto; + -webkit-clip-path: inset(0%); + clip-path: inset(0%); + max-height: 100%; } + .collapse > label:not(:first-of-type) { + border-top: 0; } + .collapse > label:first-of-type { + border-radius: var(--universal-border-radius) var(--universal-border-radius) 0 0; } + .collapse > label:last-of-type:not(:first-of-type) { + border-radius: 0 0 var(--universal-border-radius) var(--universal-border-radius); } + .collapse > label:last-of-type:first-of-type { + border-radius: var(--universal-border-radius); } + .collapse > :checked:last-of-type:not(:first-of-type) + label { + border-radius: 0; } + .collapse > :checked:last-of-type + label + div { + border-radius: 0 0 var(--universal-border-radius) var(--universal-border-radius); } + +/* + Custom elements for contextual background elements, toasts and tooltips. +*/ +mark.tertiary { + --mark-back-color: #3cb4e6; } + +mark.tag { + padding: calc(var(--universal-padding)/2) var(--universal-padding); + border-radius: 1em; } + +/* + Definitions for progress elements and spinners. +*/ +/* Progress module CSS variable definitions */ +:root { + --progress-back-color: #3cb4e6; + --progress-fore-color: #555; } + +progress { + display: block; + vertical-align: baseline; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + height: 0.75rem; + width: calc(100% - 2 * var(--universal-margin)); + margin: var(--universal-margin); + border: 0; + border-radius: calc(2 * var(--universal-border-radius)); + background: var(--progress-back-color); + color: var(--progress-fore-color); } + progress::-webkit-progress-value { + background: var(--progress-fore-color); + border-top-left-radius: calc(2 * var(--universal-border-radius)); + border-bottom-left-radius: calc(2 * var(--universal-border-radius)); } + progress::-webkit-progress-bar { + background: var(--progress-back-color); } + progress::-moz-progress-bar { + background: var(--progress-fore-color); + border-top-left-radius: calc(2 * var(--universal-border-radius)); + border-bottom-left-radius: calc(2 * var(--universal-border-radius)); } + progress[value="1000"]::-webkit-progress-value { + border-radius: calc(2 * var(--universal-border-radius)); } + progress[value="1000"]::-moz-progress-bar { + border-radius: calc(2 * var(--universal-border-radius)); } + progress.inline { + display: inline-block; + vertical-align: middle; + width: 60%; } + +:root { + --spinner-back-color: #ddd; + --spinner-fore-color: #555; } + +@keyframes spinner-donut-anim { + 0% { + transform: rotate(0deg); } + 100% { + transform: rotate(360deg); } } +.spinner { + display: inline-block; + margin: var(--universal-margin); + border: 0.25rem solid var(--spinner-back-color); + border-left: 0.25rem solid var(--spinner-fore-color); + border-radius: 50%; + width: 1.25rem; + height: 1.25rem; + animation: spinner-donut-anim 1.2s linear infinite; } + +/* + Custom elements for progress bars and spinners. +*/ +progress.primary { + --progress-fore-color: #1976d2; } + +progress.secondary { + --progress-fore-color: #d32f2f; } + +progress.tertiary { + --progress-fore-color: #308732; } + +.spinner.primary { + --spinner-fore-color: #1976d2; } + +.spinner.secondary { + --spinner-fore-color: #d32f2f; } + +.spinner.tertiary { + --spinner-fore-color: #308732; } + +/* + Definitions for icons - powered by Feather (https://feathericons.com/). +*/ +span[class^='icon-'] { + display: inline-block; + height: 1em; + width: 1em; + vertical-align: -0.125em; + background-size: contain; + margin: 0 calc(var(--universal-margin) / 4); } + span[class^='icon-'].secondary { + -webkit-filter: invert(25%); + filter: invert(25%); } + span[class^='icon-'].inverse { + -webkit-filter: invert(100%); + filter: invert(100%); } + +span.icon-alert { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12' y2='16'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-bookmark { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z'%3E%3C/path%3E%3C/svg%3E"); } +span.icon-calendar { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-credit { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='1' y='4' width='22' height='16' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='1' y1='10' x2='23' y2='10'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-edit { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 14.66V20a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h5.34'%3E%3C/path%3E%3Cpolygon points='18 2 22 6 12 16 8 16 8 12 18 2'%3E%3C/polygon%3E%3C/svg%3E"); } +span.icon-link { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6'%3E%3C/path%3E%3Cpolyline points='15 3 21 3 21 9'%3E%3C/polyline%3E%3Cline x1='10' y1='14' x2='21' y2='3'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-help { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3'%3E%3C/path%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='17' x2='12' y2='17'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-home { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z'%3E%3C/path%3E%3Cpolyline points='9 22 9 12 15 12 15 22'%3E%3C/polyline%3E%3C/svg%3E"); } +span.icon-info { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='16' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='8' x2='12' y2='8'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-lock { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='11' width='18' height='11' rx='2' ry='2'%3E%3C/rect%3E%3Cpath d='M7 11V7a5 5 0 0 1 10 0v4'%3E%3C/path%3E%3C/svg%3E"); } +span.icon-mail { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z'%3E%3C/path%3E%3Cpolyline points='22,6 12,13 2,6'%3E%3C/polyline%3E%3C/svg%3E"); } +span.icon-location { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z'%3E%3C/path%3E%3Ccircle cx='12' cy='10' r='3'%3E%3C/circle%3E%3C/svg%3E"); } +span.icon-phone { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z'%3E%3C/path%3E%3C/svg%3E"); } +span.icon-rss { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 11a9 9 0 0 1 9 9'%3E%3C/path%3E%3Cpath d='M4 4a16 16 0 0 1 16 16'%3E%3C/path%3E%3Ccircle cx='5' cy='19' r='1'%3E%3C/circle%3E%3C/svg%3E"); } +span.icon-search { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-settings { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='3'%3E%3C/circle%3E%3Cpath d='M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z'%3E%3C/path%3E%3C/svg%3E"); } +span.icon-share { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='18' cy='5' r='3'%3E%3C/circle%3E%3Ccircle cx='6' cy='12' r='3'%3E%3C/circle%3E%3Ccircle cx='18' cy='19' r='3'%3E%3C/circle%3E%3Cline x1='8.59' y1='13.51' x2='15.42' y2='17.49'%3E%3C/line%3E%3Cline x1='15.41' y1='6.51' x2='8.59' y2='10.49'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-cart { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='9' cy='21' r='1'%3E%3C/circle%3E%3Ccircle cx='20' cy='21' r='1'%3E%3C/circle%3E%3Cpath d='M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6'%3E%3C/path%3E%3C/svg%3E"); } +span.icon-upload { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4'%3E%3C/path%3E%3Cpolyline points='17 8 12 3 7 8'%3E%3C/polyline%3E%3Cline x1='12' y1='3' x2='12' y2='15'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-user { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2'%3E%3C/path%3E%3Ccircle cx='12' cy='7' r='4'%3E%3C/circle%3E%3C/svg%3E"); } + +/* + Definitions for STMicroelectronics icons (https://brandportal.st.com/document/26). +*/ +span.icon-st-update { + background-image: url("Update.svg"); } +span.icon-st-add { + background-image: url("Add button.svg"); } + +/* + Definitions for utilities and helper classes. +*/ +/* Utility module CSS variable definitions */ +:root { + --generic-border-color: rgba(0, 0, 0, 0.3); + --generic-box-shadow: 0 0.2857142857rem 0.2857142857rem 0 rgba(0, 0, 0, 0.125), 0 0.1428571429rem 0.1428571429rem -0.1428571429rem rgba(0, 0, 0, 0.125); } + +.hidden { + display: none !important; } + +.visually-hidden { + position: absolute !important; + width: 1px !important; + height: 1px !important; + margin: -1px !important; + border: 0 !important; + padding: 0 !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(100%) !important; + clip-path: inset(100%) !important; + overflow: hidden !important; } + +.bordered { + border: 0.0714285714rem solid var(--generic-border-color) !important; } + +.rounded { + border-radius: var(--universal-border-radius) !important; } + +.circular { + border-radius: 50% !important; } + +.shadowed { + box-shadow: var(--generic-box-shadow) !important; } + +.responsive-margin { + margin: calc(var(--universal-margin) / 4) !important; } + @media screen and (min-width: 500px) { + .responsive-margin { + margin: calc(var(--universal-margin) / 2) !important; } } + @media screen and (min-width: 1280px) { + .responsive-margin { + margin: var(--universal-margin) !important; } } + +.responsive-padding { + padding: calc(var(--universal-padding) / 4) !important; } + @media screen and (min-width: 500px) { + .responsive-padding { + padding: calc(var(--universal-padding) / 2) !important; } } + @media screen and (min-width: 1280px) { + .responsive-padding { + padding: var(--universal-padding) !important; } } + +@media screen and (max-width: 499px) { + .hidden-sm { + display: none !important; } } +@media screen and (min-width: 500px) and (max-width: 1279px) { + .hidden-md { + display: none !important; } } +@media screen and (min-width: 1280px) { + .hidden-lg { + display: none !important; } } +@media screen and (max-width: 499px) { + .visually-hidden-sm { + position: absolute !important; + width: 1px !important; + height: 1px !important; + margin: -1px !important; + border: 0 !important; + padding: 0 !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(100%) !important; + clip-path: inset(100%) !important; + overflow: hidden !important; } } +@media screen and (min-width: 500px) and (max-width: 1279px) { + .visually-hidden-md { + position: absolute !important; + width: 1px !important; + height: 1px !important; + margin: -1px !important; + border: 0 !important; + padding: 0 !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(100%) !important; + clip-path: inset(100%) !important; + overflow: hidden !important; } } +@media screen and (min-width: 1280px) { + .visually-hidden-lg { + position: absolute !important; + width: 1px !important; + height: 1px !important; + margin: -1px !important; + border: 0 !important; + padding: 0 !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(100%) !important; + clip-path: inset(100%) !important; + overflow: hidden !important; } } + +/*# sourceMappingURL=mini-custom.css.map */ + +img[alt="ST logo"] { display: block; margin: auto; width: 75%; max-width: 250px; min-width: 71px; } +img[alt="Cube logo"] { float: right; width: 30%; max-width: 10rem; min-width: 8rem; padding-right: 1rem;} + +.figure { + display: block; + margin-left: auto; + margin-right: auto; + text-align: center; +} \ No newline at end of file diff --git a/airmouse/lib/lsm6dso-api/_htmresc/st_logo_2020.png b/airmouse/lib/lsm6dso-api/_htmresc/st_logo_2020.png new file mode 100644 index 00000000000..d6cebb5ac70 Binary files /dev/null and b/airmouse/lib/lsm6dso-api/_htmresc/st_logo_2020.png differ diff --git a/airmouse/lib/lsm6dso-api/lsm6dso.c b/airmouse/lib/lsm6dso-api/lsm6dso.c new file mode 100644 index 00000000000..739d67afddf --- /dev/null +++ b/airmouse/lib/lsm6dso-api/lsm6dso.c @@ -0,0 +1,3909 @@ +/** + ****************************************************************************** + * @file lsm6dso.c + * @author MEMS Software Solutions Team + * @brief LSM6DSO driver file + ****************************************************************************** + * @attention + * + * Copyright (c) 2019 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "lsm6dso.h" + +/** @addtogroup BSP BSP + * @{ + */ + +/** @addtogroup Component Component + * @{ + */ + +/** @defgroup LSM6DSO LSM6DSO + * @{ + */ + +/** @defgroup LSM6DSO_Exported_Variables LSM6DSO Exported Variables + * @{ + */ + +LSM6DSO_CommonDrv_t LSM6DSO_COMMON_Driver = +{ + LSM6DSO_Init, + LSM6DSO_DeInit, + LSM6DSO_ReadID, + LSM6DSO_GetCapabilities, +}; + +LSM6DSO_ACC_Drv_t LSM6DSO_ACC_Driver = +{ + LSM6DSO_ACC_Enable, + LSM6DSO_ACC_Disable, + LSM6DSO_ACC_GetSensitivity, + LSM6DSO_ACC_GetOutputDataRate, + LSM6DSO_ACC_SetOutputDataRate, + LSM6DSO_ACC_GetFullScale, + LSM6DSO_ACC_SetFullScale, + LSM6DSO_ACC_GetAxes, + LSM6DSO_ACC_GetAxesRaw, +}; + +LSM6DSO_GYRO_Drv_t LSM6DSO_GYRO_Driver = +{ + LSM6DSO_GYRO_Enable, + LSM6DSO_GYRO_Disable, + LSM6DSO_GYRO_GetSensitivity, + LSM6DSO_GYRO_GetOutputDataRate, + LSM6DSO_GYRO_SetOutputDataRate, + LSM6DSO_GYRO_GetFullScale, + LSM6DSO_GYRO_SetFullScale, + LSM6DSO_GYRO_GetAxes, + LSM6DSO_GYRO_GetAxesRaw, +}; + +/** + * @} + */ + +/** @defgroup LSM6DSO_Private_Function_Prototypes LSM6DSO Private Function Prototypes + * @{ + */ + +static int32_t LSM6DSO_ACC_SetOutputDataRate_When_Enabled(LSM6DSO_Object_t *pObj, float_t Odr); +static int32_t LSM6DSO_ACC_SetOutputDataRate_When_Disabled(LSM6DSO_Object_t *pObj, float_t Odr); +static int32_t LSM6DSO_GYRO_SetOutputDataRate_When_Enabled(LSM6DSO_Object_t *pObj, float_t Odr); +static int32_t LSM6DSO_GYRO_SetOutputDataRate_When_Disabled(LSM6DSO_Object_t *pObj, float_t Odr); +static void LSM6DSO_Delay(LSM6DSO_Object_t *pObj, uint32_t msDelay); +static int32_t ReadRegWrap(void *Handle, uint8_t Reg, uint8_t *pData, uint16_t Length); +static int32_t WriteRegWrap(void *Handle, uint8_t Reg, uint8_t *pData, uint16_t Length); + +/** + * @} + */ + +/** @defgroup LSM6DSO_Exported_Functions LSM6DSO Exported Functions + * @{ + */ + +/** + * @brief Register Component Bus IO operations + * @param pObj the device pObj + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_RegisterBusIO(LSM6DSO_Object_t *pObj, LSM6DSO_IO_t *pIO) +{ + int32_t ret = LSM6DSO_OK; + + if (pObj == NULL) + { + ret = LSM6DSO_ERROR; + } + else + { + pObj->IO.Init = pIO->Init; + pObj->IO.DeInit = pIO->DeInit; + pObj->IO.BusType = pIO->BusType; + pObj->IO.Address = pIO->Address; + pObj->IO.WriteReg = pIO->WriteReg; + pObj->IO.ReadReg = pIO->ReadReg; + pObj->IO.GetTick = pIO->GetTick; + + pObj->Ctx.read_reg = ReadRegWrap; + pObj->Ctx.write_reg = WriteRegWrap; + pObj->Ctx.mdelay = pIO->Delay; + pObj->Ctx.handle = pObj; + + if (pObj->IO.Init == NULL) + { + ret = LSM6DSO_ERROR; + } + else if (pObj->IO.Init() != LSM6DSO_OK) + { + ret = LSM6DSO_ERROR; + } + else + { + if (pObj->IO.BusType == LSM6DSO_SPI_3WIRES_BUS) /* SPI 3-Wires */ + { + /* Enable the SPI 3-Wires support only the first time */ + if (pObj->is_initialized == 0U) + { + /* Enable SPI 3-Wires on the component */ + uint8_t data = 0x0C; + + if (LSM6DSO_Write_Reg(pObj, LSM6DSO_CTRL3_C, data) != LSM6DSO_OK) + { + ret = LSM6DSO_ERROR; + } + } + } + } + } + + return ret; +} + +/** + * @brief Initialize the LSM6DSO sensor + * @param pObj the device pObj + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_Init(LSM6DSO_Object_t *pObj) +{ + /* Disable I3C */ + if (lsm6dso_i3c_disable_set(&(pObj->Ctx), LSM6DSO_I3C_DISABLE) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Enable register address automatically incremented during a multiple byte + access with a serial interface. */ + if (lsm6dso_auto_increment_set(&(pObj->Ctx), PROPERTY_ENABLE) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Enable BDU */ + if (lsm6dso_block_data_update_set(&(pObj->Ctx), PROPERTY_ENABLE) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* FIFO mode selection */ + if (lsm6dso_fifo_mode_set(&(pObj->Ctx), LSM6DSO_BYPASS_MODE) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Select default output data rate. */ + pObj->acc_odr = LSM6DSO_XL_ODR_104Hz; + + /* Output data rate selection - power down. */ + if (lsm6dso_xl_data_rate_set(&(pObj->Ctx), LSM6DSO_XL_ODR_OFF) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Full scale selection. */ + if (lsm6dso_xl_full_scale_set(&(pObj->Ctx), LSM6DSO_2g) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Select default output data rate. */ + pObj->gyro_odr = LSM6DSO_GY_ODR_104Hz; + + /* Output data rate selection - power down. */ + if (lsm6dso_gy_data_rate_set(&(pObj->Ctx), LSM6DSO_GY_ODR_OFF) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Full scale selection. */ + if (lsm6dso_gy_full_scale_set(&(pObj->Ctx), LSM6DSO_2000dps) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + pObj->is_initialized = 1; + + return LSM6DSO_OK; +} + +/** + * @brief Deinitialize the LSM6DSO sensor + * @param pObj the device pObj + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_DeInit(LSM6DSO_Object_t *pObj) +{ + /* Disable the component */ + if (LSM6DSO_ACC_Disable(pObj) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + if (LSM6DSO_GYRO_Disable(pObj) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Reset output data rate. */ + pObj->acc_odr = LSM6DSO_XL_ODR_OFF; + pObj->gyro_odr = LSM6DSO_GY_ODR_OFF; + + pObj->is_initialized = 0; + + return LSM6DSO_OK; +} + +/** + * @brief Read component ID + * @param pObj the device pObj + * @param Id the WHO_AM_I value + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ReadID(LSM6DSO_Object_t *pObj, uint8_t *Id) +{ + if (lsm6dso_device_id_get(&(pObj->Ctx), Id) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Get LSM6DSO sensor capabilities + * @param pObj Component object pointer + * @param Capabilities pointer to LSM6DSO sensor capabilities + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_GetCapabilities(LSM6DSO_Object_t *pObj, LSM6DSO_Capabilities_t *Capabilities) +{ + /* Prevent unused argument(s) compilation warning */ + (void)(pObj); + + Capabilities->Acc = 1; + Capabilities->Gyro = 1; + Capabilities->Magneto = 0; + Capabilities->LowPower = 0; + Capabilities->GyroMaxFS = 2000; + Capabilities->AccMaxFS = 16; + Capabilities->MagMaxFS = 0; + Capabilities->GyroMaxOdr = 6660.0f; + Capabilities->AccMaxOdr = 6660.0f; + Capabilities->MagMaxOdr = 0.0f; + return LSM6DSO_OK; +} + +/** + * @brief Enable the LSM6DSO accelerometer sensor + * @param pObj the device pObj + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Enable(LSM6DSO_Object_t *pObj) +{ + /* Check if the component is already enabled */ + if (pObj->acc_is_enabled == 1U) + { + return LSM6DSO_OK; + } + + /* Output data rate selection. */ + if (lsm6dso_xl_data_rate_set(&(pObj->Ctx), pObj->acc_odr) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + pObj->acc_is_enabled = 1; + + return LSM6DSO_OK; +} + +/** + * @brief Disable the LSM6DSO accelerometer sensor + * @param pObj the device pObj + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Disable(LSM6DSO_Object_t *pObj) +{ + /* Check if the component is already disabled */ + if (pObj->acc_is_enabled == 0U) + { + return LSM6DSO_OK; + } + + /* Get current output data rate. */ + if (lsm6dso_xl_data_rate_get(&(pObj->Ctx), &pObj->acc_odr) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Output data rate selection - power down. */ + if (lsm6dso_xl_data_rate_set(&(pObj->Ctx), LSM6DSO_XL_ODR_OFF) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + pObj->acc_is_enabled = 0; + + return LSM6DSO_OK; +} + +/** + * @brief Get the LSM6DSO accelerometer sensor sensitivity + * @param pObj the device pObj + * @param Sensitivity pointer + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_GetSensitivity(LSM6DSO_Object_t *pObj, float_t *Sensitivity) +{ + int32_t ret = LSM6DSO_OK; + lsm6dso_fs_xl_t full_scale; + + /* Read actual full scale selection from sensor. */ + if (lsm6dso_xl_full_scale_get(&(pObj->Ctx), &full_scale) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Store the Sensitivity based on actual full scale. */ + switch (full_scale) + { + case LSM6DSO_2g: + *Sensitivity = LSM6DSO_ACC_SENSITIVITY_FS_2G; + break; + + case LSM6DSO_4g: + *Sensitivity = LSM6DSO_ACC_SENSITIVITY_FS_4G; + break; + + case LSM6DSO_8g: + *Sensitivity = LSM6DSO_ACC_SENSITIVITY_FS_8G; + break; + + case LSM6DSO_16g: + *Sensitivity = LSM6DSO_ACC_SENSITIVITY_FS_16G; + break; + + default: + ret = LSM6DSO_ERROR; + break; + } + + return ret; +} + +/** + * @brief Get the LSM6DSO accelerometer sensor output data rate + * @param pObj the device pObj + * @param Odr pointer where the output data rate is written + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_GetOutputDataRate(LSM6DSO_Object_t *pObj, float_t *Odr) +{ + int32_t ret = LSM6DSO_OK; + lsm6dso_odr_xl_t odr_low_level; + + /* Get current output data rate. */ + if (lsm6dso_xl_data_rate_get(&(pObj->Ctx), &odr_low_level) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + switch (odr_low_level) + { + case LSM6DSO_XL_ODR_OFF: + *Odr = 0.0f; + break; + + case LSM6DSO_XL_ODR_1Hz6: + *Odr = 1.6f; + break; + + case LSM6DSO_XL_ODR_12Hz5: + *Odr = 12.5f; + break; + + case LSM6DSO_XL_ODR_26Hz: + *Odr = 26.0f; + break; + + case LSM6DSO_XL_ODR_52Hz: + *Odr = 52.0f; + break; + + case LSM6DSO_XL_ODR_104Hz: + *Odr = 104.0f; + break; + + case LSM6DSO_XL_ODR_208Hz: + *Odr = 208.0f; + break; + + case LSM6DSO_XL_ODR_417Hz: + *Odr = 417.0f; + break; + + case LSM6DSO_XL_ODR_833Hz: + *Odr = 833.0f; + break; + + case LSM6DSO_XL_ODR_1667Hz: + *Odr = 1667.0f; + break; + + case LSM6DSO_XL_ODR_3333Hz: + *Odr = 3333.0f; + break; + + case LSM6DSO_XL_ODR_6667Hz: + *Odr = 6667.0f; + break; + + default: + ret = LSM6DSO_ERROR; + break; + } + + return ret; +} + +/** + * @brief Set the LSM6DSO accelerometer sensor output data rate + * @param pObj the device pObj + * @param Odr the output data rate value to be set + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_SetOutputDataRate(LSM6DSO_Object_t *pObj, float_t Odr) +{ + return LSM6DSO_ACC_SetOutputDataRate_With_Mode(pObj, Odr, LSM6DSO_ACC_HIGH_PERFORMANCE_MODE); +} + +/** + * @brief Set the LSM6DSO accelerometer sensor output data rate with operating mode + * @param pObj the device pObj + * @param Odr the output data rate value to be set + * @param Mode the accelerometer operating mode + * @note This function switches off the gyroscope if Ultra Low Power Mode is set + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_SetOutputDataRate_With_Mode(LSM6DSO_Object_t *pObj, float_t Odr, LSM6DSO_ACC_Operating_Mode_t Mode) +{ + int32_t ret = LSM6DSO_OK; + float_t newOdr = Odr; + + switch (Mode) + { + case LSM6DSO_ACC_HIGH_PERFORMANCE_MODE: + { + /* We must uncheck Low Power and Ultra Low Power bits if they are enabled */ + lsm6dso_ctrl5_c_t val1; + lsm6dso_ctrl6_c_t val2; + + if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_CTRL5_C, (uint8_t *)&val1, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + if (val1.xl_ulp_en != 0U) + { + /* Power off the accelerometer */ + if (pObj->acc_is_enabled == 1U) + { + if (lsm6dso_xl_data_rate_set(&(pObj->Ctx), LSM6DSO_XL_ODR_OFF) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + } + + val1.xl_ulp_en = 0; + if (lsm6dso_write_reg(&(pObj->Ctx), LSM6DSO_CTRL5_C, (uint8_t *)&val1, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + } + + if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_CTRL6_C, (uint8_t *)&val2, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + if (val2.xl_hm_mode != 0U) + { + val2.xl_hm_mode = 0U; + if (lsm6dso_write_reg(&(pObj->Ctx), LSM6DSO_CTRL6_C, (uint8_t *)&val2, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + } + + /* ODR should be at least 12.5Hz */ + if (newOdr < 12.5f) + { + newOdr = 12.5f; + } + break; + } + case LSM6DSO_ACC_LOW_POWER_NORMAL_MODE: + { + /* We must uncheck Ultra Low Power bit if it is enabled */ + /* and check the Low Power bit if it is unchecked */ + lsm6dso_ctrl5_c_t val1; + lsm6dso_ctrl6_c_t val2; + + if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_CTRL5_C, (uint8_t *)&val1, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + if (val1.xl_ulp_en != 0U) + { + /* Power off the accelerometer */ + if (pObj->acc_is_enabled == 1U) + { + if (lsm6dso_xl_data_rate_set(&(pObj->Ctx), LSM6DSO_XL_ODR_OFF) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + } + + val1.xl_ulp_en = 0; + if (lsm6dso_write_reg(&(pObj->Ctx), LSM6DSO_CTRL5_C, (uint8_t *)&val1, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + } + + if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_CTRL6_C, (uint8_t *)&val2, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + if (val2.xl_hm_mode == 0U) + { + val2.xl_hm_mode = 1U; + if (lsm6dso_write_reg(&(pObj->Ctx), LSM6DSO_CTRL6_C, (uint8_t *)&val2, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + } + + /* Now we need to limit the ODR to 208 Hz if it is higher */ + if (newOdr > 208.0f) + { + newOdr = 208.0f; + } + break; + } + case LSM6DSO_ACC_ULTRA_LOW_POWER_MODE: + { + /* We must uncheck Low Power bit if it is enabled */ + /* and check the Ultra Low Power bit if it is unchecked */ + /* We must switch off gyro otherwise Ultra Low Power does not work */ + lsm6dso_ctrl5_c_t val1; + lsm6dso_ctrl6_c_t val2; + + if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_CTRL6_C, (uint8_t *)&val2, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + if (val2.xl_hm_mode != 0U) + { + val2.xl_hm_mode = 0U; + if (lsm6dso_write_reg(&(pObj->Ctx), LSM6DSO_CTRL6_C, (uint8_t *)&val2, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + } + + /* Disable Gyro */ + if (pObj->gyro_is_enabled == 1U) + { + if (LSM6DSO_GYRO_Disable(pObj) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + } + + if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_CTRL5_C, (uint8_t *)&val1, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + if (val1.xl_ulp_en == 0U) + { + /* Power off the accelerometer */ + if (pObj->acc_is_enabled == 1U) + { + if (lsm6dso_xl_data_rate_set(&(pObj->Ctx), LSM6DSO_XL_ODR_OFF) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + } + + val1.xl_ulp_en = 1U; + if (lsm6dso_write_reg(&(pObj->Ctx), LSM6DSO_CTRL5_C, (uint8_t *)&val1, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + } + + /* Now we need to limit the ODR to 208 Hz if it is higher */ + if (newOdr > 208.0f) + { + newOdr = 208.0f; + } + break; + } + default: + ret = LSM6DSO_ERROR; + break; + } + + if (ret == LSM6DSO_ERROR) + { + return LSM6DSO_ERROR; + } + + if (pObj->acc_is_enabled == 1U) + { + ret = LSM6DSO_ACC_SetOutputDataRate_When_Enabled(pObj, newOdr); + } + else + { + ret = LSM6DSO_ACC_SetOutputDataRate_When_Disabled(pObj, newOdr); + } + + return ret; +} + +/** + * @brief Get the LSM6DSO accelerometer sensor full scale + * @param pObj the device pObj + * @param FullScale pointer where the full scale is written + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_GetFullScale(LSM6DSO_Object_t *pObj, int32_t *FullScale) +{ + int32_t ret = LSM6DSO_OK; + lsm6dso_fs_xl_t fs_low_level; + + /* Read actual full scale selection from sensor. */ + if (lsm6dso_xl_full_scale_get(&(pObj->Ctx), &fs_low_level) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + switch (fs_low_level) + { + case LSM6DSO_2g: + *FullScale = 2; + break; + + case LSM6DSO_4g: + *FullScale = 4; + break; + + case LSM6DSO_8g: + *FullScale = 8; + break; + + case LSM6DSO_16g: + *FullScale = 16; + break; + + default: + ret = LSM6DSO_ERROR; + break; + } + + return ret; +} + +/** + * @brief Set the LSM6DSO accelerometer sensor full scale + * @param pObj the device pObj + * @param FullScale the functional full scale to be set + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_SetFullScale(LSM6DSO_Object_t *pObj, int32_t FullScale) +{ + lsm6dso_fs_xl_t new_fs; + + /* Seems like MISRA C-2012 rule 14.3a violation but only from single file statical analysis point of view because + the parameter passed to the function is not known at the moment of analysis */ + new_fs = (FullScale <= 2) ? LSM6DSO_2g + : (FullScale <= 4) ? LSM6DSO_4g + : (FullScale <= 8) ? LSM6DSO_8g + : LSM6DSO_16g; + + if (lsm6dso_xl_full_scale_set(&(pObj->Ctx), new_fs) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Get the LSM6DSO accelerometer sensor raw axes + * @param pObj the device pObj + * @param Value pointer where the raw values of the axes are written + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_GetAxesRaw(LSM6DSO_Object_t *pObj, LSM6DSO_AxesRaw_t *Value) +{ + lsm6dso_axis3bit16_t data_raw; + + /* Read raw data values. */ + if (lsm6dso_acceleration_raw_get(&(pObj->Ctx), data_raw.i16bit) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Format the data. */ + Value->x = data_raw.i16bit[0]; + Value->y = data_raw.i16bit[1]; + Value->z = data_raw.i16bit[2]; + + return LSM6DSO_OK; +} + +/** + * @brief Get the LSM6DSO accelerometer sensor axes + * @param pObj the device pObj + * @param Acceleration pointer where the values of the axes are written + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_GetAxes(LSM6DSO_Object_t *pObj, LSM6DSO_Axes_t *Acceleration) +{ + lsm6dso_axis3bit16_t data_raw; + float_t sensitivity = 0.0f; + + /* Read raw data values. */ + if (lsm6dso_acceleration_raw_get(&(pObj->Ctx), data_raw.i16bit) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Get LSM6DSO actual sensitivity. */ + if (LSM6DSO_ACC_GetSensitivity(pObj, &sensitivity) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Calculate the data. */ + Acceleration->x = (int32_t)((float_t)((float_t)data_raw.i16bit[0] * sensitivity)); + Acceleration->y = (int32_t)((float_t)((float_t)data_raw.i16bit[1] * sensitivity)); + Acceleration->z = (int32_t)((float_t)((float_t)data_raw.i16bit[2] * sensitivity)); + + return LSM6DSO_OK; +} + +/** + * @brief Enable the LSM6DSO gyroscope sensor + * @param pObj the device pObj + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_GYRO_Enable(LSM6DSO_Object_t *pObj) +{ + /* Check if the component is already enabled */ + if (pObj->gyro_is_enabled == 1U) + { + return LSM6DSO_OK; + } + + /* Output data rate selection. */ + if (lsm6dso_gy_data_rate_set(&(pObj->Ctx), pObj->gyro_odr) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + pObj->gyro_is_enabled = 1; + + return LSM6DSO_OK; +} + +/** + * @brief Disable the LSM6DSO gyroscope sensor + * @param pObj the device pObj + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_GYRO_Disable(LSM6DSO_Object_t *pObj) +{ + /* Check if the component is already disabled */ + if (pObj->gyro_is_enabled == 0U) + { + return LSM6DSO_OK; + } + + /* Get current output data rate. */ + if (lsm6dso_gy_data_rate_get(&(pObj->Ctx), &pObj->gyro_odr) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Output data rate selection - power down. */ + if (lsm6dso_gy_data_rate_set(&(pObj->Ctx), LSM6DSO_GY_ODR_OFF) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + pObj->gyro_is_enabled = 0; + + return LSM6DSO_OK; +} + +/** + * @brief Get the LSM6DSO gyroscope sensor sensitivity + * @param pObj the device pObj + * @param Sensitivity pointer + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_GYRO_GetSensitivity(LSM6DSO_Object_t *pObj, float_t *Sensitivity) +{ + int32_t ret = LSM6DSO_OK; + lsm6dso_fs_g_t full_scale; + + /* Read actual full scale selection from sensor. */ + if (lsm6dso_gy_full_scale_get(&(pObj->Ctx), &full_scale) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Store the sensitivity based on actual full scale. */ + switch (full_scale) + { + case LSM6DSO_125dps: + *Sensitivity = LSM6DSO_GYRO_SENSITIVITY_FS_125DPS; + break; + + case LSM6DSO_250dps: + *Sensitivity = LSM6DSO_GYRO_SENSITIVITY_FS_250DPS; + break; + + case LSM6DSO_500dps: + *Sensitivity = LSM6DSO_GYRO_SENSITIVITY_FS_500DPS; + break; + + case LSM6DSO_1000dps: + *Sensitivity = LSM6DSO_GYRO_SENSITIVITY_FS_1000DPS; + break; + + case LSM6DSO_2000dps: + *Sensitivity = LSM6DSO_GYRO_SENSITIVITY_FS_2000DPS; + break; + + default: + ret = LSM6DSO_ERROR; + break; + } + + return ret; +} + +/** + * @brief Get the LSM6DSO gyroscope sensor output data rate + * @param pObj the device pObj + * @param Odr pointer where the output data rate is written + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_GYRO_GetOutputDataRate(LSM6DSO_Object_t *pObj, float_t *Odr) +{ + int32_t ret = LSM6DSO_OK; + lsm6dso_odr_g_t odr_low_level; + + /* Get current output data rate. */ + if (lsm6dso_gy_data_rate_get(&(pObj->Ctx), &odr_low_level) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + switch (odr_low_level) + { + case LSM6DSO_GY_ODR_OFF: + *Odr = 0.0f; + break; + + case LSM6DSO_GY_ODR_12Hz5: + *Odr = 12.5f; + break; + + case LSM6DSO_GY_ODR_26Hz: + *Odr = 26.0f; + break; + + case LSM6DSO_GY_ODR_52Hz: + *Odr = 52.0f; + break; + + case LSM6DSO_GY_ODR_104Hz: + *Odr = 104.0f; + break; + + case LSM6DSO_GY_ODR_208Hz: + *Odr = 208.0f; + break; + + case LSM6DSO_GY_ODR_417Hz: + *Odr = 417.0f; + break; + + case LSM6DSO_GY_ODR_833Hz: + *Odr = 833.0f; + break; + + case LSM6DSO_GY_ODR_1667Hz: + *Odr = 1667.0f; + break; + + case LSM6DSO_GY_ODR_3333Hz: + *Odr = 3333.0f; + break; + + case LSM6DSO_GY_ODR_6667Hz: + *Odr = 6667.0f; + break; + + default: + ret = LSM6DSO_ERROR; + break; + } + + return ret; +} + +/** + * @brief Set the LSM6DSO gyroscope sensor output data rate + * @param pObj the device pObj + * @param Odr the output data rate value to be set + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_GYRO_SetOutputDataRate(LSM6DSO_Object_t *pObj, float_t Odr) +{ + return LSM6DSO_GYRO_SetOutputDataRate_With_Mode(pObj, Odr, LSM6DSO_GYRO_HIGH_PERFORMANCE_MODE); +} + +/** + * @brief Set the LSM6DSO gyroscope sensor output data rate with operating mode + * @param pObj the device pObj + * @param Odr the output data rate value to be set + * @param Mode the gyroscope operating mode + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_GYRO_SetOutputDataRate_With_Mode(LSM6DSO_Object_t *pObj, float_t Odr, + LSM6DSO_GYRO_Operating_Mode_t Mode) +{ + int32_t ret = LSM6DSO_OK; + float_t newOdr = Odr; + + switch (Mode) + { + case LSM6DSO_GYRO_HIGH_PERFORMANCE_MODE: + { + /* We must uncheck Low Power bit if it is enabled */ + lsm6dso_ctrl7_g_t val1; + + if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_CTRL7_G, (uint8_t *)&val1, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + if (val1.g_hm_mode != 0U) + { + val1.g_hm_mode = 0U; + if (lsm6dso_write_reg(&(pObj->Ctx), LSM6DSO_CTRL7_G, (uint8_t *)&val1, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + } + break; + } + case LSM6DSO_GYRO_LOW_POWER_NORMAL_MODE: + { + /* We must check the Low Power bit if it is unchecked */ + lsm6dso_ctrl7_g_t val1; + + if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_CTRL7_G, (uint8_t *)&val1, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + if (val1.g_hm_mode == 0U) + { + val1.g_hm_mode = 1U; + if (lsm6dso_write_reg(&(pObj->Ctx), LSM6DSO_CTRL7_G, (uint8_t *)&val1, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + } + + /* Now we need to limit the ODR to 208 Hz if it is higher */ + if (newOdr > 208.0f) + { + newOdr = 208.0f; + } + break; + } + default: + ret = LSM6DSO_ERROR; + break; + } + + if (ret == LSM6DSO_ERROR) + { + return LSM6DSO_ERROR; + } + + if (pObj->gyro_is_enabled == 1U) + { + ret = LSM6DSO_GYRO_SetOutputDataRate_When_Enabled(pObj, newOdr); + } + else + { + ret = LSM6DSO_GYRO_SetOutputDataRate_When_Disabled(pObj, newOdr); + } + + return ret; +} + +/** + * @brief Get the LSM6DSO gyroscope sensor full scale + * @param pObj the device pObj + * @param FullScale pointer where the full scale is written + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_GYRO_GetFullScale(LSM6DSO_Object_t *pObj, int32_t *FullScale) +{ + int32_t ret = LSM6DSO_OK; + lsm6dso_fs_g_t fs_low_level; + + /* Read actual full scale selection from sensor. */ + if (lsm6dso_gy_full_scale_get(&(pObj->Ctx), &fs_low_level) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + switch (fs_low_level) + { + case LSM6DSO_125dps: + *FullScale = 125; + break; + + case LSM6DSO_250dps: + *FullScale = 250; + break; + + case LSM6DSO_500dps: + *FullScale = 500; + break; + + case LSM6DSO_1000dps: + *FullScale = 1000; + break; + + case LSM6DSO_2000dps: + *FullScale = 2000; + break; + + default: + ret = LSM6DSO_ERROR; + break; + } + + return ret; +} + +/** + * @brief Set the LSM6DSO gyroscope sensor full scale + * @param pObj the device pObj + * @param FullScale the functional full scale to be set + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_GYRO_SetFullScale(LSM6DSO_Object_t *pObj, int32_t FullScale) +{ + lsm6dso_fs_g_t new_fs; + + new_fs = (FullScale <= 125) ? LSM6DSO_125dps + : (FullScale <= 250) ? LSM6DSO_250dps + : (FullScale <= 500) ? LSM6DSO_500dps + : (FullScale <= 1000) ? LSM6DSO_1000dps + : LSM6DSO_2000dps; + + if (lsm6dso_gy_full_scale_set(&(pObj->Ctx), new_fs) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Get the LSM6DSO gyroscope sensor raw axes + * @param pObj the device pObj + * @param Value pointer where the raw values of the axes are written + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_GYRO_GetAxesRaw(LSM6DSO_Object_t *pObj, LSM6DSO_AxesRaw_t *Value) +{ + lsm6dso_axis3bit16_t data_raw; + + /* Read raw data values. */ + if (lsm6dso_angular_rate_raw_get(&(pObj->Ctx), data_raw.i16bit) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Format the data. */ + Value->x = data_raw.i16bit[0]; + Value->y = data_raw.i16bit[1]; + Value->z = data_raw.i16bit[2]; + + return LSM6DSO_OK; +} + +/** + * @brief Get the LSM6DSO gyroscope sensor axes + * @param pObj the device pObj + * @param AngularRate pointer where the values of the axes are written + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_GYRO_GetAxes(LSM6DSO_Object_t *pObj, LSM6DSO_Axes_t *AngularRate) +{ + lsm6dso_axis3bit16_t data_raw; + float_t sensitivity; + + /* Read raw data values. */ + if (lsm6dso_angular_rate_raw_get(&(pObj->Ctx), data_raw.i16bit) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Get LSM6DSO actual sensitivity. */ + if (LSM6DSO_GYRO_GetSensitivity(pObj, &sensitivity) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Calculate the data. */ + AngularRate->x = (int32_t)((float_t)((float_t)data_raw.i16bit[0] * sensitivity)); + AngularRate->y = (int32_t)((float_t)((float_t)data_raw.i16bit[1] * sensitivity)); + AngularRate->z = (int32_t)((float_t)((float_t)data_raw.i16bit[2] * sensitivity)); + + return LSM6DSO_OK; +} + +/** + * @brief Get the LSM6DSO register value + * @param pObj the device pObj + * @param Reg address to be read + * @param Data pointer where the value is written + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_Read_Reg(LSM6DSO_Object_t *pObj, uint8_t Reg, uint8_t *Data) +{ + if (lsm6dso_read_reg(&(pObj->Ctx), Reg, Data, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Set the LSM6DSO register value + * @param pObj the device pObj + * @param Reg address to be written + * @param Data value to be written + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_Write_Reg(LSM6DSO_Object_t *pObj, uint8_t Reg, uint8_t Data) +{ + if (lsm6dso_write_reg(&(pObj->Ctx), Reg, &Data, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Set the interrupt latch + * @param pObj the device pObj + * @param Status value to be written + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_Set_Interrupt_Latch(LSM6DSO_Object_t *pObj, uint8_t Status) +{ + int32_t ret = LSM6DSO_OK; + lsm6dso_lir_t newStatus = LSM6DSO_ALL_INT_PULSED; + + switch (Status) + { + case 0: + newStatus = LSM6DSO_ALL_INT_PULSED; + break; + case 1: + newStatus = LSM6DSO_BASE_LATCHED_EMB_PULSED; + break; + case 2: + newStatus = LSM6DSO_BASE_PULSED_EMB_LATCHED; + break; + case 3: + newStatus = LSM6DSO_ALL_INT_LATCHED; + break; + default: + ret = LSM6DSO_ERROR; + break; + } + + if (ret == LSM6DSO_ERROR) + { + return LSM6DSO_ERROR; + } + + if (Status > 1U) + { + return LSM6DSO_ERROR; + } + + if (lsm6dso_int_notification_set(&(pObj->Ctx), newStatus) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Enable free fall detection + * @param pObj the device pObj + * @param IntPin interrupt pin line to be used + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Enable_Free_Fall_Detection(LSM6DSO_Object_t *pObj, LSM6DSO_SensorIntPin_t IntPin) +{ + int32_t ret = LSM6DSO_OK; + lsm6dso_pin_int1_route_t val1; + lsm6dso_pin_int2_route_t val2; + + /* Output Data Rate selection */ + if (LSM6DSO_ACC_SetOutputDataRate(pObj, 417.0f) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Full scale selection */ + if (LSM6DSO_ACC_SetFullScale(pObj, 2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* FF_DUR setting */ + if (lsm6dso_ff_dur_set(&(pObj->Ctx), 0x06) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* WAKE_DUR setting */ + if (lsm6dso_wkup_dur_set(&(pObj->Ctx), 0x00) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* SLEEP_DUR setting */ + if (lsm6dso_act_sleep_dur_set(&(pObj->Ctx), 0x00) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* FF_THS setting */ + if (lsm6dso_ff_threshold_set(&(pObj->Ctx), LSM6DSO_FF_TSH_312mg) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Enable free fall event on either INT1 or INT2 pin */ + switch (IntPin) + { + case LSM6DSO_INT1_PIN: + if (lsm6dso_pin_int1_route_get(&(pObj->Ctx), &val1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + val1.free_fall = PROPERTY_ENABLE; + + if (lsm6dso_pin_int1_route_set(&(pObj->Ctx), val1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + break; + + case LSM6DSO_INT2_PIN: + if (lsm6dso_pin_int2_route_get(&(pObj->Ctx), NULL, &val2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + val2.free_fall = PROPERTY_ENABLE; + + if (lsm6dso_pin_int2_route_set(&(pObj->Ctx), NULL, val2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + break; + + default: + ret = LSM6DSO_ERROR; + break; + } + + return ret; +} + +/** + * @brief Disable free fall detection + * @param pObj the device pObj + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Disable_Free_Fall_Detection(LSM6DSO_Object_t *pObj) +{ + lsm6dso_pin_int1_route_t val1; + lsm6dso_pin_int2_route_t val2; + + /* Disable free fall event on both INT1 and INT2 pins */ + if (lsm6dso_pin_int1_route_get(&(pObj->Ctx), &val1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + val1.free_fall = PROPERTY_DISABLE; + + if (lsm6dso_pin_int1_route_set(&(pObj->Ctx), val1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + if (lsm6dso_pin_int2_route_get(&(pObj->Ctx), NULL, &val2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + val2.free_fall = PROPERTY_DISABLE; + + if (lsm6dso_pin_int2_route_set(&(pObj->Ctx), NULL, val2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* FF_DUR setting */ + if (lsm6dso_ff_dur_set(&(pObj->Ctx), 0x00) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* FF_THS setting */ + if (lsm6dso_ff_threshold_set(&(pObj->Ctx), LSM6DSO_FF_TSH_156mg) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Set free fall threshold + * @param pObj the device pObj + * @param Threshold free fall detection threshold + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Set_Free_Fall_Threshold(LSM6DSO_Object_t *pObj, uint8_t Threshold) +{ + int32_t ret = LSM6DSO_OK; + lsm6dso_ff_ths_t newThreshold = LSM6DSO_FF_TSH_156mg; + + switch (Threshold) + { + case 0: + newThreshold = LSM6DSO_FF_TSH_156mg; + break; + case 1: + newThreshold = LSM6DSO_FF_TSH_219mg; + break; + case 2: + newThreshold = LSM6DSO_FF_TSH_250mg; + break; + case 3: + newThreshold = LSM6DSO_FF_TSH_312mg; + break; + case 4: + newThreshold = LSM6DSO_FF_TSH_344mg; + break; + case 5: + newThreshold = LSM6DSO_FF_TSH_406mg; + break; + case 6: + newThreshold = LSM6DSO_FF_TSH_469mg; + break; + case 7: + newThreshold = LSM6DSO_FF_TSH_500mg; + break; + default: + ret = LSM6DSO_ERROR; + break; + } + + if (ret == LSM6DSO_ERROR) + { + return LSM6DSO_ERROR; + } + + if (lsm6dso_ff_threshold_set(&(pObj->Ctx), newThreshold) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return ret; +} + +/** + * @brief Set free fall duration + * @param pObj the device pObj + * @param Duration free fall detection duration + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Set_Free_Fall_Duration(LSM6DSO_Object_t *pObj, uint8_t Duration) +{ + if (lsm6dso_ff_dur_set(&(pObj->Ctx), Duration) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Enable pedometer + * @param pObj the device pObj + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Enable_Pedometer(LSM6DSO_Object_t *pObj) +{ + lsm6dso_pin_int1_route_t val; + lsm6dso_emb_sens_t emb_sens; + + /* Output Data Rate selection */ + if (LSM6DSO_ACC_SetOutputDataRate(pObj, 26.0f) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Full scale selection */ + if (LSM6DSO_ACC_SetFullScale(pObj, 2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Save current embedded features */ + if (lsm6dso_embedded_sens_get(&(pObj->Ctx), &emb_sens) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Turn off embedded features */ + if (lsm6dso_embedded_sens_off(&(pObj->Ctx)) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Wait for 10 ms */ + LSM6DSO_Delay(pObj, 10); + + /* Enable pedometer algorithm. */ + emb_sens.step = PROPERTY_ENABLE; + + if (lsm6dso_pedo_sens_set(&(pObj->Ctx), LSM6DSO_PEDO_BASE_MODE) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Turn on embedded features */ + if (lsm6dso_embedded_sens_set(&(pObj->Ctx), &emb_sens) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Enable step detector on INT1 pin */ + if (lsm6dso_pin_int1_route_get(&(pObj->Ctx), &val) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + val.step_detector = PROPERTY_ENABLE; + + if (lsm6dso_pin_int1_route_set(&(pObj->Ctx), val) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Disable pedometer + * @param pObj the device pObj + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Disable_Pedometer(LSM6DSO_Object_t *pObj) +{ + lsm6dso_pin_int1_route_t val1; + lsm6dso_emb_sens_t emb_sens; + + /* Disable step detector on INT1 pin */ + if (lsm6dso_pin_int1_route_get(&(pObj->Ctx), &val1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + val1.step_detector = PROPERTY_DISABLE; + + if (lsm6dso_pin_int1_route_set(&(pObj->Ctx), val1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Save current embedded features */ + if (lsm6dso_embedded_sens_get(&(pObj->Ctx), &emb_sens) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Disable pedometer algorithm. */ + emb_sens.step = PROPERTY_DISABLE; + + if (lsm6dso_embedded_sens_set(&(pObj->Ctx), &emb_sens) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Get step count + * @param pObj the device pObj + * @param StepCount step counter + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Get_Step_Count(LSM6DSO_Object_t *pObj, uint16_t *StepCount) +{ + if (lsm6dso_number_of_steps_get(&(pObj->Ctx), StepCount) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Enable step counter reset + * @param pObj the device pObj + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Step_Counter_Reset(LSM6DSO_Object_t *pObj) +{ + if (lsm6dso_steps_reset(&(pObj->Ctx)) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Enable tilt detection + * @param pObj the device pObj + * @param IntPin interrupt pin line to be used + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Enable_Tilt_Detection(LSM6DSO_Object_t *pObj, LSM6DSO_SensorIntPin_t IntPin) +{ + int32_t ret = LSM6DSO_OK; + lsm6dso_pin_int1_route_t val1; + lsm6dso_pin_int2_route_t val2; + lsm6dso_emb_sens_t emb_sens; + + /* Output Data Rate selection */ + if (LSM6DSO_ACC_SetOutputDataRate(pObj, 26.0f) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Full scale selection */ + if (LSM6DSO_ACC_SetFullScale(pObj, 2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Save current embedded features */ + if (lsm6dso_embedded_sens_get(&(pObj->Ctx), &emb_sens) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Turn off embedded features */ + if (lsm6dso_embedded_sens_off(&(pObj->Ctx)) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Wait for 10 ms */ + LSM6DSO_Delay(pObj, 10); + + /* Enable tilt algorithm. */ + emb_sens.tilt = PROPERTY_ENABLE; + + /* Turn on embedded features */ + if (lsm6dso_embedded_sens_set(&(pObj->Ctx), &emb_sens) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Enable tilt event on either INT1 or INT2 pin */ + switch (IntPin) + { + case LSM6DSO_INT1_PIN: + if (lsm6dso_pin_int1_route_get(&(pObj->Ctx), &val1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + val1.tilt = PROPERTY_ENABLE; + + if (lsm6dso_pin_int1_route_set(&(pObj->Ctx), val1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + break; + + case LSM6DSO_INT2_PIN: + if (lsm6dso_pin_int2_route_get(&(pObj->Ctx), NULL, &val2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + val2.tilt = PROPERTY_ENABLE; + + if (lsm6dso_pin_int2_route_set(&(pObj->Ctx), NULL, val2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + break; + + default: + ret = LSM6DSO_ERROR; + break; + } + + return ret; +} + +/** + * @brief Disable tilt detection + * @param pObj the device pObj + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Disable_Tilt_Detection(LSM6DSO_Object_t *pObj) +{ + lsm6dso_pin_int1_route_t val1; + lsm6dso_pin_int2_route_t val2; + lsm6dso_emb_sens_t emb_sens; + + /* Disable tilt event on both INT1 and INT2 pins */ + if (lsm6dso_pin_int1_route_get(&(pObj->Ctx), &val1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + val1.tilt = PROPERTY_DISABLE; + + if (lsm6dso_pin_int1_route_set(&(pObj->Ctx), val1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + if (lsm6dso_pin_int2_route_get(&(pObj->Ctx), NULL, &val2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + val2.tilt = PROPERTY_DISABLE; + + if (lsm6dso_pin_int2_route_set(&(pObj->Ctx), NULL, val2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Save current embedded features */ + if (lsm6dso_embedded_sens_get(&(pObj->Ctx), &emb_sens) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Disable tilt algorithm. */ + emb_sens.tilt = PROPERTY_DISABLE; + + if (lsm6dso_embedded_sens_set(&(pObj->Ctx), &emb_sens) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Enable wake up detection + * @param pObj the device pObj + * @param IntPin interrupt pin line to be used + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Enable_Wake_Up_Detection(LSM6DSO_Object_t *pObj, LSM6DSO_SensorIntPin_t IntPin) +{ + int32_t ret = LSM6DSO_OK; + lsm6dso_pin_int1_route_t val1; + lsm6dso_pin_int2_route_t val2; + + /* Output Data Rate selection */ + if (LSM6DSO_ACC_SetOutputDataRate(pObj, 417.0f) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Full scale selection */ + if (LSM6DSO_ACC_SetFullScale(pObj, 2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* WAKE_DUR setting */ + if (lsm6dso_wkup_dur_set(&(pObj->Ctx), 0x00) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Set wake up threshold. */ + if (lsm6dso_wkup_threshold_set(&(pObj->Ctx), 0x02) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Enable wake up event on either INT1 or INT2 pin */ + switch (IntPin) + { + case LSM6DSO_INT1_PIN: + if (lsm6dso_pin_int1_route_get(&(pObj->Ctx), &val1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + val1.wake_up = PROPERTY_ENABLE; + + if (lsm6dso_pin_int1_route_set(&(pObj->Ctx), val1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + break; + + case LSM6DSO_INT2_PIN: + if (lsm6dso_pin_int2_route_get(&(pObj->Ctx), NULL, &val2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + val2.wake_up = PROPERTY_ENABLE; + + if (lsm6dso_pin_int2_route_set(&(pObj->Ctx), NULL, val2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + break; + + default: + ret = LSM6DSO_ERROR; + break; + } + + return ret; +} + +/** + * @brief Disable wake up detection + * @param pObj the device pObj + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Disable_Wake_Up_Detection(LSM6DSO_Object_t *pObj) +{ + lsm6dso_pin_int1_route_t val1; + lsm6dso_pin_int2_route_t val2; + + /* Disable wake up event on both INT1 and INT2 pins */ + if (lsm6dso_pin_int1_route_get(&(pObj->Ctx), &val1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + val1.wake_up = PROPERTY_DISABLE; + + if (lsm6dso_pin_int1_route_set(&(pObj->Ctx), val1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + if (lsm6dso_pin_int2_route_get(&(pObj->Ctx), NULL, &val2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + val2.wake_up = PROPERTY_DISABLE; + + if (lsm6dso_pin_int2_route_set(&(pObj->Ctx), NULL, val2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Reset wake up threshold. */ + if (lsm6dso_wkup_threshold_set(&(pObj->Ctx), 0x00) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* WAKE_DUR setting */ + if (lsm6dso_wkup_dur_set(&(pObj->Ctx), 0x00) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Set wake up threshold + * @param pObj the device pObj + * @param Threshold wake up detection threshold + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Set_Wake_Up_Threshold(LSM6DSO_Object_t *pObj, uint8_t Threshold) +{ + /* Set wake up threshold. */ + if (lsm6dso_wkup_threshold_set(&(pObj->Ctx), Threshold) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Set wake up duration + * @param pObj the device pObj + * @param Duration wake up detection duration + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Set_Wake_Up_Duration(LSM6DSO_Object_t *pObj, uint8_t Duration) +{ + /* Set wake up duration. */ + if (lsm6dso_wkup_dur_set(&(pObj->Ctx), Duration) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Enable single tap detection + * @param pObj the device pObj + * @param IntPin interrupt pin line to be used + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Enable_Single_Tap_Detection(LSM6DSO_Object_t *pObj, LSM6DSO_SensorIntPin_t IntPin) +{ + int32_t ret = LSM6DSO_OK; + lsm6dso_pin_int1_route_t val1; + lsm6dso_pin_int2_route_t val2; + + /* Output Data Rate selection */ + if (LSM6DSO_ACC_SetOutputDataRate(pObj, 417.0f) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Full scale selection */ + if (LSM6DSO_ACC_SetFullScale(pObj, 2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Enable X direction in tap recognition. */ + if (lsm6dso_tap_detection_on_x_set(&(pObj->Ctx), PROPERTY_ENABLE) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Enable Y direction in tap recognition. */ + if (lsm6dso_tap_detection_on_y_set(&(pObj->Ctx), PROPERTY_ENABLE) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Enable Z direction in tap recognition. */ + if (lsm6dso_tap_detection_on_z_set(&(pObj->Ctx), PROPERTY_ENABLE) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Set tap threshold. */ + if (lsm6dso_tap_threshold_x_set(&(pObj->Ctx), 0x08) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Set tap shock time window. */ + if (lsm6dso_tap_shock_set(&(pObj->Ctx), 0x02) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Set tap quiet time window. */ + if (lsm6dso_tap_quiet_set(&(pObj->Ctx), 0x01) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* _NOTE_: Tap duration time window - don't care for single tap. */ + + /* _NOTE_: Single/Double Tap event - don't care of this flag for single tap. */ + + /* Enable single tap event on either INT1 or INT2 pin */ + switch (IntPin) + { + case LSM6DSO_INT1_PIN: + if (lsm6dso_pin_int1_route_get(&(pObj->Ctx), &val1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + val1.single_tap = PROPERTY_ENABLE; + + if (lsm6dso_pin_int1_route_set(&(pObj->Ctx), val1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + break; + + case LSM6DSO_INT2_PIN: + if (lsm6dso_pin_int2_route_get(&(pObj->Ctx), NULL, &val2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + val2.single_tap = PROPERTY_ENABLE; + + if (lsm6dso_pin_int2_route_set(&(pObj->Ctx), NULL, val2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + break; + + default: + ret = LSM6DSO_ERROR; + break; + } + + return ret; +} + +/** + * @brief Disable single tap detection + * @param pObj the device pObj + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Disable_Single_Tap_Detection(LSM6DSO_Object_t *pObj) +{ + lsm6dso_pin_int1_route_t val1; + lsm6dso_pin_int2_route_t val2; + + /* Disable single tap event on both INT1 and INT2 pins */ + if (lsm6dso_pin_int1_route_get(&(pObj->Ctx), &val1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + val1.single_tap = PROPERTY_DISABLE; + + if (lsm6dso_pin_int1_route_set(&(pObj->Ctx), val1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + if (lsm6dso_pin_int2_route_get(&(pObj->Ctx), NULL, &val2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + val2.single_tap = PROPERTY_DISABLE; + + if (lsm6dso_pin_int2_route_set(&(pObj->Ctx), NULL, val2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Reset tap quiet time window. */ + if (lsm6dso_tap_quiet_set(&(pObj->Ctx), 0x00) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Reset tap shock time window. */ + if (lsm6dso_tap_shock_set(&(pObj->Ctx), 0x00) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Reset tap threshold. */ + if (lsm6dso_tap_threshold_x_set(&(pObj->Ctx), 0x00) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Disable Z direction in tap recognition. */ + if (lsm6dso_tap_detection_on_z_set(&(pObj->Ctx), PROPERTY_DISABLE) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Disable Y direction in tap recognition. */ + if (lsm6dso_tap_detection_on_y_set(&(pObj->Ctx), PROPERTY_DISABLE) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Disable X direction in tap recognition. */ + if (lsm6dso_tap_detection_on_x_set(&(pObj->Ctx), PROPERTY_DISABLE) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Enable double tap detection + * @param pObj the device pObj + * @param IntPin interrupt pin line to be used + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Enable_Double_Tap_Detection(LSM6DSO_Object_t *pObj, LSM6DSO_SensorIntPin_t IntPin) +{ + int32_t ret = LSM6DSO_OK; + lsm6dso_pin_int1_route_t val1; + lsm6dso_pin_int2_route_t val2; + + /* Output Data Rate selection */ + if (LSM6DSO_ACC_SetOutputDataRate(pObj, 417.0f) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Full scale selection */ + if (LSM6DSO_ACC_SetFullScale(pObj, 2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Enable X direction in tap recognition. */ + if (lsm6dso_tap_detection_on_x_set(&(pObj->Ctx), PROPERTY_ENABLE) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Enable Y direction in tap recognition. */ + if (lsm6dso_tap_detection_on_y_set(&(pObj->Ctx), PROPERTY_ENABLE) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Enable Z direction in tap recognition. */ + if (lsm6dso_tap_detection_on_z_set(&(pObj->Ctx), PROPERTY_ENABLE) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Set tap threshold. */ + if (lsm6dso_tap_threshold_x_set(&(pObj->Ctx), 0x08) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Set tap shock time window. */ + if (lsm6dso_tap_shock_set(&(pObj->Ctx), 0x03) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Set tap quiet time window. */ + if (lsm6dso_tap_quiet_set(&(pObj->Ctx), 0x03) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Set tap duration time window. */ + if (lsm6dso_tap_dur_set(&(pObj->Ctx), 0x08) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Single and double tap enabled. */ + if (lsm6dso_tap_mode_set(&(pObj->Ctx), LSM6DSO_BOTH_SINGLE_DOUBLE) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Enable double tap event on either INT1 or INT2 pin */ + switch (IntPin) + { + case LSM6DSO_INT1_PIN: + if (lsm6dso_pin_int1_route_get(&(pObj->Ctx), &val1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + val1.double_tap = PROPERTY_ENABLE; + + if (lsm6dso_pin_int1_route_set(&(pObj->Ctx), val1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + break; + + case LSM6DSO_INT2_PIN: + if (lsm6dso_pin_int2_route_get(&(pObj->Ctx), NULL, &val2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + val2.double_tap = PROPERTY_ENABLE; + + if (lsm6dso_pin_int2_route_set(&(pObj->Ctx), NULL, val2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + break; + + default: + ret = LSM6DSO_ERROR; + break; + } + + return ret; +} + +/** + * @brief Disable double tap detection + * @param pObj the device pObj + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Disable_Double_Tap_Detection(LSM6DSO_Object_t *pObj) +{ + lsm6dso_pin_int1_route_t val1; + lsm6dso_pin_int2_route_t val2; + + /* Disable double tap event on both INT1 and INT2 pins */ + if (lsm6dso_pin_int1_route_get(&(pObj->Ctx), &val1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + val1.double_tap = PROPERTY_DISABLE; + + if (lsm6dso_pin_int1_route_set(&(pObj->Ctx), val1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + if (lsm6dso_pin_int2_route_get(&(pObj->Ctx), NULL, &val2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + val2.double_tap = PROPERTY_DISABLE; + + if (lsm6dso_pin_int2_route_set(&(pObj->Ctx), NULL, val2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Only single tap enabled. */ + if (lsm6dso_tap_mode_set(&(pObj->Ctx), LSM6DSO_ONLY_SINGLE) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Reset tap duration time window. */ + if (lsm6dso_tap_dur_set(&(pObj->Ctx), 0x00) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Reset tap quiet time window. */ + if (lsm6dso_tap_quiet_set(&(pObj->Ctx), 0x00) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Reset tap shock time window. */ + if (lsm6dso_tap_shock_set(&(pObj->Ctx), 0x00) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Reset tap threshold. */ + if (lsm6dso_tap_threshold_x_set(&(pObj->Ctx), 0x00) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Disable Z direction in tap recognition. */ + if (lsm6dso_tap_detection_on_z_set(&(pObj->Ctx), PROPERTY_DISABLE) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Disable Y direction in tap recognition. */ + if (lsm6dso_tap_detection_on_y_set(&(pObj->Ctx), PROPERTY_DISABLE) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Disable X direction in tap recognition. */ + if (lsm6dso_tap_detection_on_x_set(&(pObj->Ctx), PROPERTY_DISABLE) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Set tap threshold + * @param pObj the device pObj + * @param Threshold tap threshold + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Set_Tap_Threshold(LSM6DSO_Object_t *pObj, uint8_t Threshold) +{ + /* Set tap threshold. */ + if (lsm6dso_tap_threshold_x_set(&(pObj->Ctx), Threshold) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Set tap shock time + * @param pObj the device pObj + * @param Time tap shock time + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Set_Tap_Shock_Time(LSM6DSO_Object_t *pObj, uint8_t Time) +{ + /* Set tap shock time window. */ + if (lsm6dso_tap_shock_set(&(pObj->Ctx), Time) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Set tap quiet time + * @param pObj the device pObj + * @param Time tap quiet time + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Set_Tap_Quiet_Time(LSM6DSO_Object_t *pObj, uint8_t Time) +{ + /* Set tap quiet time window. */ + if (lsm6dso_tap_quiet_set(&(pObj->Ctx), Time) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Set tap duration time + * @param pObj the device pObj + * @param Time tap duration time + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Set_Tap_Duration_Time(LSM6DSO_Object_t *pObj, uint8_t Time) +{ + /* Set tap duration time window. */ + if (lsm6dso_tap_dur_set(&(pObj->Ctx), Time) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Enable 6D orientation detection + * @param pObj the device pObj + * @param IntPin interrupt pin line to be used + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Enable_6D_Orientation(LSM6DSO_Object_t *pObj, LSM6DSO_SensorIntPin_t IntPin) +{ + int32_t ret = LSM6DSO_OK; + lsm6dso_pin_int1_route_t val1; + lsm6dso_pin_int2_route_t val2; + + /* Output Data Rate selection */ + if (LSM6DSO_ACC_SetOutputDataRate(pObj, 417.0f) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Full scale selection */ + if (LSM6DSO_ACC_SetFullScale(pObj, 2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* 6D orientation enabled. */ + if (lsm6dso_6d_threshold_set(&(pObj->Ctx), LSM6DSO_DEG_60) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Enable 6D orientation event on either INT1 or INT2 pin */ + switch (IntPin) + { + case LSM6DSO_INT1_PIN: + if (lsm6dso_pin_int1_route_get(&(pObj->Ctx), &val1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + val1.six_d = PROPERTY_ENABLE; + + if (lsm6dso_pin_int1_route_set(&(pObj->Ctx), val1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + break; + + case LSM6DSO_INT2_PIN: + if (lsm6dso_pin_int2_route_get(&(pObj->Ctx), NULL, &val2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + val2.six_d = PROPERTY_ENABLE; + + if (lsm6dso_pin_int2_route_set(&(pObj->Ctx), NULL, val2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + break; + + default: + ret = LSM6DSO_ERROR; + break; + } + + return ret; +} + +/** + * @brief Disable 6D orientation detection + * @param pObj the device pObj + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Disable_6D_Orientation(LSM6DSO_Object_t *pObj) +{ + lsm6dso_pin_int1_route_t val1; + lsm6dso_pin_int2_route_t val2; + + /* Disable 6D orientation event on both INT1 and INT2 pins */ + if (lsm6dso_pin_int1_route_get(&(pObj->Ctx), &val1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + val1.six_d = PROPERTY_DISABLE; + + if (lsm6dso_pin_int1_route_set(&(pObj->Ctx), val1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + if (lsm6dso_pin_int2_route_get(&(pObj->Ctx), NULL, &val2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + val2.six_d = PROPERTY_DISABLE; + + if (lsm6dso_pin_int2_route_set(&(pObj->Ctx), NULL, val2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Reset 6D orientation. */ + if (lsm6dso_6d_threshold_set(&(pObj->Ctx), LSM6DSO_DEG_80) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Set 6D orientation threshold + * @param pObj the device pObj + * @param Threshold 6D Orientation detection threshold + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Set_6D_Orientation_Threshold(LSM6DSO_Object_t *pObj, uint8_t Threshold) +{ + int32_t ret = LSM6DSO_OK; + lsm6dso_sixd_ths_t newThreshold = LSM6DSO_DEG_80; + + switch (Threshold) + { + case 0: + newThreshold = LSM6DSO_DEG_80; + break; + case 1: + newThreshold = LSM6DSO_DEG_70; + break; + case 2: + newThreshold = LSM6DSO_DEG_60; + break; + case 3: + newThreshold = LSM6DSO_DEG_50; + break; + default: + ret = LSM6DSO_ERROR; + break; + } + + if (ret == LSM6DSO_ERROR) + { + return LSM6DSO_ERROR; + } + + if (lsm6dso_6d_threshold_set(&(pObj->Ctx), newThreshold) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Get the status of XLow orientation + * @param pObj the device pObj + * @param XLow the status of XLow orientation + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Get_6D_Orientation_XL(LSM6DSO_Object_t *pObj, uint8_t *XLow) +{ + lsm6dso_d6d_src_t data; + + if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_D6D_SRC, (uint8_t *)&data, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + *XLow = data.xl; + + return LSM6DSO_OK; +} + +/** + * @brief Get the status of XHigh orientation + * @param pObj the device pObj + * @param XHigh the status of XHigh orientation + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Get_6D_Orientation_XH(LSM6DSO_Object_t *pObj, uint8_t *XHigh) +{ + lsm6dso_d6d_src_t data; + + if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_D6D_SRC, (uint8_t *)&data, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + *XHigh = data.xh; + + return LSM6DSO_OK; +} + +/** + * @brief Get the status of YLow orientation + * @param pObj the device pObj + * @param YLow the status of YLow orientation + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Get_6D_Orientation_YL(LSM6DSO_Object_t *pObj, uint8_t *YLow) +{ + lsm6dso_d6d_src_t data; + + if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_D6D_SRC, (uint8_t *)&data, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + *YLow = data.yl; + + return LSM6DSO_OK; +} + +/** + * @brief Get the status of YHigh orientation + * @param pObj the device pObj + * @param YHigh the status of YHigh orientation + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Get_6D_Orientation_YH(LSM6DSO_Object_t *pObj, uint8_t *YHigh) +{ + lsm6dso_d6d_src_t data; + + if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_D6D_SRC, (uint8_t *)&data, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + *YHigh = data.yh; + + return LSM6DSO_OK; +} + +/** + * @brief Get the status of ZLow orientation + * @param pObj the device pObj + * @param ZLow the status of ZLow orientation + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Get_6D_Orientation_ZL(LSM6DSO_Object_t *pObj, uint8_t *ZLow) +{ + lsm6dso_d6d_src_t data; + + if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_D6D_SRC, (uint8_t *)&data, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + *ZLow = data.zl; + + return LSM6DSO_OK; +} + +/** + * @brief Get the status of ZHigh orientation + * @param pObj the device pObj + * @param ZHigh the status of ZHigh orientation + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Get_6D_Orientation_ZH(LSM6DSO_Object_t *pObj, uint8_t *ZHigh) +{ + lsm6dso_d6d_src_t data; + + if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_D6D_SRC, (uint8_t *)&data, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + *ZHigh = data.zh; + + return LSM6DSO_OK; +} + +/** + * @brief Get the LSM6DSO ACC data ready bit value + * @param pObj the device pObj + * @param Status the status of data ready bit + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Get_DRDY_Status(LSM6DSO_Object_t *pObj, uint8_t *Status) +{ + if (lsm6dso_xl_flag_data_ready_get(&(pObj->Ctx), Status) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Get the status of all hardware events + * @param pObj the device pObj + * @param Status the status of all hardware events + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Get_Event_Status(LSM6DSO_Object_t *pObj, LSM6DSO_Event_Status_t *Status) +{ + uint8_t tilt_ia; + lsm6dso_wake_up_src_t wake_up_src; + lsm6dso_tap_src_t tap_src; + lsm6dso_d6d_src_t d6d_src; + lsm6dso_emb_func_src_t func_src; + lsm6dso_md1_cfg_t md1_cfg; + lsm6dso_md2_cfg_t md2_cfg; + lsm6dso_emb_func_int1_t int1_ctrl; + lsm6dso_emb_func_int2_t int2_ctrl; + + (void)memset((void *)Status, 0x0, sizeof(LSM6DSO_Event_Status_t)); + + if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_WAKE_UP_SRC, (uint8_t *)&wake_up_src, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_TAP_SRC, (uint8_t *)&tap_src, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_D6D_SRC, (uint8_t *)&d6d_src, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + if (lsm6dso_mem_bank_set(&(pObj->Ctx), LSM6DSO_EMBEDDED_FUNC_BANK) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_EMB_FUNC_SRC, (uint8_t *)&func_src, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_EMB_FUNC_INT1, (uint8_t *)&int1_ctrl, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_EMB_FUNC_INT2, (uint8_t *)&int2_ctrl, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + if (lsm6dso_mem_bank_set(&(pObj->Ctx), LSM6DSO_USER_BANK) != 0) + { + return LSM6DSO_ERROR; + } + + if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_MD1_CFG, (uint8_t *)&md1_cfg, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_MD2_CFG, (uint8_t *)&md2_cfg, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + if (lsm6dso_tilt_flag_data_ready_get(&(pObj->Ctx), &tilt_ia) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + if ((md1_cfg.int1_ff == 1U) || (md2_cfg.int2_ff == 1U)) + { + if (wake_up_src.ff_ia == 1U) + { + Status->FreeFallStatus = 1; + } + } + + if ((md1_cfg.int1_wu == 1U) || (md2_cfg.int2_wu == 1U)) + { + if (wake_up_src.wu_ia == 1U) + { + Status->WakeUpStatus = 1; + } + } + + if ((md1_cfg.int1_single_tap == 1U) || (md2_cfg.int2_single_tap == 1U)) + { + if (tap_src.single_tap == 1U) + { + Status->TapStatus = 1; + } + } + + if ((md1_cfg.int1_double_tap == 1U) || (md2_cfg.int2_double_tap == 1U)) + { + if (tap_src.double_tap == 1U) + { + Status->DoubleTapStatus = 1; + } + } + + if ((md1_cfg.int1_6d == 1U) || (md2_cfg.int2_6d == 1U)) + { + if (d6d_src.d6d_ia == 1U) + { + Status->D6DOrientationStatus = 1; + } + } + + if (int1_ctrl.int1_step_detector == 1U) + { + if (func_src.step_detected == 1U) + { + Status->StepStatus = 1; + } + } + + if ((int1_ctrl.int1_tilt == 1U) || (int2_ctrl.int2_tilt == 1U)) + { + if (tilt_ia == 1U) + { + Status->TiltStatus = 1; + } + } + + return LSM6DSO_OK; +} + +/** + * @brief Set self test + * @param pObj the device pObj + * @param val the value of st_xl in reg CTRL5_C + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Set_SelfTest(LSM6DSO_Object_t *pObj, uint8_t val) +{ + lsm6dso_st_xl_t reg; + + reg = (val == 0U) ? LSM6DSO_XL_ST_DISABLE + : (val == 1U) ? LSM6DSO_XL_ST_POSITIVE + : (val == 2U) ? LSM6DSO_XL_ST_NEGATIVE + : LSM6DSO_XL_ST_DISABLE; + + if (lsm6dso_xl_self_test_set(&(pObj->Ctx), reg) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Get the LSM6DSO GYRO data ready bit value + * @param pObj the device pObj + * @param Status the status of data ready bit + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_GYRO_Get_DRDY_Status(LSM6DSO_Object_t *pObj, uint8_t *Status) +{ + if (lsm6dso_gy_flag_data_ready_get(&(pObj->Ctx), Status) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Set self test + * @param pObj the device pObj + * @param val the value of st_xl in reg CTRL5_C + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_GYRO_Set_SelfTest(LSM6DSO_Object_t *pObj, uint8_t val) +{ + lsm6dso_st_g_t reg; + + reg = (val == 0U) ? LSM6DSO_GY_ST_DISABLE + : (val == 1U) ? LSM6DSO_GY_ST_POSITIVE + : (val == 2U) ? LSM6DSO_GY_ST_NEGATIVE + : LSM6DSO_GY_ST_DISABLE; + + + if (lsm6dso_gy_self_test_set(&(pObj->Ctx), reg) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Get the LSM6DSO FIFO number of samples + * @param pObj the device pObj + * @param NumSamples number of samples + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_FIFO_Get_Num_Samples(LSM6DSO_Object_t *pObj, uint16_t *NumSamples) +{ + if (lsm6dso_fifo_data_level_get(&(pObj->Ctx), NumSamples) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Get the LSM6DSO FIFO full status + * @param pObj the device pObj + * @param Status FIFO full status + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_FIFO_Get_Full_Status(LSM6DSO_Object_t *pObj, uint8_t *Status) +{ + lsm6dso_reg_t reg; + + if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_FIFO_STATUS2, ®.byte, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + *Status = reg.fifo_status2.fifo_full_ia; + + return LSM6DSO_OK; +} + +/** + * @brief Set the LSM6DSO FIFO full interrupt on INT1 pin + * @param pObj the device pObj + * @param Status FIFO full interrupt on INT1 pin status + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_FIFO_Set_INT1_FIFO_Full(LSM6DSO_Object_t *pObj, uint8_t Status) +{ + lsm6dso_reg_t reg; + + if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_INT1_CTRL, ®.byte, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + reg.int1_ctrl.int1_fifo_full = Status; + + if (lsm6dso_write_reg(&(pObj->Ctx), LSM6DSO_INT1_CTRL, ®.byte, 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Set the LSM6DSO FIFO watermark level + * @param pObj the device pObj + * @param Watermark FIFO watermark level + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_FIFO_Set_Watermark_Level(LSM6DSO_Object_t *pObj, uint16_t Watermark) +{ + if (lsm6dso_fifo_watermark_set(&(pObj->Ctx), Watermark) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Set the LSM6DSO FIFO stop on watermark + * @param pObj the device pObj + * @param Status FIFO stop on watermark status + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_FIFO_Set_Stop_On_Fth(LSM6DSO_Object_t *pObj, uint8_t Status) +{ + if (lsm6dso_fifo_stop_on_wtm_set(&(pObj->Ctx), Status) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Set the LSM6DSO FIFO mode + * @param pObj the device pObj + * @param Mode FIFO mode + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_FIFO_Set_Mode(LSM6DSO_Object_t *pObj, uint8_t Mode) +{ + int32_t ret = LSM6DSO_OK; + lsm6dso_fifo_mode_t newMode = LSM6DSO_BYPASS_MODE; + + switch (Mode) + { + case 0: + newMode = LSM6DSO_BYPASS_MODE; + break; + case 1: + newMode = LSM6DSO_FIFO_MODE; + break; + case 3: + newMode = LSM6DSO_STREAM_TO_FIFO_MODE; + break; + case 4: + newMode = LSM6DSO_BYPASS_TO_STREAM_MODE; + break; + case 6: + newMode = LSM6DSO_STREAM_MODE; + break; + case 7: + newMode = LSM6DSO_BYPASS_TO_FIFO_MODE; + break; + default: + ret = LSM6DSO_ERROR; + break; + } + + if (ret == LSM6DSO_ERROR) + { + return LSM6DSO_ERROR; + } + + if (lsm6dso_fifo_mode_set(&(pObj->Ctx), newMode) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return ret; +} + +/** + * @brief Get the LSM6DSO FIFO tag + * @param pObj the device pObj + * @param Tag FIFO tag + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_FIFO_Get_Tag(LSM6DSO_Object_t *pObj, uint8_t *Tag) +{ + lsm6dso_fifo_tag_t tag_local; + + if (lsm6dso_fifo_sensor_tag_get(&(pObj->Ctx), &tag_local) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + *Tag = (uint8_t)tag_local; + + return LSM6DSO_OK; +} + +/** + * @brief Get the LSM6DSO FIFO raw data + * @param pObj the device pObj + * @param Data FIFO raw data array [6] + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_FIFO_Get_Data(LSM6DSO_Object_t *pObj, uint8_t *Data) +{ + if (lsm6dso_read_reg(&(pObj->Ctx), LSM6DSO_FIFO_DATA_OUT_X_L, Data, 6) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Get the LSM6DSO FIFO accelero single sample (16-bit data per 3 axes) and calculate acceleration [mg] + * @param pObj the device pObj + * @param Acceleration FIFO accelero axes [mg] + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_FIFO_ACC_Get_Axes(LSM6DSO_Object_t *pObj, LSM6DSO_Axes_t *Acceleration) +{ + lsm6dso_axis3bit16_t data_raw; + float_t sensitivity = 0.0f; + float_t acceleration_float_t[3]; + + if (LSM6DSO_FIFO_Get_Data(pObj, data_raw.u8bit) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + if (LSM6DSO_ACC_GetSensitivity(pObj, &sensitivity) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + acceleration_float_t[0] = (float_t)data_raw.i16bit[0] * sensitivity; + acceleration_float_t[1] = (float_t)data_raw.i16bit[1] * sensitivity; + acceleration_float_t[2] = (float_t)data_raw.i16bit[2] * sensitivity; + + Acceleration->x = (int32_t)acceleration_float_t[0]; + Acceleration->y = (int32_t)acceleration_float_t[1]; + Acceleration->z = (int32_t)acceleration_float_t[2]; + + return LSM6DSO_OK; +} + +/** + * @brief Set the LSM6DSO FIFO accelero BDR value + * @param pObj the device pObj + * @param Bdr FIFO accelero BDR value + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_FIFO_ACC_Set_BDR(LSM6DSO_Object_t *pObj, float_t Bdr) +{ + lsm6dso_bdr_xl_t new_bdr; + + new_bdr = (Bdr <= 0.0f) ? LSM6DSO_XL_NOT_BATCHED + : (Bdr <= 12.5f) ? LSM6DSO_XL_BATCHED_AT_12Hz5 + : (Bdr <= 26.0f) ? LSM6DSO_XL_BATCHED_AT_26Hz + : (Bdr <= 52.0f) ? LSM6DSO_XL_BATCHED_AT_52Hz + : (Bdr <= 104.0f) ? LSM6DSO_XL_BATCHED_AT_104Hz + : (Bdr <= 208.0f) ? LSM6DSO_XL_BATCHED_AT_208Hz + : (Bdr <= 417.0f) ? LSM6DSO_XL_BATCHED_AT_417Hz + : (Bdr <= 833.0f) ? LSM6DSO_XL_BATCHED_AT_833Hz + : (Bdr <= 1667.0f) ? LSM6DSO_XL_BATCHED_AT_1667Hz + : (Bdr <= 3333.0f) ? LSM6DSO_XL_BATCHED_AT_3333Hz + : LSM6DSO_XL_BATCHED_AT_6667Hz; + + if (lsm6dso_fifo_xl_batch_set(&(pObj->Ctx), new_bdr) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Get the LSM6DSO FIFO gyro single sample (16-bit data per 3 axes) and calculate angular velocity [mDPS] + * @param pObj the device pObj + * @param AngularVelocity FIFO gyro axes [mDPS] + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_FIFO_GYRO_Get_Axes(LSM6DSO_Object_t *pObj, LSM6DSO_Axes_t *AngularVelocity) +{ + lsm6dso_axis3bit16_t data_raw; + float_t sensitivity = 0.0f; + float_t angular_velocity_float_t[3]; + + if (LSM6DSO_FIFO_Get_Data(pObj, data_raw.u8bit) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + if (LSM6DSO_GYRO_GetSensitivity(pObj, &sensitivity) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + angular_velocity_float_t[0] = (float_t)data_raw.i16bit[0] * sensitivity; + angular_velocity_float_t[1] = (float_t)data_raw.i16bit[1] * sensitivity; + angular_velocity_float_t[2] = (float_t)data_raw.i16bit[2] * sensitivity; + + AngularVelocity->x = (int32_t)angular_velocity_float_t[0]; + AngularVelocity->y = (int32_t)angular_velocity_float_t[1]; + AngularVelocity->z = (int32_t)angular_velocity_float_t[2]; + + return LSM6DSO_OK; +} + +/** + * @brief Set the LSM6DSO FIFO gyro BDR value + * @param pObj the device pObj + * @param Bdr FIFO gyro BDR value + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_FIFO_GYRO_Set_BDR(LSM6DSO_Object_t *pObj, float_t Bdr) +{ + lsm6dso_bdr_gy_t new_bdr; + + new_bdr = (Bdr <= 0.0f) ? LSM6DSO_GY_NOT_BATCHED + : (Bdr <= 12.5f) ? LSM6DSO_GY_BATCHED_AT_12Hz5 + : (Bdr <= 26.0f) ? LSM6DSO_GY_BATCHED_AT_26Hz + : (Bdr <= 52.0f) ? LSM6DSO_GY_BATCHED_AT_52Hz + : (Bdr <= 104.0f) ? LSM6DSO_GY_BATCHED_AT_104Hz + : (Bdr <= 208.0f) ? LSM6DSO_GY_BATCHED_AT_208Hz + : (Bdr <= 417.0f) ? LSM6DSO_GY_BATCHED_AT_417Hz + : (Bdr <= 833.0f) ? LSM6DSO_GY_BATCHED_AT_833Hz + : (Bdr <= 1667.0f) ? LSM6DSO_GY_BATCHED_AT_1667Hz + : (Bdr <= 3333.0f) ? LSM6DSO_GY_BATCHED_AT_3333Hz + : LSM6DSO_GY_BATCHED_AT_6667Hz; + + if (lsm6dso_fifo_gy_batch_set(&(pObj->Ctx), new_bdr) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Enable LSM6DSO accelerometer DRDY interrupt on INT1 + * @param pObj the device pObj + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Enable_DRDY_On_INT1(LSM6DSO_Object_t *pObj) +{ + lsm6dso_pin_int1_route_t pin_int1_route; + + /* Enable accelerometer DRDY Interrupt on INT1 */ + if (lsm6dso_pin_int1_route_get(&(pObj->Ctx), &pin_int1_route) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + pin_int1_route.drdy_xl = 1; + pin_int1_route.drdy_g = 0; + if (lsm6dso_pin_int1_route_set(&(pObj->Ctx), pin_int1_route) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Disable LSM6DSO accelerometer DRDY interrupt on INT1 + * @param pObj the device pObj + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Disable_DRDY_On_INT1(LSM6DSO_Object_t *pObj) +{ + lsm6dso_pin_int1_route_t pin_int1_route; + + /* Disable accelerometer DRDY Interrupt on INT1 */ + if (lsm6dso_pin_int1_route_get(&(pObj->Ctx), &pin_int1_route) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + pin_int1_route.drdy_xl = 0; + if (lsm6dso_pin_int1_route_set(&(pObj->Ctx), pin_int1_route) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Set the LSM6DSO accelerometer power mode + * @param pObj the device pObj + * @param PowerMode Value of the powerMode + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Set_Power_Mode(LSM6DSO_Object_t *pObj, uint8_t PowerMode) +{ + int32_t ret = LSM6DSO_OK; + lsm6dso_xl_hm_mode_t newPowerMode = LSM6DSO_HIGH_PERFORMANCE_MD; + + switch (PowerMode) + { + case 0: + newPowerMode = LSM6DSO_HIGH_PERFORMANCE_MD; + break; + case 1: + newPowerMode = LSM6DSO_LOW_NORMAL_POWER_MD; + break; + case 2: + newPowerMode = LSM6DSO_ULTRA_LOW_POWER_MD; + break; + default: + ret = LSM6DSO_ERROR; + break; + } + + if (ret == LSM6DSO_ERROR) + { + return LSM6DSO_ERROR; + } + + if (lsm6dso_xl_power_mode_set(&(pObj->Ctx), newPowerMode) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Set the LSM6DSO accelerometer filter mode + * @param pObj the device pObj + * @param LowHighPassFlag 0/1 for setting low-pass/high-pass filter mode + * @param FilterMode Value of the filter Mode + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Set_Filter_Mode(LSM6DSO_Object_t *pObj, uint8_t LowHighPassFlag, uint8_t FilterMode) +{ + int32_t ret = LSM6DSO_OK; + lsm6dso_hp_slope_xl_en_t newFilterMode = LSM6DSO_HP_PATH_DISABLE_ON_OUT; + + switch (FilterMode) + { + case 0x00: + newFilterMode = LSM6DSO_HP_PATH_DISABLE_ON_OUT; + break; + case 0x01: + newFilterMode = LSM6DSO_LP_ODR_DIV_10; + break; + case 0x02: + newFilterMode = LSM6DSO_LP_ODR_DIV_20; + break; + case 0x03: + newFilterMode = LSM6DSO_LP_ODR_DIV_45; + break; + case 0x04: + newFilterMode = LSM6DSO_LP_ODR_DIV_100; + break; + case 0x05: + newFilterMode = LSM6DSO_LP_ODR_DIV_200; + break; + case 0x06: + newFilterMode = LSM6DSO_LP_ODR_DIV_400; + break; + case 0x07: + newFilterMode = LSM6DSO_LP_ODR_DIV_800; + break; + case 0x10: + newFilterMode = LSM6DSO_SLOPE_ODR_DIV_4; + break; + case 0x11: + newFilterMode = LSM6DSO_HP_ODR_DIV_10; + break; + case 0x12: + newFilterMode = LSM6DSO_HP_ODR_DIV_20; + break; + case 0x13: + newFilterMode = LSM6DSO_HP_ODR_DIV_45; + break; + case 0x14: + newFilterMode = LSM6DSO_HP_ODR_DIV_100; + break; + case 0x15: + newFilterMode = LSM6DSO_HP_ODR_DIV_200; + break; + case 0x16: + newFilterMode = LSM6DSO_HP_ODR_DIV_400; + break; + case 0x17: + newFilterMode = LSM6DSO_HP_ODR_DIV_800; + break; + case 0x31: + newFilterMode = LSM6DSO_HP_REF_MD_ODR_DIV_10; + break; + case 0x32: + newFilterMode = LSM6DSO_HP_REF_MD_ODR_DIV_20; + break; + case 0x33: + newFilterMode = LSM6DSO_HP_REF_MD_ODR_DIV_45; + break; + case 0x34: + newFilterMode = LSM6DSO_HP_REF_MD_ODR_DIV_100; + break; + case 0x35: + newFilterMode = LSM6DSO_HP_REF_MD_ODR_DIV_200; + break; + case 0x36: + newFilterMode = LSM6DSO_HP_REF_MD_ODR_DIV_400; + break; + case 0x37: + newFilterMode = LSM6DSO_HP_REF_MD_ODR_DIV_800; + break; + default: + ret = LSM6DSO_ERROR; + break; + } + + if (ret == LSM6DSO_ERROR) + { + return LSM6DSO_ERROR; + } + + if (LowHighPassFlag == 0U) + { + /*Set accelerometer low_pass filter-mode*/ + + /*Set to 1 LPF2 bit (CTRL8_XL)*/ + if (lsm6dso_xl_filter_lp2_set(&(pObj->Ctx), 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + if (lsm6dso_xl_hp_path_on_out_set(&(pObj->Ctx), newFilterMode) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + } + else + { + /*Set accelerometer high_pass filter-mode*/ + if (lsm6dso_xl_hp_path_on_out_set(&(pObj->Ctx), newFilterMode) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + } + return LSM6DSO_OK; +} + +/** + * @brief Enable LSM6DSO accelerometer inactivity detection + * @param pObj the device pObj + * @param InactMode inactivity detection mode + * @param IntPin interrupt pin line to be used + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Enable_Inactivity_Detection(LSM6DSO_Object_t *pObj, lsm6dso_inact_en_t InactMode, + LSM6DSO_SensorIntPin_t IntPin) +{ + lsm6dso_pin_int1_route_t val1; + lsm6dso_pin_int2_route_t val2; + int32_t ret = LSM6DSO_OK; + + /* Full scale selection */ + if (LSM6DSO_ACC_SetFullScale(pObj, 2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + if (LSM6DSO_GYRO_SetFullScale(pObj, 250) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* SLEEP_DUR setting */ + if (lsm6dso_act_sleep_dur_set(&(pObj->Ctx), 0x01) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Enable inactivity detection. */ + switch (InactMode) + { + case LSM6DSO_XL_AND_GY_NOT_AFFECTED: + { + if (lsm6dso_act_mode_set(&(pObj->Ctx), LSM6DSO_XL_AND_GY_NOT_AFFECTED) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + break; + } + case LSM6DSO_XL_12Hz5_GY_NOT_AFFECTED: + { + if (lsm6dso_act_mode_set(&(pObj->Ctx), LSM6DSO_XL_12Hz5_GY_NOT_AFFECTED) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + break; + } + case LSM6DSO_XL_12Hz5_GY_SLEEP: + { + if (lsm6dso_act_mode_set(&(pObj->Ctx), LSM6DSO_XL_12Hz5_GY_SLEEP) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + break; + } + case LSM6DSO_XL_12Hz5_GY_PD: + { + if (lsm6dso_act_mode_set(&(pObj->Ctx), LSM6DSO_XL_12Hz5_GY_PD) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + break; + } + default: + ret = LSM6DSO_ERROR; + break; + } + + if (ret == LSM6DSO_ERROR) + { + return LSM6DSO_ERROR; + } + + /* Enable Inactivity event on either INT1 or INT2 pin */ + switch (IntPin) + { + case LSM6DSO_INT1_PIN: + { + if (lsm6dso_pin_int1_route_get(&(pObj->Ctx), &val1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + val1.sleep_change = PROPERTY_ENABLE; + if (lsm6dso_pin_int1_route_set(&(pObj->Ctx), val1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + break; + } + case LSM6DSO_INT2_PIN: + { + if (lsm6dso_pin_int2_route_get(&(pObj->Ctx), NULL, &val2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + val2.sleep_change = PROPERTY_ENABLE; + if (lsm6dso_pin_int2_route_set(&(pObj->Ctx), NULL, val2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + break; + } + default: + ret = LSM6DSO_ERROR; + break; + } + + return ret; +} + +/** + * @brief Disable LSM6DSO accelerometer inactivity detection + * @param pObj the device pObj + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Disable_Inactivity_Detection(LSM6DSO_Object_t *pObj) +{ + lsm6dso_pin_int1_route_t val1; + lsm6dso_pin_int2_route_t val2; + + /* Disable inactivity event on both INT1 and INT2 pins */ + if (lsm6dso_pin_int1_route_get(&(pObj->Ctx), &val1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + val1.sleep_change = PROPERTY_DISABLE; + + if (lsm6dso_pin_int1_route_set(&(pObj->Ctx), val1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + if (lsm6dso_pin_int2_route_get(&(pObj->Ctx), NULL, &val2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + val2.sleep_change = PROPERTY_DISABLE; + + if (lsm6dso_pin_int2_route_set(&(pObj->Ctx), NULL, val2) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* Disable inactivity detection. */ + if (lsm6dso_act_mode_set(&(pObj->Ctx), LSM6DSO_XL_AND_GY_NOT_AFFECTED) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + /* SLEEP_DUR reset */ + if (lsm6dso_act_sleep_dur_set(&(pObj->Ctx), 0x00) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + return LSM6DSO_OK; +} + +/** + * @brief Set LSM6DSO accelerometer sleep duration + * @param pObj the device pObj + * @param Duration wake up detection duration + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_ACC_Set_Sleep_Duration(LSM6DSO_Object_t *pObj, uint8_t Duration) +{ + /* Set wake up duration. */ + if (lsm6dso_act_sleep_dur_set(&(pObj->Ctx), Duration) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Enable LSM6DSO gyroscope DRDY interrupt on INT2 + * @param pObj the device pObj + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_GYRO_Enable_DRDY_On_INT2(LSM6DSO_Object_t *pObj) +{ + lsm6dso_pin_int2_route_t pin_int2_route; + + /* Enable gyroscope DRDY Interrupts on INT2 */ + if (lsm6dso_pin_int2_route_get(&(pObj->Ctx), NULL, &pin_int2_route) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + pin_int2_route.drdy_xl = 0; + pin_int2_route.drdy_g = 1; + if (lsm6dso_pin_int2_route_set(&(pObj->Ctx), NULL, pin_int2_route) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Set the LSM6DSO gyroscope power mode + * @param pObj the device pObj + * @param PowerMode Value of the powerMode + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_GYRO_Set_Power_Mode(LSM6DSO_Object_t *pObj, uint8_t PowerMode) +{ + int32_t ret = LSM6DSO_OK; + lsm6dso_g_hm_mode_t newPowerMode = LSM6DSO_GY_HIGH_PERFORMANCE; + + switch (PowerMode) + { + case 0: + newPowerMode = LSM6DSO_GY_HIGH_PERFORMANCE; + break; + case 1: + newPowerMode = LSM6DSO_GY_NORMAL; + break; + default: + ret = LSM6DSO_ERROR; + break; + } + + if (ret == LSM6DSO_ERROR) + { + return LSM6DSO_ERROR; + } + + if (lsm6dso_gy_power_mode_set(&(pObj->Ctx), newPowerMode) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Set the LSM6DSO gyroscope filter mode + * @param pObj the device pObj + * @param LowHighPassFlag 0/1 for setting low-pass/high-pass filter mode + * @param FilterMode Value of the filter Mode + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_GYRO_Set_Filter_Mode(LSM6DSO_Object_t *pObj, uint8_t LowHighPassFlag, uint8_t FilterMode) +{ + int32_t ret = LSM6DSO_OK; + + if (LowHighPassFlag == 0U) + { + lsm6dso_ftype_t newFilterMode = LSM6DSO_ULTRA_LIGHT; + + switch (FilterMode) + { + case 0: + newFilterMode = LSM6DSO_ULTRA_LIGHT; + break; + case 1: + newFilterMode = LSM6DSO_VERY_LIGHT; + break; + case 2: + newFilterMode = LSM6DSO_LIGHT; + break; + case 3: + newFilterMode = LSM6DSO_MEDIUM; + break; + case 4: + newFilterMode = LSM6DSO_STRONG; + break; + case 5: + newFilterMode = LSM6DSO_VERY_STRONG; + break; + case 6: + newFilterMode = LSM6DSO_AGGRESSIVE; + break; + case 7: + newFilterMode = LSM6DSO_XTREME; + break; + default: + ret = LSM6DSO_ERROR; + break; + } + + if (ret == LSM6DSO_ERROR) + { + return LSM6DSO_ERROR; + } + /*Set gyroscope low_pass 1 filter-mode*/ + /* Enable low-pass filter */ + if (lsm6dso_gy_filter_lp1_set(&(pObj->Ctx), 1) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + if (lsm6dso_gy_lp1_bandwidth_set(&(pObj->Ctx), newFilterMode) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + } + else + { + lsm6dso_hpm_g_t newFilterMode = LSM6DSO_HP_FILTER_NONE; + + switch (FilterMode) + { + case 0x00: + newFilterMode = LSM6DSO_HP_FILTER_NONE; + break; + case 0x80: + newFilterMode = LSM6DSO_HP_FILTER_16mHz; + break; + case 0x81: + newFilterMode = LSM6DSO_HP_FILTER_65mHz; + break; + case 0x82: + newFilterMode = LSM6DSO_HP_FILTER_260mHz; + break; + case 0x83: + newFilterMode = LSM6DSO_HP_FILTER_1Hz04; + break; + default: + ret = LSM6DSO_ERROR; + break; + } + + if (ret == LSM6DSO_ERROR) + { + return LSM6DSO_ERROR; + } + + /*Set gyroscope high_pass filter-mode*/ + /* Enable high-pass filter */ + if (lsm6dso_gy_hp_path_internal_set(&(pObj->Ctx), newFilterMode) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + } + return LSM6DSO_OK; +} + +/** + * @brief Set LSM6DSO DRDY mode + * @param pObj the device pObj + * @param Mode DRDY mode + * @retval 0 in case of success, an error code otherwise + */ +int32_t LSM6DSO_DRDY_Set_Mode(LSM6DSO_Object_t *pObj, uint8_t Mode) +{ + int32_t ret = LSM6DSO_OK; + lsm6dso_dataready_pulsed_t newMode = LSM6DSO_DRDY_LATCHED; + + switch (Mode) + { + case 0: + newMode = LSM6DSO_DRDY_LATCHED; + break; + case 1: + newMode = LSM6DSO_DRDY_PULSED; + break; + default: + ret = LSM6DSO_ERROR; + break; + } + + if (ret == LSM6DSO_ERROR) + { + return LSM6DSO_ERROR; + } + + /* Set DRDY mode */ + if (lsm6dso_data_ready_mode_set(&(pObj->Ctx), newMode) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @} + */ + +/** @defgroup LSM6DSO_Private_Functions LSM6DSO Private Functions + * @{ + */ + +/** + * @brief Set the LSM6DSO accelerometer sensor output data rate when enabled + * @param pObj the device pObj + * @param Odr the functional output data rate to be set + * @retval 0 in case of success, an error code otherwise + */ +static int32_t LSM6DSO_ACC_SetOutputDataRate_When_Enabled(LSM6DSO_Object_t *pObj, float_t Odr) +{ + lsm6dso_odr_xl_t new_odr; + + new_odr = (Odr <= 1.6f) ? LSM6DSO_XL_ODR_1Hz6 + : (Odr <= 12.5f) ? LSM6DSO_XL_ODR_12Hz5 + : (Odr <= 26.0f) ? LSM6DSO_XL_ODR_26Hz + : (Odr <= 52.0f) ? LSM6DSO_XL_ODR_52Hz + : (Odr <= 104.0f) ? LSM6DSO_XL_ODR_104Hz + : (Odr <= 208.0f) ? LSM6DSO_XL_ODR_208Hz + : (Odr <= 417.0f) ? LSM6DSO_XL_ODR_417Hz + : (Odr <= 833.0f) ? LSM6DSO_XL_ODR_833Hz + : (Odr <= 1667.0f) ? LSM6DSO_XL_ODR_1667Hz + : (Odr <= 3333.0f) ? LSM6DSO_XL_ODR_3333Hz + : LSM6DSO_XL_ODR_6667Hz; + + /* Output data rate selection. */ + if (lsm6dso_xl_data_rate_set(&(pObj->Ctx), new_odr) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Set the LSM6DSO accelerometer sensor output data rate when disabled + * @param pObj the device pObj + * @param Odr the functional output data rate to be set + * @retval 0 in case of success, an error code otherwise + */ +static int32_t LSM6DSO_ACC_SetOutputDataRate_When_Disabled(LSM6DSO_Object_t *pObj, float_t Odr) +{ + pObj->acc_odr = (Odr <= 1.6f) ? LSM6DSO_XL_ODR_1Hz6 + : (Odr <= 12.5f) ? LSM6DSO_XL_ODR_12Hz5 + : (Odr <= 26.0f) ? LSM6DSO_XL_ODR_26Hz + : (Odr <= 52.0f) ? LSM6DSO_XL_ODR_52Hz + : (Odr <= 104.0f) ? LSM6DSO_XL_ODR_104Hz + : (Odr <= 208.0f) ? LSM6DSO_XL_ODR_208Hz + : (Odr <= 417.0f) ? LSM6DSO_XL_ODR_417Hz + : (Odr <= 833.0f) ? LSM6DSO_XL_ODR_833Hz + : (Odr <= 1667.0f) ? LSM6DSO_XL_ODR_1667Hz + : (Odr <= 3333.0f) ? LSM6DSO_XL_ODR_3333Hz + : LSM6DSO_XL_ODR_6667Hz; + + return LSM6DSO_OK; +} + +/** + * @brief Set the LSM6DSO gyroscope sensor output data rate when enabled + * @param pObj the device pObj + * @param Odr the functional output data rate to be set + * @retval 0 in case of success, an error code otherwise + */ +static int32_t LSM6DSO_GYRO_SetOutputDataRate_When_Enabled(LSM6DSO_Object_t *pObj, float_t Odr) +{ + lsm6dso_odr_g_t new_odr; + + new_odr = (Odr <= 12.5f) ? LSM6DSO_GY_ODR_12Hz5 + : (Odr <= 26.0f) ? LSM6DSO_GY_ODR_26Hz + : (Odr <= 52.0f) ? LSM6DSO_GY_ODR_52Hz + : (Odr <= 104.0f) ? LSM6DSO_GY_ODR_104Hz + : (Odr <= 208.0f) ? LSM6DSO_GY_ODR_208Hz + : (Odr <= 417.0f) ? LSM6DSO_GY_ODR_417Hz + : (Odr <= 833.0f) ? LSM6DSO_GY_ODR_833Hz + : (Odr <= 1667.0f) ? LSM6DSO_GY_ODR_1667Hz + : (Odr <= 3333.0f) ? LSM6DSO_GY_ODR_3333Hz + : LSM6DSO_GY_ODR_6667Hz; + + /* Output data rate selection. */ + if (lsm6dso_gy_data_rate_set(&(pObj->Ctx), new_odr) != LSM6DSO_OK) + { + return LSM6DSO_ERROR; + } + + return LSM6DSO_OK; +} + +/** + * @brief Set the LSM6DSO gyroscope sensor output data rate when disabled + * @param pObj the device pObj + * @param Odr the functional output data rate to be set + * @retval 0 in case of success, an error code otherwise + */ +static int32_t LSM6DSO_GYRO_SetOutputDataRate_When_Disabled(LSM6DSO_Object_t *pObj, float_t Odr) +{ + pObj->gyro_odr = (Odr <= 12.5f) ? LSM6DSO_GY_ODR_12Hz5 + : (Odr <= 26.0f) ? LSM6DSO_GY_ODR_26Hz + : (Odr <= 52.0f) ? LSM6DSO_GY_ODR_52Hz + : (Odr <= 104.0f) ? LSM6DSO_GY_ODR_104Hz + : (Odr <= 208.0f) ? LSM6DSO_GY_ODR_208Hz + : (Odr <= 417.0f) ? LSM6DSO_GY_ODR_417Hz + : (Odr <= 833.0f) ? LSM6DSO_GY_ODR_833Hz + : (Odr <= 1667.0f) ? LSM6DSO_GY_ODR_1667Hz + : (Odr <= 3333.0f) ? LSM6DSO_GY_ODR_3333Hz + : LSM6DSO_GY_ODR_6667Hz; + + return LSM6DSO_OK; +} + +/** + * @brief This function provides a minimum delay based on Tick counter + * @param pObj the device pObj + * @param msDelay delay expressed in ms + * @retval None + */ +static void LSM6DSO_Delay(LSM6DSO_Object_t *pObj, uint32_t msDelay) +{ + uint32_t tickstart = pObj->IO.GetTick(); + + while ((pObj->IO.GetTick() - tickstart) < msDelay) + { + } +} + +/** + * @brief Wrap Read register component function to Bus IO function + * @param Handle the device handler + * @param Reg the register address + * @param pData the stored data pointer + * @param Length the length + * @retval 0 in case of success, an error code otherwise + */ +static int32_t ReadRegWrap(void *Handle, uint8_t Reg, uint8_t *pData, uint16_t Length) +{ + LSM6DSO_Object_t *pObj = (LSM6DSO_Object_t *)Handle; + + return pObj->IO.ReadReg(pObj->IO.Address, Reg, pData, Length); +} + +/** + * @brief Wrap Write register component function to Bus IO function + * @param Handle the device handler + * @param Reg the register address + * @param pData the stored data pointer + * @param Length the length + * @retval 0 in case of success, an error code otherwise + */ +static int32_t WriteRegWrap(void *Handle, uint8_t Reg, uint8_t *pData, uint16_t Length) +{ + LSM6DSO_Object_t *pObj = (LSM6DSO_Object_t *)Handle; + + return pObj->IO.WriteReg(pObj->IO.Address, Reg, pData, Length); +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/airmouse/lib/lsm6dso-api/lsm6dso.h b/airmouse/lib/lsm6dso-api/lsm6dso.h new file mode 100644 index 00000000000..1843df0ac86 --- /dev/null +++ b/airmouse/lib/lsm6dso-api/lsm6dso.h @@ -0,0 +1,369 @@ +/** + ****************************************************************************** + * @file lsm6dso.h + * @author MEMS Software Solutions Team + * @brief LSM6DSO header driver file + ****************************************************************************** + * @attention + * + * Copyright (c) 2019 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef LSM6DSO_H +#define LSM6DSO_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "lsm6dso_reg.h" +#include + +/** @addtogroup BSP BSP + * @{ + */ + +/** @addtogroup Component Component + * @{ + */ + +/** @addtogroup LSM6DSO LSM6DSO + * @{ + */ + +/** @defgroup LSM6DSO_Exported_Types LSM6DSO Exported Types + * @{ + */ + +typedef int32_t (*LSM6DSO_Init_Func)(void); +typedef int32_t (*LSM6DSO_DeInit_Func)(void); +typedef int32_t (*LSM6DSO_GetTick_Func)(void); +typedef void (*LSM6DSO_Delay_Func)(uint32_t); +typedef int32_t (*LSM6DSO_WriteReg_Func)(uint16_t, uint16_t, uint8_t *, uint16_t); +typedef int32_t (*LSM6DSO_ReadReg_Func)(uint16_t, uint16_t, uint8_t *, uint16_t); + +typedef enum +{ + LSM6DSO_INT1_PIN, + LSM6DSO_INT2_PIN, +} LSM6DSO_SensorIntPin_t; + +typedef enum +{ + LSM6DSO_ACC_HIGH_PERFORMANCE_MODE, + LSM6DSO_ACC_LOW_POWER_NORMAL_MODE, + LSM6DSO_ACC_ULTRA_LOW_POWER_MODE +} LSM6DSO_ACC_Operating_Mode_t; + +typedef enum +{ + LSM6DSO_GYRO_HIGH_PERFORMANCE_MODE, + LSM6DSO_GYRO_LOW_POWER_NORMAL_MODE +} LSM6DSO_GYRO_Operating_Mode_t; + +typedef struct +{ + LSM6DSO_Init_Func Init; + LSM6DSO_DeInit_Func DeInit; + uint32_t BusType; /*0 means I2C, 1 means SPI 4-Wires, 2 means SPI-3-Wires */ + uint8_t Address; + LSM6DSO_WriteReg_Func WriteReg; + LSM6DSO_ReadReg_Func ReadReg; + LSM6DSO_GetTick_Func GetTick; + LSM6DSO_Delay_Func Delay; +} LSM6DSO_IO_t; + + +typedef struct +{ + int16_t x; + int16_t y; + int16_t z; +} LSM6DSO_AxesRaw_t; + +typedef struct +{ + int32_t x; + int32_t y; + int32_t z; +} LSM6DSO_Axes_t; + +typedef struct +{ + unsigned int FreeFallStatus : 1; + unsigned int TapStatus : 1; + unsigned int DoubleTapStatus : 1; + unsigned int WakeUpStatus : 1; + unsigned int StepStatus : 1; + unsigned int TiltStatus : 1; + unsigned int D6DOrientationStatus : 1; + unsigned int SleepStatus : 1; +} LSM6DSO_Event_Status_t; + +typedef struct +{ + LSM6DSO_IO_t IO; + stmdev_ctx_t Ctx; + uint8_t is_initialized; + uint8_t acc_is_enabled; + uint8_t gyro_is_enabled; + lsm6dso_odr_xl_t acc_odr; + lsm6dso_odr_g_t gyro_odr; +} LSM6DSO_Object_t; + +typedef struct +{ + uint8_t Acc; + uint8_t Gyro; + uint8_t Magneto; + uint8_t LowPower; + uint32_t GyroMaxFS; + uint32_t AccMaxFS; + uint32_t MagMaxFS; + float_t GyroMaxOdr; + float_t AccMaxOdr; + float_t MagMaxOdr; +} LSM6DSO_Capabilities_t; + +typedef struct +{ + int32_t (*Init)(LSM6DSO_Object_t *); + int32_t (*DeInit)(LSM6DSO_Object_t *); + int32_t (*ReadID)(LSM6DSO_Object_t *, uint8_t *); + int32_t (*GetCapabilities)(LSM6DSO_Object_t *, LSM6DSO_Capabilities_t *); +} LSM6DSO_CommonDrv_t; + +typedef struct +{ + int32_t (*Enable)(LSM6DSO_Object_t *); + int32_t (*Disable)(LSM6DSO_Object_t *); + int32_t (*GetSensitivity)(LSM6DSO_Object_t *, float_t *); + int32_t (*GetOutputDataRate)(LSM6DSO_Object_t *, float_t *); + int32_t (*SetOutputDataRate)(LSM6DSO_Object_t *, float_t); + int32_t (*GetFullScale)(LSM6DSO_Object_t *, int32_t *); + int32_t (*SetFullScale)(LSM6DSO_Object_t *, int32_t); + int32_t (*GetAxes)(LSM6DSO_Object_t *, LSM6DSO_Axes_t *); + int32_t (*GetAxesRaw)(LSM6DSO_Object_t *, LSM6DSO_AxesRaw_t *); +} LSM6DSO_ACC_Drv_t; + +typedef struct +{ + int32_t (*Enable)(LSM6DSO_Object_t *); + int32_t (*Disable)(LSM6DSO_Object_t *); + int32_t (*GetSensitivity)(LSM6DSO_Object_t *, float_t *); + int32_t (*GetOutputDataRate)(LSM6DSO_Object_t *, float_t *); + int32_t (*SetOutputDataRate)(LSM6DSO_Object_t *, float_t); + int32_t (*GetFullScale)(LSM6DSO_Object_t *, int32_t *); + int32_t (*SetFullScale)(LSM6DSO_Object_t *, int32_t); + int32_t (*GetAxes)(LSM6DSO_Object_t *, LSM6DSO_Axes_t *); + int32_t (*GetAxesRaw)(LSM6DSO_Object_t *, LSM6DSO_AxesRaw_t *); +} LSM6DSO_GYRO_Drv_t; + +typedef union +{ + int16_t i16bit[3]; + uint8_t u8bit[6]; +} lsm6dso_axis3bit16_t; + +typedef union +{ + int16_t i16bit; + uint8_t u8bit[2]; +} lsm6dso_axis1bit16_t; + +typedef union +{ + int32_t i32bit[3]; + uint8_t u8bit[12]; +} lsm6dso_axis3bit32_t; + +typedef union +{ + int32_t i32bit; + uint8_t u8bit[4]; +} lsm6dso_axis1bit32_t; + +/** + * @} + */ + +/** @defgroup LSM6DSO_Exported_Constants LSM6DSO Exported Constants + * @{ + */ + +#define LSM6DSO_OK 0 +#define LSM6DSO_ERROR -1 + +#define LSM6DSO_I2C_BUS 0U +#define LSM6DSO_SPI_4WIRES_BUS 1U +#define LSM6DSO_SPI_3WIRES_BUS 2U + +#define LSM6DSO_ACC_SENSITIVITY_FS_2G 0.061f +#define LSM6DSO_ACC_SENSITIVITY_FS_4G 0.122f +#define LSM6DSO_ACC_SENSITIVITY_FS_8G 0.244f +#define LSM6DSO_ACC_SENSITIVITY_FS_16G 0.488f + +#define LSM6DSO_GYRO_SENSITIVITY_FS_125DPS 4.375f +#define LSM6DSO_GYRO_SENSITIVITY_FS_250DPS 8.750f +#define LSM6DSO_GYRO_SENSITIVITY_FS_500DPS 17.500f +#define LSM6DSO_GYRO_SENSITIVITY_FS_1000DPS 35.000f +#define LSM6DSO_GYRO_SENSITIVITY_FS_2000DPS 70.000f + +/** + * @} + */ + +/** @addtogroup LSM6DSO_Exported_Functions LSM6DSO Exported Functions + * @{ + */ + +int32_t LSM6DSO_RegisterBusIO(LSM6DSO_Object_t *pObj, LSM6DSO_IO_t *pIO); +int32_t LSM6DSO_Init(LSM6DSO_Object_t *pObj); +int32_t LSM6DSO_DeInit(LSM6DSO_Object_t *pObj); +int32_t LSM6DSO_ReadID(LSM6DSO_Object_t *pObj, uint8_t *Id); +int32_t LSM6DSO_GetCapabilities(LSM6DSO_Object_t *pObj, LSM6DSO_Capabilities_t *Capabilities); + +int32_t LSM6DSO_ACC_Enable(LSM6DSO_Object_t *pObj); +int32_t LSM6DSO_ACC_Disable(LSM6DSO_Object_t *pObj); +int32_t LSM6DSO_ACC_GetSensitivity(LSM6DSO_Object_t *pObj, float_t *Sensitivity); +int32_t LSM6DSO_ACC_GetOutputDataRate(LSM6DSO_Object_t *pObj, float_t *Odr); +int32_t LSM6DSO_ACC_SetOutputDataRate(LSM6DSO_Object_t *pObj, float_t Odr); +int32_t LSM6DSO_ACC_SetOutputDataRate_With_Mode(LSM6DSO_Object_t *pObj, float_t Odr, LSM6DSO_ACC_Operating_Mode_t Mode); +int32_t LSM6DSO_ACC_GetFullScale(LSM6DSO_Object_t *pObj, int32_t *FullScale); +int32_t LSM6DSO_ACC_SetFullScale(LSM6DSO_Object_t *pObj, int32_t FullScale); +int32_t LSM6DSO_ACC_GetAxesRaw(LSM6DSO_Object_t *pObj, LSM6DSO_AxesRaw_t *Value); +int32_t LSM6DSO_ACC_GetAxes(LSM6DSO_Object_t *pObj, LSM6DSO_Axes_t *Acceleration); + +int32_t LSM6DSO_GYRO_Enable(LSM6DSO_Object_t *pObj); +int32_t LSM6DSO_GYRO_Disable(LSM6DSO_Object_t *pObj); +int32_t LSM6DSO_GYRO_GetSensitivity(LSM6DSO_Object_t *pObj, float_t *Sensitivity); +int32_t LSM6DSO_GYRO_GetOutputDataRate(LSM6DSO_Object_t *pObj, float_t *Odr); +int32_t LSM6DSO_GYRO_SetOutputDataRate(LSM6DSO_Object_t *pObj, float_t Odr); +int32_t LSM6DSO_GYRO_SetOutputDataRate_With_Mode(LSM6DSO_Object_t *pObj, float_t Odr, + LSM6DSO_GYRO_Operating_Mode_t Mode); +int32_t LSM6DSO_GYRO_GetFullScale(LSM6DSO_Object_t *pObj, int32_t *FullScale); +int32_t LSM6DSO_GYRO_SetFullScale(LSM6DSO_Object_t *pObj, int32_t FullScale); +int32_t LSM6DSO_GYRO_GetAxesRaw(LSM6DSO_Object_t *pObj, LSM6DSO_AxesRaw_t *Value); +int32_t LSM6DSO_GYRO_GetAxes(LSM6DSO_Object_t *pObj, LSM6DSO_Axes_t *AngularRate); + +int32_t LSM6DSO_Read_Reg(LSM6DSO_Object_t *pObj, uint8_t reg, uint8_t *Data); +int32_t LSM6DSO_Write_Reg(LSM6DSO_Object_t *pObj, uint8_t reg, uint8_t Data); +int32_t LSM6DSO_Set_Interrupt_Latch(LSM6DSO_Object_t *pObj, uint8_t Status); + +int32_t LSM6DSO_ACC_Enable_Free_Fall_Detection(LSM6DSO_Object_t *pObj, LSM6DSO_SensorIntPin_t IntPin); +int32_t LSM6DSO_ACC_Disable_Free_Fall_Detection(LSM6DSO_Object_t *pObj); +int32_t LSM6DSO_ACC_Set_Free_Fall_Threshold(LSM6DSO_Object_t *pObj, uint8_t Threshold); +int32_t LSM6DSO_ACC_Set_Free_Fall_Duration(LSM6DSO_Object_t *pObj, uint8_t Duration); + +int32_t LSM6DSO_ACC_Enable_Pedometer(LSM6DSO_Object_t *pObj); +int32_t LSM6DSO_ACC_Disable_Pedometer(LSM6DSO_Object_t *pObj); +int32_t LSM6DSO_ACC_Get_Step_Count(LSM6DSO_Object_t *pObj, uint16_t *StepCount); +int32_t LSM6DSO_ACC_Step_Counter_Reset(LSM6DSO_Object_t *pObj); + +int32_t LSM6DSO_ACC_Enable_Tilt_Detection(LSM6DSO_Object_t *pObj, LSM6DSO_SensorIntPin_t IntPin); +int32_t LSM6DSO_ACC_Disable_Tilt_Detection(LSM6DSO_Object_t *pObj); + +int32_t LSM6DSO_ACC_Enable_Wake_Up_Detection(LSM6DSO_Object_t *pObj, LSM6DSO_SensorIntPin_t IntPin); +int32_t LSM6DSO_ACC_Disable_Wake_Up_Detection(LSM6DSO_Object_t *pObj); +int32_t LSM6DSO_ACC_Set_Wake_Up_Threshold(LSM6DSO_Object_t *pObj, uint8_t Threshold); +int32_t LSM6DSO_ACC_Set_Wake_Up_Duration(LSM6DSO_Object_t *pObj, uint8_t Duration); + +int32_t LSM6DSO_ACC_Enable_Single_Tap_Detection(LSM6DSO_Object_t *pObj, LSM6DSO_SensorIntPin_t IntPin); +int32_t LSM6DSO_ACC_Disable_Single_Tap_Detection(LSM6DSO_Object_t *pObj); +int32_t LSM6DSO_ACC_Enable_Double_Tap_Detection(LSM6DSO_Object_t *pObj, LSM6DSO_SensorIntPin_t IntPin); +int32_t LSM6DSO_ACC_Disable_Double_Tap_Detection(LSM6DSO_Object_t *pObj); +int32_t LSM6DSO_ACC_Set_Tap_Threshold(LSM6DSO_Object_t *pObj, uint8_t Threshold); +int32_t LSM6DSO_ACC_Set_Tap_Shock_Time(LSM6DSO_Object_t *pObj, uint8_t Time); +int32_t LSM6DSO_ACC_Set_Tap_Quiet_Time(LSM6DSO_Object_t *pObj, uint8_t Time); +int32_t LSM6DSO_ACC_Set_Tap_Duration_Time(LSM6DSO_Object_t *pObj, uint8_t Time); + +int32_t LSM6DSO_ACC_Enable_6D_Orientation(LSM6DSO_Object_t *pObj, LSM6DSO_SensorIntPin_t IntPin); +int32_t LSM6DSO_ACC_Disable_6D_Orientation(LSM6DSO_Object_t *pObj); +int32_t LSM6DSO_ACC_Set_6D_Orientation_Threshold(LSM6DSO_Object_t *pObj, uint8_t Threshold); +int32_t LSM6DSO_ACC_Get_6D_Orientation_XL(LSM6DSO_Object_t *pObj, uint8_t *XLow); +int32_t LSM6DSO_ACC_Get_6D_Orientation_XH(LSM6DSO_Object_t *pObj, uint8_t *XHigh); +int32_t LSM6DSO_ACC_Get_6D_Orientation_YL(LSM6DSO_Object_t *pObj, uint8_t *YLow); +int32_t LSM6DSO_ACC_Get_6D_Orientation_YH(LSM6DSO_Object_t *pObj, uint8_t *YHigh); +int32_t LSM6DSO_ACC_Get_6D_Orientation_ZL(LSM6DSO_Object_t *pObj, uint8_t *ZLow); +int32_t LSM6DSO_ACC_Get_6D_Orientation_ZH(LSM6DSO_Object_t *pObj, uint8_t *ZHigh); + +int32_t LSM6DSO_ACC_Get_DRDY_Status(LSM6DSO_Object_t *pObj, uint8_t *Status); +int32_t LSM6DSO_ACC_Get_Event_Status(LSM6DSO_Object_t *pObj, LSM6DSO_Event_Status_t *Status); +int32_t LSM6DSO_ACC_Set_SelfTest(LSM6DSO_Object_t *pObj, uint8_t Status); + +int32_t LSM6DSO_GYRO_Get_DRDY_Status(LSM6DSO_Object_t *pObj, uint8_t *Status); +int32_t LSM6DSO_GYRO_Set_SelfTest(LSM6DSO_Object_t *pObj, uint8_t Status); + +int32_t LSM6DSO_FIFO_Get_Num_Samples(LSM6DSO_Object_t *pObj, uint16_t *NumSamples); +int32_t LSM6DSO_FIFO_Get_Full_Status(LSM6DSO_Object_t *pObj, uint8_t *Status); +int32_t LSM6DSO_FIFO_Set_INT1_FIFO_Full(LSM6DSO_Object_t *pObj, uint8_t Status); +int32_t LSM6DSO_FIFO_Set_Watermark_Level(LSM6DSO_Object_t *pObj, uint16_t Watermark); +int32_t LSM6DSO_FIFO_Set_Stop_On_Fth(LSM6DSO_Object_t *pObj, uint8_t Status); +int32_t LSM6DSO_FIFO_Set_Mode(LSM6DSO_Object_t *pObj, uint8_t Mode); +int32_t LSM6DSO_FIFO_Get_Tag(LSM6DSO_Object_t *pObj, uint8_t *Tag); +int32_t LSM6DSO_FIFO_Get_Data(LSM6DSO_Object_t *pObj, uint8_t *Data); +int32_t LSM6DSO_FIFO_Get_Empty_Status(LSM6DSO_Object_t *pObj, uint8_t *Status); +int32_t LSM6DSO_FIFO_Get_Overrun_Status(LSM6DSO_Object_t *pObj, uint8_t *Status); +int32_t LSM6DSO_FIFO_ACC_Get_Axes(LSM6DSO_Object_t *pObj, LSM6DSO_Axes_t *Acceleration); +int32_t LSM6DSO_FIFO_ACC_Set_BDR(LSM6DSO_Object_t *pObj, float_t Bdr); +int32_t LSM6DSO_FIFO_GYRO_Get_Axes(LSM6DSO_Object_t *pObj, LSM6DSO_Axes_t *AngularVelocity); +int32_t LSM6DSO_FIFO_GYRO_Set_BDR(LSM6DSO_Object_t *pObj, float_t Bdr); + +int32_t LSM6DSO_ACC_Enable_DRDY_On_INT1(LSM6DSO_Object_t *pObj); +int32_t LSM6DSO_ACC_Disable_DRDY_On_INT1(LSM6DSO_Object_t *pObj); +int32_t LSM6DSO_ACC_Set_Power_Mode(LSM6DSO_Object_t *pObj, uint8_t PowerMode); +int32_t LSM6DSO_ACC_Set_Filter_Mode(LSM6DSO_Object_t *pObj, uint8_t LowHighPassFlag, uint8_t FilterMode); +int32_t LSM6DSO_ACC_Enable_Inactivity_Detection(LSM6DSO_Object_t *pObj, lsm6dso_inact_en_t InactMode, + LSM6DSO_SensorIntPin_t IntPin); +int32_t LSM6DSO_ACC_Disable_Inactivity_Detection(LSM6DSO_Object_t *pObj); +int32_t LSM6DSO_ACC_Set_Sleep_Duration(LSM6DSO_Object_t *pObj, uint8_t Duration); + +int32_t LSM6DSO_GYRO_Enable_DRDY_On_INT2(LSM6DSO_Object_t *pObj); +int32_t LSM6DSO_GYRO_Set_Power_Mode(LSM6DSO_Object_t *pObj, uint8_t PowerMode); +int32_t LSM6DSO_GYRO_Set_Filter_Mode(LSM6DSO_Object_t *pObj, uint8_t LowHighPassFlag, uint8_t FilterMode); + +int32_t LSM6DSO_DRDY_Set_Mode(LSM6DSO_Object_t *pObj, uint8_t Mode); + +/** + * @} + */ + +/** @addtogroup LSM6DSO_Exported_Variables LSM6DSO Exported Variables + * @{ + */ + +extern LSM6DSO_CommonDrv_t LSM6DSO_COMMON_Driver; +extern LSM6DSO_ACC_Drv_t LSM6DSO_ACC_Driver; +extern LSM6DSO_GYRO_Drv_t LSM6DSO_GYRO_Driver; + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/airmouse/lib/lsm6dso-api/lsm6dso_reg.c b/airmouse/lib/lsm6dso-api/lsm6dso_reg.c new file mode 100644 index 00000000000..9eb6542ee37 --- /dev/null +++ b/airmouse/lib/lsm6dso-api/lsm6dso_reg.c @@ -0,0 +1,13139 @@ +/** + ****************************************************************************** + * @file lsm6dso_reg.c + * @author Sensors Software Solution Team + * @brief LSM6DSO driver file + ****************************************************************************** + * @attention + * + * Copyright (c) 2019 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +#include "lsm6dso_reg.h" +#include + +/** + * @defgroup LSM6DSO + * @brief This file provides a set of functions needed to drive the + * lsm6dso enhanced inertial module. + * @{ + * + */ + +/** + * @defgroup LSM6DSO_Interfaces_Functions + * @brief This section provide a set of functions used to read and + * write a generic register of the device. + * MANDATORY: return 0 -> no Error. + * @{ + * + */ + +/** + * @brief Read generic device register + * + * @param ctx read / write interface definitions(ptr) + * @param reg register to read + * @param data pointer to buffer that store the data read(ptr) + * @param len number of consecutive register to read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t __weak lsm6dso_read_reg(stmdev_ctx_t *ctx, uint8_t reg, + uint8_t *data, + uint16_t len) +{ + int32_t ret; + + ret = ctx->read_reg(ctx->handle, reg, data, len); + + return ret; +} + +/** + * @brief Write generic device register + * + * @param ctx read / write interface definitions(ptr) + * @param reg register to write + * @param data pointer to data to write in register reg(ptr) + * @param len number of consecutive register to write + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t __weak lsm6dso_write_reg(stmdev_ctx_t *ctx, uint8_t reg, + uint8_t *data, + uint16_t len) +{ + int32_t ret; + + ret = ctx->write_reg(ctx->handle, reg, data, len); + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DSOX_Private_functions + * @brief Section collect all the utility functions needed by APIs. + * @{ + * + */ + +static void bytecpy(uint8_t *target, uint8_t *source) +{ + if ((target != NULL) && (source != NULL)) + { + *target = *source; + } +} + +/** + * @defgroup LSM6DSO_Sensitivity + * @brief These functions convert raw-data into engineering units. + * @{ + * + */ +float_t lsm6dso_from_fs2_to_mg(int16_t lsb) +{ + return ((float_t)lsb) * 0.061f; +} + +float_t lsm6dso_from_fs4_to_mg(int16_t lsb) +{ + return ((float_t)lsb) * 0.122f; +} + +float_t lsm6dso_from_fs8_to_mg(int16_t lsb) +{ + return ((float_t)lsb) * 0.244f; +} + +float_t lsm6dso_from_fs16_to_mg(int16_t lsb) +{ + return ((float_t)lsb) * 0.488f; +} + +float_t lsm6dso_from_fs125_to_mdps(int16_t lsb) +{ + return ((float_t)lsb) * 4.375f; +} + +float_t lsm6dso_from_fs500_to_mdps(int16_t lsb) +{ + return ((float_t)lsb) * 17.50f; +} + +float_t lsm6dso_from_fs250_to_mdps(int16_t lsb) +{ + return ((float_t)lsb) * 8.750f; +} + +float_t lsm6dso_from_fs1000_to_mdps(int16_t lsb) +{ + return ((float_t)lsb) * 35.0f; +} + +float_t lsm6dso_from_fs2000_to_mdps(int16_t lsb) +{ + return ((float_t)lsb) * 70.0f; +} + +float_t lsm6dso_from_lsb_to_celsius(int16_t lsb) +{ + return (((float_t)lsb / 256.0f) + 25.0f); +} + +float_t lsm6dso_from_lsb_to_nsec(int16_t lsb) +{ + return ((float_t)lsb * 25000.0f); +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DSO_Data_Generation + * @brief This section groups all the functions concerning + * data generation. + * + */ + +/** + * @brief Accelerometer full-scale selection.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of fs_xl in reg CTRL1_XL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_xl_full_scale_set(stmdev_ctx_t *ctx, + lsm6dso_fs_xl_t val) +{ + lsm6dso_ctrl1_xl_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL1_XL, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.fs_xl = (uint8_t) val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL1_XL, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Accelerometer full-scale selection.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of fs_xl in reg CTRL1_XL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_xl_full_scale_get(stmdev_ctx_t *ctx, + lsm6dso_fs_xl_t *val) +{ + lsm6dso_ctrl1_xl_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL1_XL, (uint8_t *)®, 1); + + switch (reg.fs_xl) + { + case LSM6DSO_2g: + *val = LSM6DSO_2g; + break; + + case LSM6DSO_16g: + *val = LSM6DSO_16g; + break; + + case LSM6DSO_4g: + *val = LSM6DSO_4g; + break; + + case LSM6DSO_8g: + *val = LSM6DSO_8g; + break; + + default: + *val = LSM6DSO_2g; + break; + } + + return ret; +} + +/** + * @brief Accelerometer UI data rate selection.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of odr_xl in reg CTRL1_XL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_xl_data_rate_set(stmdev_ctx_t *ctx, + lsm6dso_odr_xl_t val) +{ + lsm6dso_odr_xl_t odr_xl = val; + lsm6dso_emb_fsm_enable_t fsm_enable; + lsm6dso_fsm_odr_t fsm_odr; + lsm6dso_ctrl1_xl_t reg; + int32_t ret; + + /* Check the Finite State Machine data rate constraints */ + ret = lsm6dso_fsm_enable_get(ctx, &fsm_enable); + + if (ret == 0) + { + if ((fsm_enable.fsm_enable_a.fsm1_en | + fsm_enable.fsm_enable_a.fsm2_en | + fsm_enable.fsm_enable_a.fsm3_en | + fsm_enable.fsm_enable_a.fsm4_en | + fsm_enable.fsm_enable_a.fsm5_en | + fsm_enable.fsm_enable_a.fsm6_en | + fsm_enable.fsm_enable_a.fsm7_en | + fsm_enable.fsm_enable_a.fsm8_en | + fsm_enable.fsm_enable_b.fsm9_en | + fsm_enable.fsm_enable_b.fsm10_en | + fsm_enable.fsm_enable_b.fsm11_en | + fsm_enable.fsm_enable_b.fsm12_en | + fsm_enable.fsm_enable_b.fsm13_en | + fsm_enable.fsm_enable_b.fsm14_en | + fsm_enable.fsm_enable_b.fsm15_en | + fsm_enable.fsm_enable_b.fsm16_en) == PROPERTY_ENABLE) + { + ret = lsm6dso_fsm_data_rate_get(ctx, &fsm_odr); + + if (ret == 0) + { + switch (fsm_odr) + { + case LSM6DSO_ODR_FSM_12Hz5: + if (val == LSM6DSO_XL_ODR_OFF) + { + odr_xl = LSM6DSO_XL_ODR_12Hz5; + } + + else + { + odr_xl = val; + } + + break; + + case LSM6DSO_ODR_FSM_26Hz: + if (val == LSM6DSO_XL_ODR_OFF) + { + odr_xl = LSM6DSO_XL_ODR_26Hz; + } + + else if (val == LSM6DSO_XL_ODR_12Hz5) + { + odr_xl = LSM6DSO_XL_ODR_26Hz; + } + + else + { + odr_xl = val; + } + + break; + + case LSM6DSO_ODR_FSM_52Hz: + if (val == LSM6DSO_XL_ODR_OFF) + { + odr_xl = LSM6DSO_XL_ODR_52Hz; + } + + else if (val == LSM6DSO_XL_ODR_12Hz5) + { + odr_xl = LSM6DSO_XL_ODR_52Hz; + } + + else if (val == LSM6DSO_XL_ODR_26Hz) + { + odr_xl = LSM6DSO_XL_ODR_52Hz; + } + + else + { + odr_xl = val; + } + + break; + + case LSM6DSO_ODR_FSM_104Hz: + if (val == LSM6DSO_XL_ODR_OFF) + { + odr_xl = LSM6DSO_XL_ODR_104Hz; + } + + else if (val == LSM6DSO_XL_ODR_12Hz5) + { + odr_xl = LSM6DSO_XL_ODR_104Hz; + } + + else if (val == LSM6DSO_XL_ODR_26Hz) + { + odr_xl = LSM6DSO_XL_ODR_104Hz; + } + + else if (val == LSM6DSO_XL_ODR_52Hz) + { + odr_xl = LSM6DSO_XL_ODR_104Hz; + } + + else + { + odr_xl = val; + } + + break; + + default: + odr_xl = val; + break; + } + } + } + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL1_XL, (uint8_t *)®, 1); + } + + if (ret == 0) + { + reg.odr_xl = (uint8_t) odr_xl; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL1_XL, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Accelerometer UI data rate selection.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of odr_xl in reg CTRL1_XL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_xl_data_rate_get(stmdev_ctx_t *ctx, + lsm6dso_odr_xl_t *val) +{ + lsm6dso_ctrl1_xl_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL1_XL, (uint8_t *)®, 1); + + switch (reg.odr_xl) + { + case LSM6DSO_XL_ODR_OFF: + *val = LSM6DSO_XL_ODR_OFF; + break; + + case LSM6DSO_XL_ODR_12Hz5: + *val = LSM6DSO_XL_ODR_12Hz5; + break; + + case LSM6DSO_XL_ODR_26Hz: + *val = LSM6DSO_XL_ODR_26Hz; + break; + + case LSM6DSO_XL_ODR_52Hz: + *val = LSM6DSO_XL_ODR_52Hz; + break; + + case LSM6DSO_XL_ODR_104Hz: + *val = LSM6DSO_XL_ODR_104Hz; + break; + + case LSM6DSO_XL_ODR_208Hz: + *val = LSM6DSO_XL_ODR_208Hz; + break; + + case LSM6DSO_XL_ODR_417Hz: + *val = LSM6DSO_XL_ODR_417Hz; + break; + + case LSM6DSO_XL_ODR_833Hz: + *val = LSM6DSO_XL_ODR_833Hz; + break; + + case LSM6DSO_XL_ODR_1667Hz: + *val = LSM6DSO_XL_ODR_1667Hz; + break; + + case LSM6DSO_XL_ODR_3333Hz: + *val = LSM6DSO_XL_ODR_3333Hz; + break; + + case LSM6DSO_XL_ODR_6667Hz: + *val = LSM6DSO_XL_ODR_6667Hz; + break; + + case LSM6DSO_XL_ODR_1Hz6: + *val = LSM6DSO_XL_ODR_1Hz6; + break; + + default: + *val = LSM6DSO_XL_ODR_OFF; + break; + } + + return ret; +} + +/** + * @brief Gyroscope UI chain full-scale selection.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of fs_g in reg CTRL2_G + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_gy_full_scale_set(stmdev_ctx_t *ctx, + lsm6dso_fs_g_t val) +{ + lsm6dso_ctrl2_g_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL2_G, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.fs_g = (uint8_t) val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL2_G, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Gyroscope UI chain full-scale selection.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of fs_g in reg CTRL2_G + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_gy_full_scale_get(stmdev_ctx_t *ctx, + lsm6dso_fs_g_t *val) +{ + lsm6dso_ctrl2_g_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL2_G, (uint8_t *)®, 1); + + switch (reg.fs_g) + { + case LSM6DSO_250dps: + *val = LSM6DSO_250dps; + break; + + case LSM6DSO_125dps: + *val = LSM6DSO_125dps; + break; + + case LSM6DSO_500dps: + *val = LSM6DSO_500dps; + break; + + case LSM6DSO_1000dps: + *val = LSM6DSO_1000dps; + break; + + case LSM6DSO_2000dps: + *val = LSM6DSO_2000dps; + break; + + default: + *val = LSM6DSO_250dps; + break; + } + + return ret; +} + +/** + * @brief Gyroscope UI data rate selection.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of odr_g in reg CTRL2_G + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_gy_data_rate_set(stmdev_ctx_t *ctx, + lsm6dso_odr_g_t val) +{ + lsm6dso_odr_g_t odr_gy = val; + lsm6dso_emb_fsm_enable_t fsm_enable; + lsm6dso_fsm_odr_t fsm_odr; + lsm6dso_ctrl2_g_t reg; + int32_t ret; + + /* Check the Finite State Machine data rate constraints */ + ret = lsm6dso_fsm_enable_get(ctx, &fsm_enable); + + if (ret == 0) + { + if ((fsm_enable.fsm_enable_a.fsm1_en | + fsm_enable.fsm_enable_a.fsm2_en | + fsm_enable.fsm_enable_a.fsm3_en | + fsm_enable.fsm_enable_a.fsm4_en | + fsm_enable.fsm_enable_a.fsm5_en | + fsm_enable.fsm_enable_a.fsm6_en | + fsm_enable.fsm_enable_a.fsm7_en | + fsm_enable.fsm_enable_a.fsm8_en | + fsm_enable.fsm_enable_b.fsm9_en | + fsm_enable.fsm_enable_b.fsm10_en | + fsm_enable.fsm_enable_b.fsm11_en | + fsm_enable.fsm_enable_b.fsm12_en | + fsm_enable.fsm_enable_b.fsm13_en | + fsm_enable.fsm_enable_b.fsm14_en | + fsm_enable.fsm_enable_b.fsm15_en | + fsm_enable.fsm_enable_b.fsm16_en) == PROPERTY_ENABLE) + { + ret = lsm6dso_fsm_data_rate_get(ctx, &fsm_odr); + + if (ret == 0) + { + switch (fsm_odr) + { + case LSM6DSO_ODR_FSM_12Hz5: + if (val == LSM6DSO_GY_ODR_OFF) + { + odr_gy = LSM6DSO_GY_ODR_12Hz5; + } + + else + { + odr_gy = val; + } + + break; + + case LSM6DSO_ODR_FSM_26Hz: + if (val == LSM6DSO_GY_ODR_OFF) + { + odr_gy = LSM6DSO_GY_ODR_26Hz; + } + + else if (val == LSM6DSO_GY_ODR_12Hz5) + { + odr_gy = LSM6DSO_GY_ODR_26Hz; + } + + else + { + odr_gy = val; + } + + break; + + case LSM6DSO_ODR_FSM_52Hz: + if (val == LSM6DSO_GY_ODR_OFF) + { + odr_gy = LSM6DSO_GY_ODR_52Hz; + } + + else if (val == LSM6DSO_GY_ODR_12Hz5) + { + odr_gy = LSM6DSO_GY_ODR_52Hz; + } + + else if (val == LSM6DSO_GY_ODR_26Hz) + { + odr_gy = LSM6DSO_GY_ODR_52Hz; + } + + else + { + odr_gy = val; + } + + break; + + case LSM6DSO_ODR_FSM_104Hz: + if (val == LSM6DSO_GY_ODR_OFF) + { + odr_gy = LSM6DSO_GY_ODR_104Hz; + } + + else if (val == LSM6DSO_GY_ODR_12Hz5) + { + odr_gy = LSM6DSO_GY_ODR_104Hz; + } + + else if (val == LSM6DSO_GY_ODR_26Hz) + { + odr_gy = LSM6DSO_GY_ODR_104Hz; + } + + else if (val == LSM6DSO_GY_ODR_52Hz) + { + odr_gy = LSM6DSO_GY_ODR_104Hz; + } + + else + { + odr_gy = val; + } + + break; + + default: + odr_gy = val; + break; + } + } + } + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL2_G, (uint8_t *)®, 1); + } + + if (ret == 0) + { + reg.odr_g = (uint8_t) odr_gy; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL2_G, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Gyroscope UI data rate selection.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of odr_g in reg CTRL2_G + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_gy_data_rate_get(stmdev_ctx_t *ctx, + lsm6dso_odr_g_t *val) +{ + lsm6dso_ctrl2_g_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL2_G, (uint8_t *)®, 1); + + switch (reg.odr_g) + { + case LSM6DSO_GY_ODR_OFF: + *val = LSM6DSO_GY_ODR_OFF; + break; + + case LSM6DSO_GY_ODR_12Hz5: + *val = LSM6DSO_GY_ODR_12Hz5; + break; + + case LSM6DSO_GY_ODR_26Hz: + *val = LSM6DSO_GY_ODR_26Hz; + break; + + case LSM6DSO_GY_ODR_52Hz: + *val = LSM6DSO_GY_ODR_52Hz; + break; + + case LSM6DSO_GY_ODR_104Hz: + *val = LSM6DSO_GY_ODR_104Hz; + break; + + case LSM6DSO_GY_ODR_208Hz: + *val = LSM6DSO_GY_ODR_208Hz; + break; + + case LSM6DSO_GY_ODR_417Hz: + *val = LSM6DSO_GY_ODR_417Hz; + break; + + case LSM6DSO_GY_ODR_833Hz: + *val = LSM6DSO_GY_ODR_833Hz; + break; + + case LSM6DSO_GY_ODR_1667Hz: + *val = LSM6DSO_GY_ODR_1667Hz; + break; + + case LSM6DSO_GY_ODR_3333Hz: + *val = LSM6DSO_GY_ODR_3333Hz; + break; + + case LSM6DSO_GY_ODR_6667Hz: + *val = LSM6DSO_GY_ODR_6667Hz; + break; + + default: + *val = LSM6DSO_GY_ODR_OFF; + break; + } + + return ret; +} + +/** + * @brief Block data update.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of bdu in reg CTRL3_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_block_data_update_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_ctrl3_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL3_C, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.bdu = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL3_C, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Block data update.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of bdu in reg CTRL3_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_block_data_update_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_ctrl3_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL3_C, (uint8_t *)®, 1); + *val = reg.bdu; + + return ret; +} + +/** + * @brief Weight of XL user offset bits of registers X_OFS_USR (73h), + * Y_OFS_USR (74h), Z_OFS_USR (75h).[set] + * + * @param ctx read / write interface definitions + * @param val change the values of usr_off_w in reg CTRL6_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_xl_offset_weight_set(stmdev_ctx_t *ctx, + lsm6dso_usr_off_w_t val) +{ + lsm6dso_ctrl6_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL6_C, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.usr_off_w = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL6_C, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Weight of XL user offset bits of registers X_OFS_USR (73h), + * Y_OFS_USR (74h), Z_OFS_USR (75h).[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of usr_off_w in reg CTRL6_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_xl_offset_weight_get(stmdev_ctx_t *ctx, + lsm6dso_usr_off_w_t *val) +{ + lsm6dso_ctrl6_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL6_C, (uint8_t *)®, 1); + + switch (reg.usr_off_w) + { + case LSM6DSO_LSb_1mg: + *val = LSM6DSO_LSb_1mg; + break; + + case LSM6DSO_LSb_16mg: + *val = LSM6DSO_LSb_16mg; + break; + + default: + *val = LSM6DSO_LSb_1mg; + break; + } + + return ret; +} + +/** + * @brief Accelerometer power mode.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of xl_hm_mode in + * reg CTRL6_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_xl_power_mode_set(stmdev_ctx_t *ctx, + lsm6dso_xl_hm_mode_t val) +{ + lsm6dso_ctrl5_c_t ctrl5_c; + lsm6dso_ctrl6_c_t ctrl6_c; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL5_C, (uint8_t *) &ctrl5_c, 1); + + if (ret == 0) + { + ctrl5_c.xl_ulp_en = ((uint8_t)val & 0x02U) >> 1; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL5_C, (uint8_t *) &ctrl5_c, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL6_C, (uint8_t *) &ctrl6_c, 1); + } + + if (ret == 0) + { + ctrl6_c.xl_hm_mode = (uint8_t)val & 0x01U; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL6_C, (uint8_t *) &ctrl6_c, 1); + } + + return ret; +} + +/** + * @brief Accelerometer power mode.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of xl_hm_mode in reg CTRL6_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_xl_power_mode_get(stmdev_ctx_t *ctx, + lsm6dso_xl_hm_mode_t *val) +{ + lsm6dso_ctrl5_c_t ctrl5_c; + lsm6dso_ctrl6_c_t ctrl6_c; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL5_C, (uint8_t *) &ctrl5_c, 1); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL6_C, (uint8_t *) &ctrl6_c, 1); + + switch ((ctrl5_c.xl_ulp_en << 1) | ctrl6_c.xl_hm_mode) + { + case LSM6DSO_HIGH_PERFORMANCE_MD: + *val = LSM6DSO_HIGH_PERFORMANCE_MD; + break; + + case LSM6DSO_LOW_NORMAL_POWER_MD: + *val = LSM6DSO_LOW_NORMAL_POWER_MD; + break; + + case LSM6DSO_ULTRA_LOW_POWER_MD: + *val = LSM6DSO_ULTRA_LOW_POWER_MD; + break; + + default: + *val = LSM6DSO_HIGH_PERFORMANCE_MD; + break; + } + } + + return ret; +} + +/** + * @brief Operating mode for gyroscope.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of g_hm_mode in reg CTRL7_G + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_gy_power_mode_set(stmdev_ctx_t *ctx, + lsm6dso_g_hm_mode_t val) +{ + lsm6dso_ctrl7_g_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL7_G, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.g_hm_mode = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL7_G, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Operating mode for gyroscope.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of g_hm_mode in reg CTRL7_G + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_gy_power_mode_get(stmdev_ctx_t *ctx, + lsm6dso_g_hm_mode_t *val) +{ + lsm6dso_ctrl7_g_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL7_G, (uint8_t *)®, 1); + + switch (reg.g_hm_mode) + { + case LSM6DSO_GY_HIGH_PERFORMANCE: + *val = LSM6DSO_GY_HIGH_PERFORMANCE; + break; + + case LSM6DSO_GY_NORMAL: + *val = LSM6DSO_GY_NORMAL; + break; + + default: + *val = LSM6DSO_GY_HIGH_PERFORMANCE; + break; + } + + return ret; +} + +/** + * @brief The STATUS_REG register is read by the primary interface.[get] + * + * @param ctx read / write interface definitions + * @param val register STATUS_REG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_status_reg_get(stmdev_ctx_t *ctx, + lsm6dso_status_reg_t *val) +{ + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_STATUS_REG, (uint8_t *) val, 1); + + return ret; +} + +/** + * @brief Accelerometer new data available.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of xlda in reg STATUS_REG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_xl_flag_data_ready_get(stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6dso_status_reg_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_STATUS_REG, (uint8_t *)®, 1); + *val = reg.xlda; + + return ret; +} + +/** + * @brief Gyroscope new data available.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of gda in reg STATUS_REG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_gy_flag_data_ready_get(stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6dso_status_reg_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_STATUS_REG, (uint8_t *)®, 1); + *val = reg.gda; + + return ret; +} + +/** + * @brief Temperature new data available.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of tda in reg STATUS_REG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_temp_flag_data_ready_get(stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6dso_status_reg_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_STATUS_REG, (uint8_t *)®, 1); + *val = reg.tda; + + return ret; +} + +/** + * @brief Accelerometer X-axis user offset correction expressed in + * two's complement, weight depends on USR_OFF_W in CTRL6_C (15h). + * The value must be in the range [-127 127].[set] + * + * @param ctx read / write interface definitions + * @param buff buffer that contains data to write + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_xl_usr_offset_x_set(stmdev_ctx_t *ctx, uint8_t *buff) +{ + int32_t ret; + + ret = lsm6dso_write_reg(ctx, LSM6DSO_X_OFS_USR, buff, 1); + + return ret; +} + +/** + * @brief Accelerometer X-axis user offset correction expressed in two's + * complement, weight depends on USR_OFF_W in CTRL6_C (15h). + * The value must be in the range [-127 127].[get] + * + * @param ctx read / write interface definitions + * @param buff buffer that stores data read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_xl_usr_offset_x_get(stmdev_ctx_t *ctx, uint8_t *buff) +{ + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_X_OFS_USR, buff, 1); + + return ret; +} + +/** + * @brief Accelerometer Y-axis user offset correction expressed in two's + * complement, weight depends on USR_OFF_W in CTRL6_C (15h). + * The value must be in the range [-127 127].[set] + * + * @param ctx read / write interface definitions + * @param buff buffer that contains data to write + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_xl_usr_offset_y_set(stmdev_ctx_t *ctx, uint8_t *buff) +{ + int32_t ret; + + ret = lsm6dso_write_reg(ctx, LSM6DSO_Y_OFS_USR, buff, 1); + + return ret; +} + +/** + * @brief Accelerometer Y-axis user offset correction expressed in two's + * complement, weight depends on USR_OFF_W in CTRL6_C (15h). + * The value must be in the range [-127 127].[get] + * + * @param ctx read / write interface definitions + * @param buff buffer that stores data read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_xl_usr_offset_y_get(stmdev_ctx_t *ctx, uint8_t *buff) +{ + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_Y_OFS_USR, buff, 1); + + return ret; +} + +/** + * @brief Accelerometer Z-axis user offset correction expressed in two's + * complement, weight depends on USR_OFF_W in CTRL6_C (15h). + * The value must be in the range [-127 127].[set] + * + * @param ctx read / write interface definitions + * @param buff buffer that contains data to write + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_xl_usr_offset_z_set(stmdev_ctx_t *ctx, uint8_t *buff) +{ + int32_t ret; + + ret = lsm6dso_write_reg(ctx, LSM6DSO_Z_OFS_USR, buff, 1); + + return ret; +} + +/** + * @brief Accelerometer Z-axis user offset correction expressed in two's + * complement, weight depends on USR_OFF_W in CTRL6_C (15h). + * The value must be in the range [-127 127].[get] + * + * @param ctx read / write interface definitions + * @param buff buffer that stores data read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_xl_usr_offset_z_get(stmdev_ctx_t *ctx, uint8_t *buff) +{ + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_Z_OFS_USR, buff, 1); + + return ret; +} + +/** + * @brief Enables user offset on out.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of usr_off_on_out in reg CTRL7_G + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_xl_usr_offset_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_ctrl7_g_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL7_G, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.usr_off_on_out = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL7_G, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief User offset on out flag.[get] + * + * @param ctx read / write interface definitions + * @param val values of usr_off_on_out in reg CTRL7_G + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_xl_usr_offset_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_ctrl7_g_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL7_G, (uint8_t *)®, 1); + *val = reg.usr_off_on_out; + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DSO_Timestamp + * @brief This section groups all the functions that manage the + * timestamp generation. + * @{ + * + */ + +/** + * @brief Reset timestamp counter.[set] + * + * @param ctx Read / write interface definitions.(ptr) + * @retval Interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_timestamp_rst(stmdev_ctx_t *ctx) +{ + uint8_t rst_val = 0xAA; + return lsm6dso_write_reg(ctx, LSM6DSO_TIMESTAMP2, &rst_val, 1); +} + +/** + * @brief Enables timestamp counter.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of timestamp_en in reg CTRL10_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_timestamp_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_ctrl10_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL10_C, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.timestamp_en = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL10_C, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Enables timestamp counter.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of timestamp_en in reg CTRL10_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_timestamp_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_ctrl10_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL10_C, (uint8_t *)®, 1); + *val = reg.timestamp_en; + + return ret; +} + +/** + * @brief Timestamp first data output register (r). + * The value is expressed as a 32-bit word and the bit + * resolution is 25 us.[get] + * + * @param ctx read / write interface definitions + * @param buff buffer that stores data read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_timestamp_raw_get(stmdev_ctx_t *ctx, uint32_t *val) +{ + uint8_t buff[4]; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_TIMESTAMP0, buff, 4); + *val = buff[3]; + *val = (*val * 256U) + buff[2]; + *val = (*val * 256U) + buff[1]; + *val = (*val * 256U) + buff[0]; + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DSO_Data output + * @brief This section groups all the data output functions. + * @{ + * + */ + +/** + * @brief Circular burst-mode (rounding) read of the output + * registers.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of rounding in reg CTRL5_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_rounding_mode_set(stmdev_ctx_t *ctx, + lsm6dso_rounding_t val) +{ + lsm6dso_ctrl5_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL5_C, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.rounding = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL5_C, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Gyroscope UI chain full-scale selection.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of rounding in reg CTRL5_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_rounding_mode_get(stmdev_ctx_t *ctx, + lsm6dso_rounding_t *val) +{ + lsm6dso_ctrl5_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL5_C, (uint8_t *)®, 1); + + switch (reg.rounding) + { + case LSM6DSO_NO_ROUND: + *val = LSM6DSO_NO_ROUND; + break; + + case LSM6DSO_ROUND_XL: + *val = LSM6DSO_ROUND_XL; + break; + + case LSM6DSO_ROUND_GY: + *val = LSM6DSO_ROUND_GY; + break; + + case LSM6DSO_ROUND_GY_XL: + *val = LSM6DSO_ROUND_GY_XL; + break; + + default: + *val = LSM6DSO_NO_ROUND; + break; + } + + return ret; +} + +/** + * @brief Temperature data output register (r). + * L and H registers together express a 16-bit word in two's + * complement.[get] + * + * @param ctx read / write interface definitions + * @param buff buffer that stores data read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_temperature_raw_get(stmdev_ctx_t *ctx, int16_t *val) +{ + uint8_t buff[2]; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_OUT_TEMP_L, buff, 2); + val[0] = (int16_t)buff[1]; + val[0] = (val[0] * 256) + (int16_t)buff[0]; + + return ret; +} + +/** + * @brief Angular rate sensor. The value is expressed as a 16-bit + * word in two's complement.[get] + * + * @param ctx read / write interface definitions + * @param buff buffer that stores data read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_angular_rate_raw_get(stmdev_ctx_t *ctx, int16_t *val) +{ + uint8_t buff[6]; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_OUTX_L_G, buff, 6); + val[0] = (int16_t)buff[1]; + val[0] = (val[0] * 256) + (int16_t)buff[0]; + val[1] = (int16_t)buff[3]; + val[1] = (val[1] * 256) + (int16_t)buff[2]; + val[2] = (int16_t)buff[5]; + val[2] = (val[2] * 256) + (int16_t)buff[4]; + + return ret; +} + +/** + * @brief Linear acceleration output register. + * The value is expressed as a 16-bit word in two's complement.[get] + * + * @param ctx read / write interface definitions + * @param buff buffer that stores data read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_acceleration_raw_get(stmdev_ctx_t *ctx, int16_t *val) +{ + uint8_t buff[6]; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_OUTX_L_A, buff, 6); + val[0] = (int16_t)buff[1]; + val[0] = (val[0] * 256) + (int16_t)buff[0]; + val[1] = (int16_t)buff[3]; + val[1] = (val[1] * 256) + (int16_t)buff[2]; + val[2] = (int16_t)buff[5]; + val[2] = (val[2] * 256) + (int16_t)buff[4]; + + return ret; +} + +/** + * @brief FIFO data output [get] + * + * @param ctx read / write interface definitions + * @param buff buffer that stores data read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fifo_out_raw_get(stmdev_ctx_t *ctx, uint8_t *buff) +{ + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_FIFO_DATA_OUT_X_L, buff, 6); + + return ret; +} + +/** + * @brief Step counter output register.[get] + * + * @param ctx read / write interface definitions + * @param buff buffer that stores data read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_number_of_steps_get(stmdev_ctx_t *ctx, uint16_t *val) +{ + uint8_t buff[2]; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_STEP_COUNTER_L, buff, 2); + } + + if (ret == 0) + { + *val = buff[1]; + *val = (*val * 256U) + buff[0]; + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Reset step counter register.[get] + * + * @param ctx read / write interface definitions + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_steps_reset(stmdev_ctx_t *ctx) +{ + lsm6dso_emb_func_src_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_EMB_FUNC_SRC, (uint8_t *)®, 1); + } + + if (ret == 0) + { + reg.pedo_rst_step = PROPERTY_ENABLE; + ret = lsm6dso_write_reg(ctx, LSM6DSO_EMB_FUNC_SRC, (uint8_t *)®, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DSO_common + * @brief This section groups common useful functions. + * @{ + * + */ + +/** + * @brief Difference in percentage of the effective ODR(and timestamp rate) + * with respect to the typical. + * Step: 0.15%. 8-bit format, 2's complement.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of freq_fine in reg + * INTERNAL_FREQ_FINE + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_odr_cal_reg_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_internal_freq_fine_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_INTERNAL_FREQ_FINE, + (uint8_t *)®, 1); + + if (ret == 0) + { + reg.freq_fine = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_INTERNAL_FREQ_FINE, + (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Difference in percentage of the effective ODR(and timestamp rate) + * with respect to the typical. + * Step: 0.15%. 8-bit format, 2's complement.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of freq_fine in reg INTERNAL_FREQ_FINE + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_odr_cal_reg_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_internal_freq_fine_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_INTERNAL_FREQ_FINE, + (uint8_t *)®, 1); + *val = reg.freq_fine; + + return ret; +} + + +/** + * @brief Enable access to the embedded functions/sensor + * hub configuration registers.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of reg_access in + * reg FUNC_CFG_ACCESS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_mem_bank_set(stmdev_ctx_t *ctx, + lsm6dso_reg_access_t val) +{ + lsm6dso_func_cfg_access_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_FUNC_CFG_ACCESS, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.reg_access = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_FUNC_CFG_ACCESS, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Enable access to the embedded functions/sensor + * hub configuration registers.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of reg_access in + * reg FUNC_CFG_ACCESS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_mem_bank_get(stmdev_ctx_t *ctx, + lsm6dso_reg_access_t *val) +{ + lsm6dso_func_cfg_access_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_FUNC_CFG_ACCESS, (uint8_t *)®, 1); + + switch (reg.reg_access) + { + case LSM6DSO_USER_BANK: + *val = LSM6DSO_USER_BANK; + break; + + case LSM6DSO_SENSOR_HUB_BANK: + *val = LSM6DSO_SENSOR_HUB_BANK; + break; + + case LSM6DSO_EMBEDDED_FUNC_BANK: + *val = LSM6DSO_EMBEDDED_FUNC_BANK; + break; + + default: + *val = LSM6DSO_USER_BANK; + break; + } + + return ret; +} + +/** + * @brief Write a line(byte) in a page.[set] + * + * @param ctx read / write interface definitions + * @param uint8_t address: page line address + * @param val value to write + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_ln_pg_write_byte(stmdev_ctx_t *ctx, uint16_t address, + uint8_t *val) +{ + lsm6dso_page_rw_t page_rw; + lsm6dso_page_sel_t page_sel; + lsm6dso_page_address_t page_address; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_PAGE_RW, (uint8_t *) &page_rw, 1); + } + + if (ret == 0) + { + page_rw.page_rw = 0x02; /* page_write enable */ + ret = lsm6dso_write_reg(ctx, LSM6DSO_PAGE_RW, (uint8_t *) &page_rw, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_PAGE_SEL, (uint8_t *) &page_sel, 1); + } + + if (ret == 0) + { + page_sel.page_sel = ((uint8_t)(address >> 8) & 0x0FU); + page_sel.not_used_01 = 1; + ret = lsm6dso_write_reg(ctx, LSM6DSO_PAGE_SEL, (uint8_t *) &page_sel, 1); + } + + if (ret == 0) + { + page_address.page_addr = (uint8_t)address & 0xFFU; + ret = lsm6dso_write_reg(ctx, LSM6DSO_PAGE_ADDRESS, + (uint8_t *)&page_address, 1); + } + + if (ret == 0) + { + ret = lsm6dso_write_reg(ctx, LSM6DSO_PAGE_VALUE, val, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_PAGE_RW, (uint8_t *) &page_rw, 1); + } + + if (ret == 0) + { + page_rw.page_rw = 0x00; /* page_write disable */ + ret = lsm6dso_write_reg(ctx, LSM6DSO_PAGE_RW, (uint8_t *) &page_rw, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Write buffer in a page.[set] + * + * @param ctx read / write interface definitions + * @param uint8_t address: page line address + * @param uint8_t *buf: buffer to write + * @param uint8_t len: buffer len + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_ln_pg_write(stmdev_ctx_t *ctx, uint16_t address, + uint8_t *buf, uint8_t len) +{ + lsm6dso_page_rw_t page_rw; + lsm6dso_page_sel_t page_sel; + lsm6dso_page_address_t page_address; + uint16_t addr_pointed; + int32_t ret; + + uint8_t i ; + addr_pointed = address; + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_PAGE_RW, (uint8_t *) &page_rw, 1); + } + + if (ret == 0) + { + page_rw.page_rw = 0x02; /* page_write enable*/ + ret = lsm6dso_write_reg(ctx, LSM6DSO_PAGE_RW, (uint8_t *) &page_rw, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_PAGE_SEL, (uint8_t *) &page_sel, 1); + } + + if (ret == 0) + { + page_sel.page_sel = ((uint8_t)(addr_pointed >> 8) & 0x0FU); + page_sel.not_used_01 = 1; + ret = lsm6dso_write_reg(ctx, LSM6DSO_PAGE_SEL, (uint8_t *) &page_sel, 1); + } + + if (ret == 0) + { + page_address.page_addr = (uint8_t)(addr_pointed & 0x00FFU); + ret = lsm6dso_write_reg(ctx, LSM6DSO_PAGE_ADDRESS, + (uint8_t *)&page_address, 1); + } + + if (ret == 0) + { + for (i = 0; ((i < len) && (ret == 0)); i++) + { + ret = lsm6dso_write_reg(ctx, LSM6DSO_PAGE_VALUE, &buf[i], 1); + addr_pointed++; + + /* Check if page wrap */ + if (((addr_pointed % 0x0100U) == 0x00U) && (ret == 0)) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_PAGE_SEL, (uint8_t *)&page_sel, 1); + + if (ret == 0) + { + page_sel.page_sel = ((uint8_t)(addr_pointed >> 8) & 0x0FU); + page_sel.not_used_01 = 1; + ret = lsm6dso_write_reg(ctx, LSM6DSO_PAGE_SEL, + (uint8_t *)&page_sel, 1); + } + } + } + + page_sel.page_sel = 0; + page_sel.not_used_01 = 1; + ret = lsm6dso_write_reg(ctx, LSM6DSO_PAGE_SEL, (uint8_t *) &page_sel, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_PAGE_RW, (uint8_t *) &page_rw, 1); + } + + if (ret == 0) + { + page_rw.page_rw = 0x00; /* page_write disable */ + ret = lsm6dso_write_reg(ctx, LSM6DSO_PAGE_RW, (uint8_t *) &page_rw, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Read a line(byte) in a page.[get] + * + * @param ctx read / write interface definitions + * @param uint8_t address: page line address + * @param val read value + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_ln_pg_read_byte(stmdev_ctx_t *ctx, uint16_t address, + uint8_t *val) +{ + lsm6dso_page_rw_t page_rw; + lsm6dso_page_sel_t page_sel; + lsm6dso_page_address_t page_address; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_PAGE_RW, (uint8_t *) &page_rw, 1); + } + + if (ret == 0) + { + page_rw.page_rw = 0x01; /* page_read enable*/ + ret = lsm6dso_write_reg(ctx, LSM6DSO_PAGE_RW, (uint8_t *) &page_rw, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_PAGE_SEL, (uint8_t *) &page_sel, 1); + } + + if (ret == 0) + { + page_sel.page_sel = ((uint8_t)(address >> 8) & 0x0FU); + page_sel.not_used_01 = 1; + ret = lsm6dso_write_reg(ctx, LSM6DSO_PAGE_SEL, (uint8_t *) &page_sel, 1); + } + + if (ret == 0) + { + page_address.page_addr = (uint8_t)address & 0x00FFU; + ret = lsm6dso_write_reg(ctx, LSM6DSO_PAGE_ADDRESS, + (uint8_t *)&page_address, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_PAGE_VALUE, val, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_PAGE_RW, (uint8_t *) &page_rw, 1); + } + + if (ret == 0) + { + page_rw.page_rw = 0x00; /* page_read disable */ + ret = lsm6dso_write_reg(ctx, LSM6DSO_PAGE_RW, (uint8_t *) &page_rw, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Data-ready pulsed / letched mode.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of + * dataready_pulsed in + * reg COUNTER_BDR_REG1 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_data_ready_mode_set(stmdev_ctx_t *ctx, + lsm6dso_dataready_pulsed_t val) +{ + lsm6dso_counter_bdr_reg1_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_COUNTER_BDR_REG1, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.dataready_pulsed = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_COUNTER_BDR_REG1, + (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Data-ready pulsed / letched mode.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of + * dataready_pulsed in + * reg COUNTER_BDR_REG1 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_data_ready_mode_get(stmdev_ctx_t *ctx, + lsm6dso_dataready_pulsed_t *val) +{ + lsm6dso_counter_bdr_reg1_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_COUNTER_BDR_REG1, (uint8_t *)®, 1); + + switch (reg.dataready_pulsed) + { + case LSM6DSO_DRDY_LATCHED: + *val = LSM6DSO_DRDY_LATCHED; + break; + + case LSM6DSO_DRDY_PULSED: + *val = LSM6DSO_DRDY_PULSED; + break; + + default: + *val = LSM6DSO_DRDY_LATCHED; + break; + } + + return ret; +} + +/** + * @brief Device "Who am I".[get] + * + * @param ctx read / write interface definitions + * @param buff buffer that stores data read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_device_id_get(stmdev_ctx_t *ctx, uint8_t *buff) +{ + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_WHO_AM_I, buff, 1); + + return ret; +} + +/** + * @brief Software reset. Restore the default values + * in user registers[set] + * + * @param ctx read / write interface definitions + * @param val change the values of sw_reset in reg CTRL3_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_reset_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_ctrl3_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL3_C, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.sw_reset = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL3_C, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Software reset. Restore the default values in user registers.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of sw_reset in reg CTRL3_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_reset_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_ctrl3_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL3_C, (uint8_t *)®, 1); + *val = reg.sw_reset; + + return ret; +} + +/** + * @brief Register address automatically incremented during a multiple byte + * access with a serial interface.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of if_inc in reg CTRL3_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_auto_increment_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_ctrl3_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL3_C, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.if_inc = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL3_C, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Register address automatically incremented during a multiple byte + * access with a serial interface.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of if_inc in reg CTRL3_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_auto_increment_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_ctrl3_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL3_C, (uint8_t *)®, 1); + *val = reg.if_inc; + + return ret; +} + +/** + * @brief Reboot memory content. Reload the calibration parameters.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of boot in reg CTRL3_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_boot_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_ctrl3_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL3_C, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.boot = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL3_C, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Reboot memory content. Reload the calibration parameters.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of boot in reg CTRL3_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_boot_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_ctrl3_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL3_C, (uint8_t *)®, 1); + *val = reg.boot; + + return ret; +} + +/** + * @brief Linear acceleration sensor self-test enable.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of st_xl in reg CTRL5_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_xl_self_test_set(stmdev_ctx_t *ctx, + lsm6dso_st_xl_t val) +{ + lsm6dso_ctrl5_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL5_C, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.st_xl = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL5_C, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Linear acceleration sensor self-test enable.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of st_xl in reg CTRL5_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_xl_self_test_get(stmdev_ctx_t *ctx, + lsm6dso_st_xl_t *val) +{ + lsm6dso_ctrl5_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL5_C, (uint8_t *)®, 1); + + switch (reg.st_xl) + { + case LSM6DSO_XL_ST_DISABLE: + *val = LSM6DSO_XL_ST_DISABLE; + break; + + case LSM6DSO_XL_ST_POSITIVE: + *val = LSM6DSO_XL_ST_POSITIVE; + break; + + case LSM6DSO_XL_ST_NEGATIVE: + *val = LSM6DSO_XL_ST_NEGATIVE; + break; + + default: + *val = LSM6DSO_XL_ST_DISABLE; + break; + } + + return ret; +} + +/** + * @brief Angular rate sensor self-test enable.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of st_g in reg CTRL5_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_gy_self_test_set(stmdev_ctx_t *ctx, + lsm6dso_st_g_t val) +{ + lsm6dso_ctrl5_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL5_C, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.st_g = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL5_C, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Angular rate sensor self-test enable.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of st_g in reg CTRL5_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_gy_self_test_get(stmdev_ctx_t *ctx, + lsm6dso_st_g_t *val) +{ + lsm6dso_ctrl5_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL5_C, (uint8_t *)®, 1); + + switch (reg.st_g) + { + case LSM6DSO_GY_ST_DISABLE: + *val = LSM6DSO_GY_ST_DISABLE; + break; + + case LSM6DSO_GY_ST_POSITIVE: + *val = LSM6DSO_GY_ST_POSITIVE; + break; + + case LSM6DSO_GY_ST_NEGATIVE: + *val = LSM6DSO_GY_ST_NEGATIVE; + break; + + default: + *val = LSM6DSO_GY_ST_DISABLE; + break; + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DSO_filters + * @brief This section group all the functions concerning the + * filters configuration + * @{ + * + */ + +/** + * @brief Accelerometer output from LPF2 filtering stage selection.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of lpf2_xl_en in reg CTRL1_XL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_xl_filter_lp2_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_ctrl1_xl_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL1_XL, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.lpf2_xl_en = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL1_XL, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Accelerometer output from LPF2 filtering stage selection.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of lpf2_xl_en in reg CTRL1_XL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_xl_filter_lp2_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_ctrl1_xl_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL1_XL, (uint8_t *)®, 1); + *val = reg.lpf2_xl_en; + + return ret; +} + +/** + * @brief Enables gyroscope digital LPF1 if auxiliary SPI is disabled; + * the bandwidth can be selected through FTYPE [2:0] + * in CTRL6_C (15h).[set] + * + * @param ctx read / write interface definitions + * @param val change the values of lpf1_sel_g in reg CTRL4_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_gy_filter_lp1_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_ctrl4_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL4_C, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.lpf1_sel_g = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL4_C, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Enables gyroscope digital LPF1 if auxiliary SPI is disabled; + * the bandwidth can be selected through FTYPE [2:0] + * in CTRL6_C (15h).[get] + * + * @param ctx read / write interface definitions + * @param val change the values of lpf1_sel_g in reg CTRL4_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_gy_filter_lp1_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_ctrl4_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL4_C, (uint8_t *)®, 1); + *val = reg.lpf1_sel_g; + + return ret; +} + +/** + * @brief Mask DRDY on pin (both XL & Gyro) until filter settling ends + * (XL and Gyro independently masked).[set] + * + * @param ctx read / write interface definitions + * @param val change the values of drdy_mask in reg CTRL4_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_filter_settling_mask_set(stmdev_ctx_t *ctx, + uint8_t val) +{ + lsm6dso_ctrl4_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL4_C, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.drdy_mask = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL4_C, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Mask DRDY on pin (both XL & Gyro) until filter settling ends + * (XL and Gyro independently masked).[get] + * + * @param ctx read / write interface definitions + * @param val change the values of drdy_mask in reg CTRL4_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_filter_settling_mask_get(stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6dso_ctrl4_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL4_C, (uint8_t *)®, 1); + *val = reg.drdy_mask; + + return ret; +} + +/** + * @brief Gyroscope lp1 bandwidth.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of ftype in reg CTRL6_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_gy_lp1_bandwidth_set(stmdev_ctx_t *ctx, + lsm6dso_ftype_t val) +{ + lsm6dso_ctrl6_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL6_C, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.ftype = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL6_C, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Gyroscope lp1 bandwidth.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of ftype in reg CTRL6_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_gy_lp1_bandwidth_get(stmdev_ctx_t *ctx, + lsm6dso_ftype_t *val) +{ + lsm6dso_ctrl6_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL6_C, (uint8_t *)®, 1); + + switch (reg.ftype) + { + case LSM6DSO_ULTRA_LIGHT: + *val = LSM6DSO_ULTRA_LIGHT; + break; + + case LSM6DSO_VERY_LIGHT: + *val = LSM6DSO_VERY_LIGHT; + break; + + case LSM6DSO_LIGHT: + *val = LSM6DSO_LIGHT; + break; + + case LSM6DSO_MEDIUM: + *val = LSM6DSO_MEDIUM; + break; + + case LSM6DSO_STRONG: + *val = LSM6DSO_STRONG; + break; + + case LSM6DSO_VERY_STRONG: + *val = LSM6DSO_VERY_STRONG; + break; + + case LSM6DSO_AGGRESSIVE: + *val = LSM6DSO_AGGRESSIVE; + break; + + case LSM6DSO_XTREME: + *val = LSM6DSO_XTREME; + break; + + default: + *val = LSM6DSO_ULTRA_LIGHT; + break; + } + + return ret; +} + +/** + * @brief Low pass filter 2 on 6D function selection.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of low_pass_on_6d in reg CTRL8_XL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_xl_lp2_on_6d_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_ctrl8_xl_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL8_XL, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.low_pass_on_6d = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL8_XL, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Low pass filter 2 on 6D function selection.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of low_pass_on_6d in reg CTRL8_XL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_xl_lp2_on_6d_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_ctrl8_xl_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL8_XL, (uint8_t *)®, 1); + *val = reg.low_pass_on_6d; + + return ret; +} + +/** + * @brief Accelerometer slope filter / high-pass filter selection + * on output.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of hp_slope_xl_en + * in reg CTRL8_XL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_xl_hp_path_on_out_set(stmdev_ctx_t *ctx, + lsm6dso_hp_slope_xl_en_t val) +{ + lsm6dso_ctrl8_xl_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL8_XL, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.hp_slope_xl_en = ((uint8_t)val & 0x10U) >> 4; + reg.hp_ref_mode_xl = ((uint8_t)val & 0x20U) >> 5; + reg.hpcf_xl = (uint8_t)val & 0x07U; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL8_XL, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Accelerometer slope filter / high-pass filter selection + * on output.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of hp_slope_xl_en + * in reg CTRL8_XL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_xl_hp_path_on_out_get(stmdev_ctx_t *ctx, + lsm6dso_hp_slope_xl_en_t *val) +{ + lsm6dso_ctrl8_xl_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL8_XL, (uint8_t *)®, 1); + + switch ((reg.hp_ref_mode_xl << 5) | (reg.hp_slope_xl_en << 4) | + reg.hpcf_xl) + { + case LSM6DSO_HP_PATH_DISABLE_ON_OUT: + *val = LSM6DSO_HP_PATH_DISABLE_ON_OUT; + break; + + case LSM6DSO_SLOPE_ODR_DIV_4: + *val = LSM6DSO_SLOPE_ODR_DIV_4; + break; + + case LSM6DSO_HP_ODR_DIV_10: + *val = LSM6DSO_HP_ODR_DIV_10; + break; + + case LSM6DSO_HP_ODR_DIV_20: + *val = LSM6DSO_HP_ODR_DIV_20; + break; + + case LSM6DSO_HP_ODR_DIV_45: + *val = LSM6DSO_HP_ODR_DIV_45; + break; + + case LSM6DSO_HP_ODR_DIV_100: + *val = LSM6DSO_HP_ODR_DIV_100; + break; + + case LSM6DSO_HP_ODR_DIV_200: + *val = LSM6DSO_HP_ODR_DIV_200; + break; + + case LSM6DSO_HP_ODR_DIV_400: + *val = LSM6DSO_HP_ODR_DIV_400; + break; + + case LSM6DSO_HP_ODR_DIV_800: + *val = LSM6DSO_HP_ODR_DIV_800; + break; + + case LSM6DSO_HP_REF_MD_ODR_DIV_10: + *val = LSM6DSO_HP_REF_MD_ODR_DIV_10; + break; + + case LSM6DSO_HP_REF_MD_ODR_DIV_20: + *val = LSM6DSO_HP_REF_MD_ODR_DIV_20; + break; + + case LSM6DSO_HP_REF_MD_ODR_DIV_45: + *val = LSM6DSO_HP_REF_MD_ODR_DIV_45; + break; + + case LSM6DSO_HP_REF_MD_ODR_DIV_100: + *val = LSM6DSO_HP_REF_MD_ODR_DIV_100; + break; + + case LSM6DSO_HP_REF_MD_ODR_DIV_200: + *val = LSM6DSO_HP_REF_MD_ODR_DIV_200; + break; + + case LSM6DSO_HP_REF_MD_ODR_DIV_400: + *val = LSM6DSO_HP_REF_MD_ODR_DIV_400; + break; + + case LSM6DSO_HP_REF_MD_ODR_DIV_800: + *val = LSM6DSO_HP_REF_MD_ODR_DIV_800; + break; + + case LSM6DSO_LP_ODR_DIV_10: + *val = LSM6DSO_LP_ODR_DIV_10; + break; + + case LSM6DSO_LP_ODR_DIV_20: + *val = LSM6DSO_LP_ODR_DIV_20; + break; + + case LSM6DSO_LP_ODR_DIV_45: + *val = LSM6DSO_LP_ODR_DIV_45; + break; + + case LSM6DSO_LP_ODR_DIV_100: + *val = LSM6DSO_LP_ODR_DIV_100; + break; + + case LSM6DSO_LP_ODR_DIV_200: + *val = LSM6DSO_LP_ODR_DIV_200; + break; + + case LSM6DSO_LP_ODR_DIV_400: + *val = LSM6DSO_LP_ODR_DIV_400; + break; + + case LSM6DSO_LP_ODR_DIV_800: + *val = LSM6DSO_LP_ODR_DIV_800; + break; + + default: + *val = LSM6DSO_HP_PATH_DISABLE_ON_OUT; + break; + } + + return ret; +} + +/** + * @brief Enables accelerometer LPF2 and HPF fast-settling mode. + * The filter sets the second samples after writing this bit. + * Active only during device exit from power-down mode.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of fastsettl_mode_xl in + * reg CTRL8_XL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_xl_fast_settling_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_ctrl8_xl_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL8_XL, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.fastsettl_mode_xl = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL8_XL, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Enables accelerometer LPF2 and HPF fast-settling mode. + * The filter sets the second samples after writing this bit. + * Active only during device exit from power-down mode.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of fastsettl_mode_xl in reg CTRL8_XL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_xl_fast_settling_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_ctrl8_xl_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL8_XL, (uint8_t *)®, 1); + *val = reg.fastsettl_mode_xl; + + return ret; +} + +/** + * @brief HPF or SLOPE filter selection on wake-up and Activity/Inactivity + * functions.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of slope_fds in reg TAP_CFG0 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_xl_hp_path_internal_set(stmdev_ctx_t *ctx, + lsm6dso_slope_fds_t val) +{ + lsm6dso_tap_cfg0_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_TAP_CFG0, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.slope_fds = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_TAP_CFG0, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief HPF or SLOPE filter selection on wake-up and Activity/Inactivity + * functions.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of slope_fds in reg TAP_CFG0 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_xl_hp_path_internal_get(stmdev_ctx_t *ctx, + lsm6dso_slope_fds_t *val) +{ + lsm6dso_tap_cfg0_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_TAP_CFG0, (uint8_t *)®, 1); + + switch (reg.slope_fds) + { + case LSM6DSO_USE_SLOPE: + *val = LSM6DSO_USE_SLOPE; + break; + + case LSM6DSO_USE_HPF: + *val = LSM6DSO_USE_HPF; + break; + + default: + *val = LSM6DSO_USE_SLOPE; + break; + } + + return ret; +} + +/** + * @brief Enables gyroscope digital high-pass filter. The filter is + * enabled only if the gyro is in HP mode.[set] + * + * @param ctx read / write interface definitions + * @param val Get the values of hp_en_g and hp_en_g + * in reg CTRL7_G + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_gy_hp_path_internal_set(stmdev_ctx_t *ctx, + lsm6dso_hpm_g_t val) +{ + lsm6dso_ctrl7_g_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL7_G, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.hp_en_g = ((uint8_t)val & 0x80U) >> 7; + reg.hpm_g = (uint8_t)val & 0x03U; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL7_G, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Enables gyroscope digital high-pass filter. The filter is + * enabled only if the gyro is in HP mode.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of hp_en_g and hp_en_g + * in reg CTRL7_G + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_gy_hp_path_internal_get(stmdev_ctx_t *ctx, + lsm6dso_hpm_g_t *val) +{ + lsm6dso_ctrl7_g_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL7_G, (uint8_t *)®, 1); + + switch ((reg.hp_en_g << 7) + reg.hpm_g) + { + case LSM6DSO_HP_FILTER_NONE: + *val = LSM6DSO_HP_FILTER_NONE; + break; + + case LSM6DSO_HP_FILTER_16mHz: + *val = LSM6DSO_HP_FILTER_16mHz; + break; + + case LSM6DSO_HP_FILTER_65mHz: + *val = LSM6DSO_HP_FILTER_65mHz; + break; + + case LSM6DSO_HP_FILTER_260mHz: + *val = LSM6DSO_HP_FILTER_260mHz; + break; + + case LSM6DSO_HP_FILTER_1Hz04: + *val = LSM6DSO_HP_FILTER_1Hz04; + break; + + default: + *val = LSM6DSO_HP_FILTER_NONE; + break; + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DSO_ Auxiliary_interface + * @brief This section groups all the functions concerning + * auxiliary interface. + * @{ + * + */ + +/** + * @brief aOn auxiliary interface connect/disconnect SDO and OCS + * internal pull-up.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of ois_pu_dis in + * reg PIN_CTRL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_sdo_ocs_mode_set(stmdev_ctx_t *ctx, + lsm6dso_ois_pu_dis_t val) +{ + lsm6dso_pin_ctrl_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_PIN_CTRL, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.ois_pu_dis = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_PIN_CTRL, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief On auxiliary interface connect/disconnect SDO and OCS + * internal pull-up.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of ois_pu_dis in reg PIN_CTRL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_sdo_ocs_mode_get(stmdev_ctx_t *ctx, + lsm6dso_ois_pu_dis_t *val) +{ + lsm6dso_pin_ctrl_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_PIN_CTRL, (uint8_t *)®, 1); + + switch (reg.ois_pu_dis) + { + case LSM6DSO_AUX_PULL_UP_DISC: + *val = LSM6DSO_AUX_PULL_UP_DISC; + break; + + case LSM6DSO_AUX_PULL_UP_CONNECT: + *val = LSM6DSO_AUX_PULL_UP_CONNECT; + break; + + default: + *val = LSM6DSO_AUX_PULL_UP_DISC; + break; + } + + return ret; +} + +/** + * @brief OIS chain on aux interface power on mode.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of ois_on in reg CTRL7_G + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_pw_on_ctrl_set(stmdev_ctx_t *ctx, + lsm6dso_ois_on_t val) +{ + lsm6dso_ctrl7_g_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL7_G, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.ois_on_en = (uint8_t)val & 0x01U; + reg.ois_on = (uint8_t)val & 0x01U; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL7_G, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief aux_pw_on_ctrl: [get] OIS chain on aux interface power on mode + * + * @param ctx read / write interface definitions + * @param val Get the values of ois_on in reg CTRL7_G + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_pw_on_ctrl_get(stmdev_ctx_t *ctx, + lsm6dso_ois_on_t *val) +{ + lsm6dso_ctrl7_g_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL7_G, (uint8_t *)®, 1); + + switch (reg.ois_on) + { + case LSM6DSO_AUX_ON: + *val = LSM6DSO_AUX_ON; + break; + + case LSM6DSO_AUX_ON_BY_AUX_INTERFACE: + *val = LSM6DSO_AUX_ON_BY_AUX_INTERFACE; + break; + + default: + *val = LSM6DSO_AUX_ON; + break; + } + + return ret; +} + +/** + * @brief Accelerometer full-scale management between UI chain and + * OIS chain. When XL UI is on, the full scale is the same + * between UI/OIS and is chosen by the UI CTRL registers; + * when XL UI is in PD, the OIS can choose the FS. + * Full scales are independent between the UI/OIS chain + * but both bound to 8 g.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of xl_fs_mode in + * reg CTRL8_XL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_xl_fs_mode_set(stmdev_ctx_t *ctx, + lsm6dso_xl_fs_mode_t val) +{ + lsm6dso_ctrl8_xl_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL8_XL, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.xl_fs_mode = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL8_XL, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Accelerometer full-scale management between UI chain and + * OIS chain. When XL UI is on, the full scale is the same + * between UI/OIS and is chosen by the UI CTRL registers; + * when XL UI is in PD, the OIS can choose the FS. + * Full scales are independent between the UI/OIS chain + * but both bound to 8 g.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of xl_fs_mode in reg CTRL8_XL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_xl_fs_mode_get(stmdev_ctx_t *ctx, + lsm6dso_xl_fs_mode_t *val) +{ + lsm6dso_ctrl8_xl_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL8_XL, (uint8_t *)®, 1); + + switch (reg.xl_fs_mode) + { + case LSM6DSO_USE_SAME_XL_FS: + *val = LSM6DSO_USE_SAME_XL_FS; + break; + + case LSM6DSO_USE_DIFFERENT_XL_FS: + *val = LSM6DSO_USE_DIFFERENT_XL_FS; + break; + + default: + *val = LSM6DSO_USE_SAME_XL_FS; + break; + } + + return ret; +} + +/** + * @brief The STATUS_SPIAux register is read by the auxiliary SPI.[get] + * + * @param ctx read / write interface definitions + * @param lsm6dso_status_spiaux_t: registers STATUS_SPIAUX + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_status_reg_get(stmdev_ctx_t *ctx, + lsm6dso_status_spiaux_t *val) +{ + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_STATUS_SPIAUX, (uint8_t *) val, 1); + + return ret; +} + +/** + * @brief aux_xl_flag_data_ready: [get] AUX accelerometer data available + * + * @param ctx read / write interface definitions + * @param val change the values of xlda in reg STATUS_SPIAUX + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_xl_flag_data_ready_get(stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6dso_status_spiaux_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_STATUS_SPIAUX, (uint8_t *)®, 1); + *val = reg.xlda; + + return ret; +} + +/** + * @brief aux_gy_flag_data_ready: [get] AUX gyroscope data available. + * + * @param ctx read / write interface definitions + * @param val change the values of gda in reg STATUS_SPIAUX + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_gy_flag_data_ready_get(stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6dso_status_spiaux_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_STATUS_SPIAUX, (uint8_t *)®, 1); + *val = reg.gda; + + return ret; +} + +/** + * @brief High when the gyroscope output is in the settling phase.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of gyro_settling in reg STATUS_SPIAUX + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_gy_flag_settling_get(stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6dso_status_spiaux_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_STATUS_SPIAUX, (uint8_t *)®, 1); + *val = reg.gyro_settling; + + return ret; +} + +/** + * @brief Selects accelerometer self-test. Effective only if XL OIS + * chain is enabled.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of st_xl_ois in reg INT_OIS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_xl_self_test_set(stmdev_ctx_t *ctx, + lsm6dso_st_xl_ois_t val) +{ + lsm6dso_int_ois_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_INT_OIS, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.st_xl_ois = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_INT_OIS, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Selects accelerometer self-test. Effective only if XL OIS + * chain is enabled.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of st_xl_ois in reg INT_OIS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_xl_self_test_get(stmdev_ctx_t *ctx, + lsm6dso_st_xl_ois_t *val) +{ + lsm6dso_int_ois_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_INT_OIS, (uint8_t *)®, 1); + + switch (reg.st_xl_ois) + { + case LSM6DSO_AUX_XL_DISABLE: + *val = LSM6DSO_AUX_XL_DISABLE; + break; + + case LSM6DSO_AUX_XL_POS: + *val = LSM6DSO_AUX_XL_POS; + break; + + case LSM6DSO_AUX_XL_NEG: + *val = LSM6DSO_AUX_XL_NEG; + break; + + default: + *val = LSM6DSO_AUX_XL_DISABLE; + break; + } + + return ret; +} + +/** + * @brief Indicates polarity of DEN signal on OIS chain.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of den_lh_ois in + * reg INT_OIS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_den_polarity_set(stmdev_ctx_t *ctx, + lsm6dso_den_lh_ois_t val) +{ + lsm6dso_int_ois_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_INT_OIS, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.den_lh_ois = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_INT_OIS, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Indicates polarity of DEN signal on OIS chain.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of den_lh_ois in reg INT_OIS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_den_polarity_get(stmdev_ctx_t *ctx, + lsm6dso_den_lh_ois_t *val) +{ + lsm6dso_int_ois_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_INT_OIS, (uint8_t *)®, 1); + + switch (reg.den_lh_ois) + { + case LSM6DSO_AUX_DEN_ACTIVE_LOW: + *val = LSM6DSO_AUX_DEN_ACTIVE_LOW; + break; + + case LSM6DSO_AUX_DEN_ACTIVE_HIGH: + *val = LSM6DSO_AUX_DEN_ACTIVE_HIGH; + break; + + default: + *val = LSM6DSO_AUX_DEN_ACTIVE_LOW; + break; + } + + return ret; +} + +/** + * @brief Configure DEN mode on the OIS chain.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of lvl2_ois in reg INT_OIS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_den_mode_set(stmdev_ctx_t *ctx, + lsm6dso_lvl2_ois_t val) +{ + lsm6dso_ctrl1_ois_t ctrl1_ois; + lsm6dso_int_ois_t int_ois; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_INT_OIS, (uint8_t *) &int_ois, 1); + + if (ret == 0) + { + int_ois.lvl2_ois = (uint8_t)val & 0x01U; + ret = lsm6dso_write_reg(ctx, LSM6DSO_INT_OIS, (uint8_t *) &int_ois, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL1_OIS, (uint8_t *) &ctrl1_ois, 1); + } + + if (ret == 0) + { + ctrl1_ois.lvl1_ois = ((uint8_t)val & 0x02U) >> 1; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL1_OIS, + (uint8_t *) &ctrl1_ois, 1); + } + + return ret; +} + +/** + * @brief Configure DEN mode on the OIS chain.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of lvl2_ois in reg INT_OIS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_den_mode_get(stmdev_ctx_t *ctx, + lsm6dso_lvl2_ois_t *val) +{ + lsm6dso_ctrl1_ois_t ctrl1_ois; + lsm6dso_int_ois_t int_ois; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_INT_OIS, (uint8_t *) &int_ois, 1); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL1_OIS, (uint8_t *) &ctrl1_ois, 1); + + switch ((ctrl1_ois.lvl1_ois << 1) + int_ois.lvl2_ois) + { + case LSM6DSO_AUX_DEN_DISABLE: + *val = LSM6DSO_AUX_DEN_DISABLE; + break; + + case LSM6DSO_AUX_DEN_LEVEL_LATCH: + *val = LSM6DSO_AUX_DEN_LEVEL_LATCH; + break; + + case LSM6DSO_AUX_DEN_LEVEL_TRIG: + *val = LSM6DSO_AUX_DEN_LEVEL_TRIG; + break; + + default: + *val = LSM6DSO_AUX_DEN_DISABLE; + break; + } + } + + return ret; +} + +/** + * @brief Enables/Disable OIS chain DRDY on INT2 pin. + * This setting has priority over all other INT2 settings.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of int2_drdy_ois in reg INT_OIS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_drdy_on_int2_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_int_ois_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_INT_OIS, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.int2_drdy_ois = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_INT_OIS, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Enables/Disable OIS chain DRDY on INT2 pin. + * This setting has priority over all other INT2 settings.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of int2_drdy_ois in reg INT_OIS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_drdy_on_int2_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_int_ois_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_INT_OIS, (uint8_t *)®, 1); + *val = reg.int2_drdy_ois; + + return ret; +} + +/** + * @brief Enables OIS chain data processing for gyro in Mode 3 and Mode 4 + * (mode4_en = 1) and accelerometer data in and Mode 4 (mode4_en = 1). + * When the OIS chain is enabled, the OIS outputs are available + * through the SPI2 in registers OUTX_L_G (22h) through + * OUTZ_H_G (27h) and STATUS_REG (1Eh) / STATUS_SPIAux, and + * LPF1 is dedicated to this chain.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of ois_en_spi2 in + * reg CTRL1_OIS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_mode_set(stmdev_ctx_t *ctx, + lsm6dso_ois_en_spi2_t val) +{ + lsm6dso_ctrl1_ois_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL1_OIS, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.ois_en_spi2 = (uint8_t)val & 0x01U; + reg.mode4_en = ((uint8_t)val & 0x02U) >> 1; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL1_OIS, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Enables OIS chain data processing for gyro in Mode 3 and Mode 4 + * (mode4_en = 1) and accelerometer data in and Mode 4 (mode4_en = 1). + * When the OIS chain is enabled, the OIS outputs are available + * through the SPI2 in registers OUTX_L_G (22h) through + * OUTZ_H_G (27h) and STATUS_REG (1Eh) / STATUS_SPIAux, and + * LPF1 is dedicated to this chain.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of ois_en_spi2 in + * reg CTRL1_OIS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_mode_get(stmdev_ctx_t *ctx, + lsm6dso_ois_en_spi2_t *val) +{ + lsm6dso_ctrl1_ois_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL1_OIS, (uint8_t *)®, 1); + + switch ((reg.mode4_en << 1) | reg.ois_en_spi2) + { + case LSM6DSO_AUX_DISABLE: + *val = LSM6DSO_AUX_DISABLE; + break; + + case LSM6DSO_MODE_3_GY: + *val = LSM6DSO_MODE_3_GY; + break; + + case LSM6DSO_MODE_4_GY_XL: + *val = LSM6DSO_MODE_4_GY_XL; + break; + + default: + *val = LSM6DSO_AUX_DISABLE; + break; + } + + return ret; +} + +/** + * @brief Selects gyroscope OIS chain full-scale.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of fs_g_ois in reg CTRL1_OIS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_gy_full_scale_set(stmdev_ctx_t *ctx, + lsm6dso_fs_g_ois_t val) +{ + lsm6dso_ctrl1_ois_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL1_OIS, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.fs_g_ois = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL1_OIS, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Selects gyroscope OIS chain full-scale.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of fs_g_ois in reg CTRL1_OIS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_gy_full_scale_get(stmdev_ctx_t *ctx, + lsm6dso_fs_g_ois_t *val) +{ + lsm6dso_ctrl1_ois_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL1_OIS, (uint8_t *)®, 1); + + switch (reg.fs_g_ois) + { + case LSM6DSO_250dps_AUX: + *val = LSM6DSO_250dps_AUX; + break; + + case LSM6DSO_125dps_AUX: + *val = LSM6DSO_125dps_AUX; + break; + + case LSM6DSO_500dps_AUX: + *val = LSM6DSO_500dps_AUX; + break; + + case LSM6DSO_1000dps_AUX: + *val = LSM6DSO_1000dps_AUX; + break; + + case LSM6DSO_2000dps_AUX: + *val = LSM6DSO_2000dps_AUX; + break; + + default: + *val = LSM6DSO_250dps_AUX; + break; + } + + return ret; +} + +/** + * @brief SPI2 3- or 4-wire interface.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of sim_ois in reg CTRL1_OIS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_spi_mode_set(stmdev_ctx_t *ctx, + lsm6dso_sim_ois_t val) +{ + lsm6dso_ctrl1_ois_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL1_OIS, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.sim_ois = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL1_OIS, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief SPI2 3- or 4-wire interface.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of sim_ois in reg CTRL1_OIS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_spi_mode_get(stmdev_ctx_t *ctx, + lsm6dso_sim_ois_t *val) +{ + lsm6dso_ctrl1_ois_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL1_OIS, (uint8_t *)®, 1); + + switch (reg.sim_ois) + { + case LSM6DSO_AUX_SPI_4_WIRE: + *val = LSM6DSO_AUX_SPI_4_WIRE; + break; + + case LSM6DSO_AUX_SPI_3_WIRE: + *val = LSM6DSO_AUX_SPI_3_WIRE; + break; + + default: + *val = LSM6DSO_AUX_SPI_4_WIRE; + break; + } + + return ret; +} + +/** + * @brief Selects gyroscope digital LPF1 filter bandwidth.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of ftype_ois in + * reg CTRL2_OIS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_gy_lp1_bandwidth_set(stmdev_ctx_t *ctx, + lsm6dso_ftype_ois_t val) +{ + lsm6dso_ctrl2_ois_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL2_OIS, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.ftype_ois = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL2_OIS, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Selects gyroscope digital LPF1 filter bandwidth.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of ftype_ois in reg CTRL2_OIS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_gy_lp1_bandwidth_get(stmdev_ctx_t *ctx, + lsm6dso_ftype_ois_t *val) +{ + lsm6dso_ctrl2_ois_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL2_OIS, (uint8_t *)®, 1); + + switch (reg.ftype_ois) + { + case LSM6DSO_351Hz39: + *val = LSM6DSO_351Hz39; + break; + + case LSM6DSO_236Hz63: + *val = LSM6DSO_236Hz63; + break; + + case LSM6DSO_172Hz70: + *val = LSM6DSO_172Hz70; + break; + + case LSM6DSO_937Hz91: + *val = LSM6DSO_937Hz91; + break; + + default: + *val = LSM6DSO_351Hz39; + break; + } + + return ret; +} + +/** + * @brief Selects gyroscope OIS chain digital high-pass filter cutoff.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of hpm_ois in reg CTRL2_OIS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_gy_hp_bandwidth_set(stmdev_ctx_t *ctx, + lsm6dso_hpm_ois_t val) +{ + lsm6dso_ctrl2_ois_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL2_OIS, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.hpm_ois = (uint8_t)val & 0x03U; + reg.hp_en_ois = ((uint8_t)val & 0x10U) >> 4; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL2_OIS, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Selects gyroscope OIS chain digital high-pass filter cutoff.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of hpm_ois in reg CTRL2_OIS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_gy_hp_bandwidth_get(stmdev_ctx_t *ctx, + lsm6dso_hpm_ois_t *val) +{ + lsm6dso_ctrl2_ois_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL2_OIS, (uint8_t *)®, 1); + + switch ((reg.hp_en_ois << 4) | reg.hpm_ois) + { + case LSM6DSO_AUX_HP_DISABLE: + *val = LSM6DSO_AUX_HP_DISABLE; + break; + + case LSM6DSO_AUX_HP_Hz016: + *val = LSM6DSO_AUX_HP_Hz016; + break; + + case LSM6DSO_AUX_HP_Hz065: + *val = LSM6DSO_AUX_HP_Hz065; + break; + + case LSM6DSO_AUX_HP_Hz260: + *val = LSM6DSO_AUX_HP_Hz260; + break; + + case LSM6DSO_AUX_HP_1Hz040: + *val = LSM6DSO_AUX_HP_1Hz040; + break; + + default: + *val = LSM6DSO_AUX_HP_DISABLE; + break; + } + + return ret; +} + +/** + * @brief Enable / Disables OIS chain clamp. + * Enable: All OIS chain outputs = 8000h + * during self-test; Disable: OIS chain self-test + * outputs dependent from the aux gyro full + * scale selected.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of st_ois_clampdis in + * reg CTRL3_OIS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_gy_clamp_set(stmdev_ctx_t *ctx, + lsm6dso_st_ois_clampdis_t val) +{ + lsm6dso_ctrl3_ois_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL3_OIS, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.st_ois_clampdis = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL3_OIS, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Enable / Disables OIS chain clamp. + * Enable: All OIS chain outputs = 8000h + * during self-test; Disable: OIS chain self-test + * outputs dependent from the aux gyro full + * scale selected.[set] + * + * @param ctx read / write interface definitions + * @param val Get the values of st_ois_clampdis in + * reg CTRL3_OIS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_gy_clamp_get(stmdev_ctx_t *ctx, + lsm6dso_st_ois_clampdis_t *val) +{ + lsm6dso_ctrl3_ois_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL3_OIS, (uint8_t *)®, 1); + + switch (reg.st_ois_clampdis) + { + case LSM6DSO_ENABLE_CLAMP: + *val = LSM6DSO_ENABLE_CLAMP; + break; + + case LSM6DSO_DISABLE_CLAMP: + *val = LSM6DSO_DISABLE_CLAMP; + break; + + default: + *val = LSM6DSO_ENABLE_CLAMP; + break; + } + + return ret; +} + +/** + * @brief Selects gyroscope OIS chain self-test.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of st_ois in reg CTRL3_OIS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_gy_self_test_set(stmdev_ctx_t *ctx, + lsm6dso_st_ois_t val) +{ + lsm6dso_ctrl3_ois_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL3_OIS, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.st_ois = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL3_OIS, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Selects gyroscope OIS chain self-test.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of st_ois in reg CTRL3_OIS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_gy_self_test_get(stmdev_ctx_t *ctx, + lsm6dso_st_ois_t *val) +{ + lsm6dso_ctrl3_ois_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL3_OIS, (uint8_t *)®, 1); + + switch (reg.st_ois) + { + case LSM6DSO_AUX_GY_DISABLE: + *val = LSM6DSO_AUX_GY_DISABLE; + break; + + case LSM6DSO_AUX_GY_POS: + *val = LSM6DSO_AUX_GY_POS; + break; + + case LSM6DSO_AUX_GY_NEG: + *val = LSM6DSO_AUX_GY_NEG; + break; + + default: + *val = LSM6DSO_AUX_GY_DISABLE; + break; + } + + return ret; +} + +/** + * @brief Selects accelerometer OIS channel bandwidth.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of + * filter_xl_conf_ois in reg CTRL3_OIS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_xl_bandwidth_set(stmdev_ctx_t *ctx, + lsm6dso_filter_xl_conf_ois_t val) +{ + lsm6dso_ctrl3_ois_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL3_OIS, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.filter_xl_conf_ois = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL3_OIS, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Selects accelerometer OIS channel bandwidth.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of + * filter_xl_conf_ois in reg CTRL3_OIS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_xl_bandwidth_get(stmdev_ctx_t *ctx, + lsm6dso_filter_xl_conf_ois_t *val) +{ + lsm6dso_ctrl3_ois_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL3_OIS, (uint8_t *)®, 1); + + switch (reg.filter_xl_conf_ois) + { + case LSM6DSO_289Hz: + *val = LSM6DSO_289Hz; + break; + + case LSM6DSO_258Hz: + *val = LSM6DSO_258Hz; + break; + + case LSM6DSO_120Hz: + *val = LSM6DSO_120Hz; + break; + + case LSM6DSO_65Hz2: + *val = LSM6DSO_65Hz2; + break; + + case LSM6DSO_33Hz2: + *val = LSM6DSO_33Hz2; + break; + + case LSM6DSO_16Hz6: + *val = LSM6DSO_16Hz6; + break; + + case LSM6DSO_8Hz30: + *val = LSM6DSO_8Hz30; + break; + + case LSM6DSO_4Hz15: + *val = LSM6DSO_4Hz15; + break; + + default: + *val = LSM6DSO_289Hz; + break; + } + + return ret; +} + +/** + * @brief Selects accelerometer OIS channel full-scale.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of fs_xl_ois in + * reg CTRL3_OIS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_xl_full_scale_set(stmdev_ctx_t *ctx, + lsm6dso_fs_xl_ois_t val) +{ + lsm6dso_ctrl3_ois_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL3_OIS, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.fs_xl_ois = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL3_OIS, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Selects accelerometer OIS channel full-scale.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of fs_xl_ois in reg CTRL3_OIS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_aux_xl_full_scale_get(stmdev_ctx_t *ctx, + lsm6dso_fs_xl_ois_t *val) +{ + lsm6dso_ctrl3_ois_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL3_OIS, (uint8_t *)®, 1); + + switch (reg.fs_xl_ois) + { + case LSM6DSO_AUX_2g: + *val = LSM6DSO_AUX_2g; + break; + + case LSM6DSO_AUX_16g: + *val = LSM6DSO_AUX_16g; + break; + + case LSM6DSO_AUX_4g: + *val = LSM6DSO_AUX_4g; + break; + + case LSM6DSO_AUX_8g: + *val = LSM6DSO_AUX_8g; + break; + + default: + *val = LSM6DSO_AUX_2g; + break; + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DSO_ main_serial_interface + * @brief This section groups all the functions concerning main + * serial interface management (not auxiliary) + * @{ + * + */ + +/** + * @brief Connect/Disconnect SDO/SA0 internal pull-up.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of sdo_pu_en in + * reg PIN_CTRL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sdo_sa0_mode_set(stmdev_ctx_t *ctx, + lsm6dso_sdo_pu_en_t val) +{ + lsm6dso_pin_ctrl_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_PIN_CTRL, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.sdo_pu_en = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_PIN_CTRL, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Connect/Disconnect SDO/SA0 internal pull-up.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of sdo_pu_en in reg PIN_CTRL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sdo_sa0_mode_get(stmdev_ctx_t *ctx, + lsm6dso_sdo_pu_en_t *val) +{ + lsm6dso_pin_ctrl_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_PIN_CTRL, (uint8_t *)®, 1); + + switch (reg.sdo_pu_en) + { + case LSM6DSO_PULL_UP_DISC: + *val = LSM6DSO_PULL_UP_DISC; + break; + + case LSM6DSO_PULL_UP_CONNECT: + *val = LSM6DSO_PULL_UP_CONNECT; + break; + + default: + *val = LSM6DSO_PULL_UP_DISC; + break; + } + + return ret; +} + +/** + * @brief SPI Serial Interface Mode selection.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of sim in reg CTRL3_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_spi_mode_set(stmdev_ctx_t *ctx, lsm6dso_sim_t val) +{ + lsm6dso_ctrl3_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL3_C, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.sim = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL3_C, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief SPI Serial Interface Mode selection.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of sim in reg CTRL3_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_spi_mode_get(stmdev_ctx_t *ctx, lsm6dso_sim_t *val) +{ + lsm6dso_ctrl3_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL3_C, (uint8_t *)®, 1); + + switch (reg.sim) + { + case LSM6DSO_SPI_4_WIRE: + *val = LSM6DSO_SPI_4_WIRE; + break; + + case LSM6DSO_SPI_3_WIRE: + *val = LSM6DSO_SPI_3_WIRE; + break; + + default: + *val = LSM6DSO_SPI_4_WIRE; + break; + } + + return ret; +} + +/** + * @brief Disable / Enable I2C interface.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of i2c_disable in + * reg CTRL4_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_i2c_interface_set(stmdev_ctx_t *ctx, + lsm6dso_i2c_disable_t val) +{ + lsm6dso_ctrl4_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL4_C, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.i2c_disable = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL4_C, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Disable / Enable I2C interface.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of i2c_disable in + * reg CTRL4_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_i2c_interface_get(stmdev_ctx_t *ctx, + lsm6dso_i2c_disable_t *val) +{ + lsm6dso_ctrl4_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL4_C, (uint8_t *)®, 1); + + switch (reg.i2c_disable) + { + case LSM6DSO_I2C_ENABLE: + *val = LSM6DSO_I2C_ENABLE; + break; + + case LSM6DSO_I2C_DISABLE: + *val = LSM6DSO_I2C_DISABLE; + break; + + default: + *val = LSM6DSO_I2C_ENABLE; + break; + } + + return ret; +} + +/** + * @brief I3C Enable/Disable communication protocol[.set] + * + * @param ctx read / write interface definitions + * @param val change the values of i3c_disable + * in reg CTRL9_XL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_i3c_disable_set(stmdev_ctx_t *ctx, + lsm6dso_i3c_disable_t val) +{ + lsm6dso_i3c_bus_avb_t i3c_bus_avb; + lsm6dso_ctrl9_xl_t ctrl9_xl; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL9_XL, (uint8_t *)&ctrl9_xl, 1); + + if (ret == 0) + { + ctrl9_xl.i3c_disable = ((uint8_t)val & 0x80U) >> 7; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL9_XL, (uint8_t *)&ctrl9_xl, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_I3C_BUS_AVB, + (uint8_t *)&i3c_bus_avb, 1); + } + + if (ret == 0) + { + i3c_bus_avb.i3c_bus_avb_sel = (uint8_t)val & 0x03U; + ret = lsm6dso_write_reg(ctx, LSM6DSO_I3C_BUS_AVB, + (uint8_t *)&i3c_bus_avb, 1); + } + + return ret; +} + +/** + * @brief I3C Enable/Disable communication protocol.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of i3c_disable in + * reg CTRL9_XL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_i3c_disable_get(stmdev_ctx_t *ctx, + lsm6dso_i3c_disable_t *val) +{ + lsm6dso_ctrl9_xl_t ctrl9_xl; + lsm6dso_i3c_bus_avb_t i3c_bus_avb; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL9_XL, (uint8_t *)&ctrl9_xl, 1); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_I3C_BUS_AVB, + (uint8_t *)&i3c_bus_avb, 1); + + switch ((ctrl9_xl.i3c_disable << 7) | i3c_bus_avb.i3c_bus_avb_sel) + { + case LSM6DSO_I3C_DISABLE: + *val = LSM6DSO_I3C_DISABLE; + break; + + case LSM6DSO_I3C_ENABLE_T_50us: + *val = LSM6DSO_I3C_ENABLE_T_50us; + break; + + case LSM6DSO_I3C_ENABLE_T_2us: + *val = LSM6DSO_I3C_ENABLE_T_2us; + break; + + case LSM6DSO_I3C_ENABLE_T_1ms: + *val = LSM6DSO_I3C_ENABLE_T_1ms; + break; + + case LSM6DSO_I3C_ENABLE_T_25ms: + *val = LSM6DSO_I3C_ENABLE_T_25ms; + break; + + default: + *val = LSM6DSO_I3C_DISABLE; + break; + } + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DSO_interrupt_pins + * @brief This section groups all the functions that manage interrupt pins + * @{ + * + */ + +/** + * @brief Connect/Disconnect INT1 internal pull-down.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of pd_dis_int1 in reg I3C_BUS_AVB + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_int1_mode_set(stmdev_ctx_t *ctx, + lsm6dso_int1_pd_en_t val) +{ + lsm6dso_i3c_bus_avb_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_I3C_BUS_AVB, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.pd_dis_int1 = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_I3C_BUS_AVB, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Connect/Disconnect INT1 internal pull-down.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of pd_dis_int1 in reg I3C_BUS_AVB + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_int1_mode_get(stmdev_ctx_t *ctx, + lsm6dso_int1_pd_en_t *val) +{ + lsm6dso_i3c_bus_avb_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_I3C_BUS_AVB, (uint8_t *)®, 1); + + switch (reg.pd_dis_int1) + { + case LSM6DSO_PULL_DOWN_DISC: + *val = LSM6DSO_PULL_DOWN_DISC; + break; + + case LSM6DSO_PULL_DOWN_CONNECT: + *val = LSM6DSO_PULL_DOWN_CONNECT; + break; + + default: + *val = LSM6DSO_PULL_DOWN_DISC; + break; + } + + return ret; +} + +/** + * @brief Push-pull/open drain selection on interrupt pads.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of pp_od in reg CTRL3_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_pin_mode_set(stmdev_ctx_t *ctx, lsm6dso_pp_od_t val) +{ + lsm6dso_ctrl3_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL3_C, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.pp_od = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL3_C, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Push-pull/open drain selection on interrupt pads.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of pp_od in reg CTRL3_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_pin_mode_get(stmdev_ctx_t *ctx, lsm6dso_pp_od_t *val) +{ + lsm6dso_ctrl3_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL3_C, (uint8_t *)®, 1); + + switch (reg.pp_od) + { + case LSM6DSO_PUSH_PULL: + *val = LSM6DSO_PUSH_PULL; + break; + + case LSM6DSO_OPEN_DRAIN: + *val = LSM6DSO_OPEN_DRAIN; + break; + + default: + *val = LSM6DSO_PUSH_PULL; + break; + } + + return ret; +} + +/** + * @brief Interrupt active-high/low.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of h_lactive in reg CTRL3_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_pin_polarity_set(stmdev_ctx_t *ctx, + lsm6dso_h_lactive_t val) +{ + lsm6dso_ctrl3_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL3_C, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.h_lactive = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL3_C, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Interrupt active-high/low.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of h_lactive in reg CTRL3_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_pin_polarity_get(stmdev_ctx_t *ctx, + lsm6dso_h_lactive_t *val) +{ + lsm6dso_ctrl3_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL3_C, (uint8_t *)®, 1); + + switch (reg.h_lactive) + { + case LSM6DSO_ACTIVE_HIGH: + *val = LSM6DSO_ACTIVE_HIGH; + break; + + case LSM6DSO_ACTIVE_LOW: + *val = LSM6DSO_ACTIVE_LOW; + break; + + default: + *val = LSM6DSO_ACTIVE_HIGH; + break; + } + + return ret; +} + +/** + * @brief All interrupt signals become available on INT1 pin.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of int2_on_int1 in reg CTRL4_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_all_on_int1_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_ctrl4_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL4_C, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.int2_on_int1 = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL4_C, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief All interrupt signals become available on INT1 pin.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of int2_on_int1 in reg CTRL4_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_all_on_int1_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_ctrl4_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL4_C, (uint8_t *)®, 1); + *val = reg.int2_on_int1; + + return ret; +} + +/** + * @brief Interrupt notification mode.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of lir in reg TAP_CFG0 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_int_notification_set(stmdev_ctx_t *ctx, + lsm6dso_lir_t val) +{ + lsm6dso_tap_cfg0_t tap_cfg0; + lsm6dso_page_rw_t page_rw; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_TAP_CFG0, (uint8_t *) &tap_cfg0, 1); + + if (ret == 0) + { + tap_cfg0.lir = (uint8_t)val & 0x01U; + tap_cfg0.int_clr_on_read = (uint8_t)val & 0x01U; + ret = lsm6dso_write_reg(ctx, LSM6DSO_TAP_CFG0, (uint8_t *) &tap_cfg0, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_PAGE_RW, (uint8_t *) &page_rw, 1); + } + + if (ret == 0) + { + page_rw.emb_func_lir = ((uint8_t)val & 0x02U) >> 1; + ret = lsm6dso_write_reg(ctx, LSM6DSO_PAGE_RW, (uint8_t *) &page_rw, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Interrupt notification mode.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of lir in reg TAP_CFG0 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_int_notification_get(stmdev_ctx_t *ctx, + lsm6dso_lir_t *val) +{ + lsm6dso_tap_cfg0_t tap_cfg0; + lsm6dso_page_rw_t page_rw; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_TAP_CFG0, (uint8_t *) &tap_cfg0, 1); + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_PAGE_RW, (uint8_t *) &page_rw, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + if (ret == 0) + { + switch ((page_rw.emb_func_lir << 1) | tap_cfg0.lir) + { + case LSM6DSO_ALL_INT_PULSED: + *val = LSM6DSO_ALL_INT_PULSED; + break; + + case LSM6DSO_BASE_LATCHED_EMB_PULSED: + *val = LSM6DSO_BASE_LATCHED_EMB_PULSED; + break; + + case LSM6DSO_BASE_PULSED_EMB_LATCHED: + *val = LSM6DSO_BASE_PULSED_EMB_LATCHED; + break; + + case LSM6DSO_ALL_INT_LATCHED: + *val = LSM6DSO_ALL_INT_LATCHED; + break; + + default: + *val = LSM6DSO_ALL_INT_PULSED; + break; + } + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_PAGE_RW, (uint8_t *) &page_rw, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DSO_Wake_Up_event + * @brief This section groups all the functions that manage the Wake Up + * event generation. + * @{ + * + */ + +/** + * @brief Weight of 1 LSB of wakeup threshold.[set] + * 0: 1 LSB =FS_XL / 64 + * 1: 1 LSB = FS_XL / 256 + * + * @param ctx read / write interface definitions + * @param val change the values of wake_ths_w in + * reg WAKE_UP_DUR + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_wkup_ths_weight_set(stmdev_ctx_t *ctx, + lsm6dso_wake_ths_w_t val) +{ + lsm6dso_wake_up_dur_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_WAKE_UP_DUR, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.wake_ths_w = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_WAKE_UP_DUR, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Weight of 1 LSB of wakeup threshold.[get] + * 0: 1 LSB =FS_XL / 64 + * 1: 1 LSB = FS_XL / 256 + * + * @param ctx read / write interface definitions + * @param val Get the values of wake_ths_w in + * reg WAKE_UP_DUR + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_wkup_ths_weight_get(stmdev_ctx_t *ctx, + lsm6dso_wake_ths_w_t *val) +{ + lsm6dso_wake_up_dur_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_WAKE_UP_DUR, (uint8_t *)®, 1); + + switch (reg.wake_ths_w) + { + case LSM6DSO_LSb_FS_DIV_64: + *val = LSM6DSO_LSb_FS_DIV_64; + break; + + case LSM6DSO_LSb_FS_DIV_256: + *val = LSM6DSO_LSb_FS_DIV_256; + break; + + default: + *val = LSM6DSO_LSb_FS_DIV_64; + break; + } + + return ret; +} + +/** + * @brief Threshold for wakeup: 1 LSB weight depends on WAKE_THS_W in + * WAKE_UP_DUR.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of wk_ths in reg WAKE_UP_THS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_wkup_threshold_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_wake_up_ths_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_WAKE_UP_THS, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.wk_ths = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_WAKE_UP_THS, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Threshold for wakeup: 1 LSB weight depends on WAKE_THS_W in + * WAKE_UP_DUR.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of wk_ths in reg WAKE_UP_THS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_wkup_threshold_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_wake_up_ths_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_WAKE_UP_THS, (uint8_t *)®, 1); + *val = reg.wk_ths; + + return ret; +} + +/** + * @brief Wake up duration event.[set] + * 1LSb = 1 / ODR + * + * @param ctx read / write interface definitions + * @param val change the values of usr_off_on_wu in reg WAKE_UP_THS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_xl_usr_offset_on_wkup_set(stmdev_ctx_t *ctx, + uint8_t val) +{ + lsm6dso_wake_up_ths_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_WAKE_UP_THS, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.usr_off_on_wu = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_WAKE_UP_THS, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Wake up duration event.[get] + * 1LSb = 1 / ODR + * + * @param ctx read / write interface definitions + * @param val change the values of usr_off_on_wu in reg WAKE_UP_THS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_xl_usr_offset_on_wkup_get(stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6dso_wake_up_ths_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_WAKE_UP_THS, (uint8_t *)®, 1); + *val = reg.usr_off_on_wu; + + return ret; +} + +/** + * @brief Wake up duration event.[set] + * 1LSb = 1 / ODR + * + * @param ctx read / write interface definitions + * @param val change the values of wake_dur in reg WAKE_UP_DUR + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_wkup_dur_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_wake_up_dur_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_WAKE_UP_DUR, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.wake_dur = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_WAKE_UP_DUR, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Wake up duration event.[get] + * 1LSb = 1 / ODR + * + * @param ctx read / write interface definitions + * @param val change the values of wake_dur in reg WAKE_UP_DUR + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_wkup_dur_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_wake_up_dur_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_WAKE_UP_DUR, (uint8_t *)®, 1); + *val = reg.wake_dur; + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DSO_ Activity/Inactivity_detection + * @brief This section groups all the functions concerning + * activity/inactivity detection. + * @{ + * + */ + +/** + * @brief Enables gyroscope Sleep mode.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of sleep_g in reg CTRL4_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_gy_sleep_mode_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_ctrl4_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL4_C, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.sleep_g = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL4_C, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Enables gyroscope Sleep mode.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of sleep_g in reg CTRL4_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_gy_sleep_mode_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_ctrl4_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL4_C, (uint8_t *)®, 1); + *val = reg.sleep_g; + + return ret; +} + +/** + * @brief Drives the sleep status instead of + * sleep change on INT pins + * (only if INT1_SLEEP_CHANGE or + * INT2_SLEEP_CHANGE bits are enabled).[set] + * + * @param ctx read / write interface definitions + * @param val change the values of sleep_status_on_int in reg TAP_CFG0 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_act_pin_notification_set(stmdev_ctx_t *ctx, + lsm6dso_sleep_status_on_int_t val) +{ + lsm6dso_tap_cfg0_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_TAP_CFG0, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.sleep_status_on_int = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_TAP_CFG0, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Drives the sleep status instead of + * sleep change on INT pins (only if + * INT1_SLEEP_CHANGE or + * INT2_SLEEP_CHANGE bits are enabled).[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of sleep_status_on_int in reg TAP_CFG0 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_act_pin_notification_get(stmdev_ctx_t *ctx, + lsm6dso_sleep_status_on_int_t *val) +{ + lsm6dso_tap_cfg0_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_TAP_CFG0, (uint8_t *)®, 1); + + switch (reg.sleep_status_on_int) + { + case LSM6DSO_DRIVE_SLEEP_CHG_EVENT: + *val = LSM6DSO_DRIVE_SLEEP_CHG_EVENT; + break; + + case LSM6DSO_DRIVE_SLEEP_STATUS: + *val = LSM6DSO_DRIVE_SLEEP_STATUS; + break; + + default: + *val = LSM6DSO_DRIVE_SLEEP_CHG_EVENT; + break; + } + + return ret; +} + +/** + * @brief Enable inactivity function.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of inact_en in reg TAP_CFG2 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_act_mode_set(stmdev_ctx_t *ctx, + lsm6dso_inact_en_t val) +{ + lsm6dso_tap_cfg2_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_TAP_CFG2, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.inact_en = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_TAP_CFG2, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Enable inactivity function.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of inact_en in reg TAP_CFG2 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_act_mode_get(stmdev_ctx_t *ctx, + lsm6dso_inact_en_t *val) +{ + lsm6dso_tap_cfg2_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_TAP_CFG2, (uint8_t *)®, 1); + + switch (reg.inact_en) + { + case LSM6DSO_XL_AND_GY_NOT_AFFECTED: + *val = LSM6DSO_XL_AND_GY_NOT_AFFECTED; + break; + + case LSM6DSO_XL_12Hz5_GY_NOT_AFFECTED: + *val = LSM6DSO_XL_12Hz5_GY_NOT_AFFECTED; + break; + + case LSM6DSO_XL_12Hz5_GY_SLEEP: + *val = LSM6DSO_XL_12Hz5_GY_SLEEP; + break; + + case LSM6DSO_XL_12Hz5_GY_PD: + *val = LSM6DSO_XL_12Hz5_GY_PD; + break; + + default: + *val = LSM6DSO_XL_AND_GY_NOT_AFFECTED; + break; + } + + return ret; +} + +/** + * @brief Duration to go in sleep mode.[set] + * 1 LSb = 512 / ODR + * + * @param ctx read / write interface definitions + * @param val change the values of sleep_dur in reg WAKE_UP_DUR + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_act_sleep_dur_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_wake_up_dur_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_WAKE_UP_DUR, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.sleep_dur = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_WAKE_UP_DUR, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Duration to go in sleep mode.[get] + * 1 LSb = 512 / ODR + * + * @param ctx read / write interface definitions + * @param val change the values of sleep_dur in reg WAKE_UP_DUR + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_act_sleep_dur_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_wake_up_dur_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_WAKE_UP_DUR, (uint8_t *)®, 1); + *val = reg.sleep_dur; + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DSO_tap_generator + * @brief This section groups all the functions that manage the + * tap and double tap event generation. + * @{ + * + */ + +/** + * @brief Enable Z direction in tap recognition.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of tap_z_en in reg TAP_CFG0 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_tap_detection_on_z_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_tap_cfg0_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_TAP_CFG0, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.tap_z_en = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_TAP_CFG0, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Enable Z direction in tap recognition.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of tap_z_en in reg TAP_CFG0 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_tap_detection_on_z_get(stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6dso_tap_cfg0_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_TAP_CFG0, (uint8_t *)®, 1); + *val = reg.tap_z_en; + + return ret; +} + +/** + * @brief Enable Y direction in tap recognition.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of tap_y_en in reg TAP_CFG0 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_tap_detection_on_y_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_tap_cfg0_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_TAP_CFG0, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.tap_y_en = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_TAP_CFG0, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Enable Y direction in tap recognition.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of tap_y_en in reg TAP_CFG0 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_tap_detection_on_y_get(stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6dso_tap_cfg0_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_TAP_CFG0, (uint8_t *)®, 1); + *val = reg.tap_y_en; + + return ret; +} + +/** + * @brief Enable X direction in tap recognition.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of tap_x_en in reg TAP_CFG0 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_tap_detection_on_x_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_tap_cfg0_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_TAP_CFG0, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.tap_x_en = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_TAP_CFG0, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Enable X direction in tap recognition.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of tap_x_en in reg TAP_CFG0 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_tap_detection_on_x_get(stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6dso_tap_cfg0_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_TAP_CFG0, (uint8_t *)®, 1); + *val = reg.tap_x_en; + + return ret; +} + +/** + * @brief X-axis tap recognition threshold.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of tap_ths_x in reg TAP_CFG1 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_tap_threshold_x_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_tap_cfg1_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_TAP_CFG1, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.tap_ths_x = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_TAP_CFG1, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief X-axis tap recognition threshold.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of tap_ths_x in reg TAP_CFG1 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_tap_threshold_x_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_tap_cfg1_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_TAP_CFG1, (uint8_t *)®, 1); + *val = reg.tap_ths_x; + + return ret; +} + +/** + * @brief Selection of axis priority for TAP detection.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of tap_priority in + * reg TAP_CFG1 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_tap_axis_priority_set(stmdev_ctx_t *ctx, + lsm6dso_tap_priority_t val) +{ + lsm6dso_tap_cfg1_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_TAP_CFG1, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.tap_priority = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_TAP_CFG1, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Selection of axis priority for TAP detection.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of tap_priority in + * reg TAP_CFG1 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_tap_axis_priority_get(stmdev_ctx_t *ctx, + lsm6dso_tap_priority_t *val) +{ + lsm6dso_tap_cfg1_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_TAP_CFG1, (uint8_t *)®, 1); + + switch (reg.tap_priority) + { + case LSM6DSO_XYZ: + *val = LSM6DSO_XYZ; + break; + + case LSM6DSO_YXZ: + *val = LSM6DSO_YXZ; + break; + + case LSM6DSO_XZY: + *val = LSM6DSO_XZY; + break; + + case LSM6DSO_ZYX: + *val = LSM6DSO_ZYX; + break; + + case LSM6DSO_YZX: + *val = LSM6DSO_YZX; + break; + + case LSM6DSO_ZXY: + *val = LSM6DSO_ZXY; + break; + + default: + *val = LSM6DSO_XYZ; + break; + } + + return ret; +} + +/** + * @brief Y-axis tap recognition threshold.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of tap_ths_y in reg TAP_CFG2 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_tap_threshold_y_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_tap_cfg2_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_TAP_CFG2, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.tap_ths_y = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_TAP_CFG2, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Y-axis tap recognition threshold.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of tap_ths_y in reg TAP_CFG2 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_tap_threshold_y_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_tap_cfg2_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_TAP_CFG2, (uint8_t *)®, 1); + *val = reg.tap_ths_y; + + return ret; +} + +/** + * @brief Z-axis recognition threshold.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of tap_ths_z in reg TAP_THS_6D + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_tap_threshold_z_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_tap_ths_6d_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_TAP_THS_6D, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.tap_ths_z = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_TAP_THS_6D, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Z-axis recognition threshold.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of tap_ths_z in reg TAP_THS_6D + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_tap_threshold_z_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_tap_ths_6d_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_TAP_THS_6D, (uint8_t *)®, 1); + *val = reg.tap_ths_z; + + return ret; +} + +/** + * @brief Maximum duration is the maximum time of an + * over threshold signal detection to be recognized + * as a tap event. The default value of these bits + * is 00b which corresponds to 4*ODR_XL time. + * If the SHOCK[1:0] bits are set to a different + * value, 1LSB corresponds to 8*ODR_XL time.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of shock in reg INT_DUR2 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_tap_shock_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_int_dur2_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_INT_DUR2, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.shock = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_INT_DUR2, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Maximum duration is the maximum time of an + * over threshold signal detection to be recognized + * as a tap event. The default value of these bits + * is 00b which corresponds to 4*ODR_XL time. + * If the SHOCK[1:0] bits are set to a different + * value, 1LSB corresponds to 8*ODR_XL time.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of shock in reg INT_DUR2 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_tap_shock_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_int_dur2_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_INT_DUR2, (uint8_t *)®, 1); + *val = reg.shock; + + return ret; +} + +/** + * @brief Quiet time is the time after the first detected + * tap in which there must not be any over threshold + * event. + * The default value of these bits is 00b which + * corresponds to 2*ODR_XL time. If the QUIET[1:0] + * bits are set to a different value, + * 1LSB corresponds to 4*ODR_XL time.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of quiet in reg INT_DUR2 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_tap_quiet_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_int_dur2_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_INT_DUR2, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.quiet = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_INT_DUR2, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Quiet time is the time after the first detected + * tap in which there must not be any over threshold + * event. + * The default value of these bits is 00b which + * corresponds to 2*ODR_XL time. + * If the QUIET[1:0] bits are set to a different + * value, 1LSB corresponds to 4*ODR_XL time.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of quiet in reg INT_DUR2 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_tap_quiet_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_int_dur2_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_INT_DUR2, (uint8_t *)®, 1); + *val = reg.quiet; + + return ret; +} + +/** + * @brief When double tap recognition is enabled, + * this register expresses the maximum time + * between two consecutive detected taps to + * determine a double tap event. + * The default value of these bits is 0000b which + * corresponds to 16*ODR_XL time. + * If the DUR[3:0] bits are set to a different value, + * 1LSB corresponds to 32*ODR_XL time.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of dur in reg INT_DUR2 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_tap_dur_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_int_dur2_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_INT_DUR2, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.dur = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_INT_DUR2, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief When double tap recognition is enabled, + * this register expresses the maximum time + * between two consecutive detected taps to + * determine a double tap event. + * The default value of these bits is 0000b which + * corresponds to 16*ODR_XL time. If the DUR[3:0] + * bits are set to a different value, + * 1LSB corresponds to 32*ODR_XL time.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of dur in reg INT_DUR2 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_tap_dur_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_int_dur2_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_INT_DUR2, (uint8_t *)®, 1); + *val = reg.dur; + + return ret; +} + +/** + * @brief Single/double-tap event enable.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of single_double_tap in reg WAKE_UP_THS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_tap_mode_set(stmdev_ctx_t *ctx, + lsm6dso_single_double_tap_t val) +{ + lsm6dso_wake_up_ths_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_WAKE_UP_THS, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.single_double_tap = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_WAKE_UP_THS, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Single/double-tap event enable.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of single_double_tap in reg WAKE_UP_THS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_tap_mode_get(stmdev_ctx_t *ctx, + lsm6dso_single_double_tap_t *val) +{ + lsm6dso_wake_up_ths_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_WAKE_UP_THS, (uint8_t *)®, 1); + + switch (reg.single_double_tap) + { + case LSM6DSO_ONLY_SINGLE: + *val = LSM6DSO_ONLY_SINGLE; + break; + + case LSM6DSO_BOTH_SINGLE_DOUBLE: + *val = LSM6DSO_BOTH_SINGLE_DOUBLE; + break; + + default: + *val = LSM6DSO_ONLY_SINGLE; + break; + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DSO_ Six_position_detection(6D/4D) + * @brief This section groups all the functions concerning six position + * detection (6D). + * @{ + * + */ + +/** + * @brief Threshold for 4D/6D function.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of sixd_ths in reg TAP_THS_6D + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_6d_threshold_set(stmdev_ctx_t *ctx, + lsm6dso_sixd_ths_t val) +{ + lsm6dso_tap_ths_6d_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_TAP_THS_6D, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.sixd_ths = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_TAP_THS_6D, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Threshold for 4D/6D function.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of sixd_ths in reg TAP_THS_6D + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_6d_threshold_get(stmdev_ctx_t *ctx, + lsm6dso_sixd_ths_t *val) +{ + lsm6dso_tap_ths_6d_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_TAP_THS_6D, (uint8_t *)®, 1); + + switch (reg.sixd_ths) + { + case LSM6DSO_DEG_80: + *val = LSM6DSO_DEG_80; + break; + + case LSM6DSO_DEG_70: + *val = LSM6DSO_DEG_70; + break; + + case LSM6DSO_DEG_60: + *val = LSM6DSO_DEG_60; + break; + + case LSM6DSO_DEG_50: + *val = LSM6DSO_DEG_50; + break; + + default: + *val = LSM6DSO_DEG_80; + break; + } + + return ret; +} + +/** + * @brief 4D orientation detection enable.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of d4d_en in reg TAP_THS_6D + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_4d_mode_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_tap_ths_6d_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_TAP_THS_6D, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.d4d_en = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_TAP_THS_6D, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief 4D orientation detection enable.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of d4d_en in reg TAP_THS_6D + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_4d_mode_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_tap_ths_6d_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_TAP_THS_6D, (uint8_t *)®, 1); + *val = reg.d4d_en; + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DSO_free_fall + * @brief This section group all the functions concerning the free + * fall detection. + * @{ + * + */ +/** + * @brief Free fall threshold setting.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of ff_ths in reg FREE_FALL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_ff_threshold_set(stmdev_ctx_t *ctx, + lsm6dso_ff_ths_t val) +{ + lsm6dso_free_fall_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_FREE_FALL, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.ff_ths = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_FREE_FALL, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Free fall threshold setting.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of ff_ths in reg FREE_FALL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_ff_threshold_get(stmdev_ctx_t *ctx, + lsm6dso_ff_ths_t *val) +{ + lsm6dso_free_fall_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_FREE_FALL, (uint8_t *)®, 1); + + switch (reg.ff_ths) + { + case LSM6DSO_FF_TSH_156mg: + *val = LSM6DSO_FF_TSH_156mg; + break; + + case LSM6DSO_FF_TSH_219mg: + *val = LSM6DSO_FF_TSH_219mg; + break; + + case LSM6DSO_FF_TSH_250mg: + *val = LSM6DSO_FF_TSH_250mg; + break; + + case LSM6DSO_FF_TSH_312mg: + *val = LSM6DSO_FF_TSH_312mg; + break; + + case LSM6DSO_FF_TSH_344mg: + *val = LSM6DSO_FF_TSH_344mg; + break; + + case LSM6DSO_FF_TSH_406mg: + *val = LSM6DSO_FF_TSH_406mg; + break; + + case LSM6DSO_FF_TSH_469mg: + *val = LSM6DSO_FF_TSH_469mg; + break; + + case LSM6DSO_FF_TSH_500mg: + *val = LSM6DSO_FF_TSH_500mg; + break; + + default: + *val = LSM6DSO_FF_TSH_156mg; + break; + } + + return ret; +} + +/** + * @brief Free-fall duration event.[set] + * 1LSb = 1 / ODR + * + * @param ctx read / write interface definitions + * @param val change the values of ff_dur in reg FREE_FALL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_ff_dur_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_wake_up_dur_t wake_up_dur; + lsm6dso_free_fall_t free_fall; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_WAKE_UP_DUR, + (uint8_t *)&wake_up_dur, 1); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_FREE_FALL, (uint8_t *)&free_fall, 1); + } + + if (ret == 0) + { + wake_up_dur.ff_dur = ((uint8_t)val & 0x20U) >> 5; + free_fall.ff_dur = (uint8_t)val & 0x1FU; + ret = lsm6dso_write_reg(ctx, LSM6DSO_WAKE_UP_DUR, + (uint8_t *)&wake_up_dur, 1); + } + + if (ret == 0) + { + ret = lsm6dso_write_reg(ctx, LSM6DSO_FREE_FALL, (uint8_t *)&free_fall, 1); + } + + return ret; +} + +/** + * @brief Free-fall duration event.[get] + * 1LSb = 1 / ODR + * + * @param ctx read / write interface definitions + * @param val change the values of ff_dur in reg FREE_FALL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_ff_dur_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_wake_up_dur_t wake_up_dur; + lsm6dso_free_fall_t free_fall; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_WAKE_UP_DUR, + (uint8_t *)&wake_up_dur, 1); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_FREE_FALL, (uint8_t *)&free_fall, 1); + *val = (wake_up_dur.ff_dur << 5) + free_fall.ff_dur; + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DSO_fifo + * @brief This section group all the functions concerning the fifo usage + * @{ + * + */ + +/** + * @brief FIFO watermark level selection.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of wtm in reg FIFO_CTRL1 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fifo_watermark_set(stmdev_ctx_t *ctx, uint16_t val) +{ + lsm6dso_fifo_ctrl1_t fifo_ctrl1; + lsm6dso_fifo_ctrl2_t fifo_ctrl2; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_FIFO_CTRL2, + (uint8_t *)&fifo_ctrl2, 1); + + if (ret == 0) + { + fifo_ctrl1.wtm = 0x00FFU & (uint8_t)val; + fifo_ctrl2.wtm = (uint8_t)((0x0100U & val) >> 8); + ret = lsm6dso_write_reg(ctx, LSM6DSO_FIFO_CTRL1, + (uint8_t *)&fifo_ctrl1, 1); + } + + if (ret == 0) + { + ret = lsm6dso_write_reg(ctx, LSM6DSO_FIFO_CTRL2, + (uint8_t *)&fifo_ctrl2, 1); + } + + return ret; +} + +/** + * @brief FIFO watermark level selection.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of wtm in reg FIFO_CTRL1 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fifo_watermark_get(stmdev_ctx_t *ctx, uint16_t *val) +{ + lsm6dso_fifo_ctrl1_t fifo_ctrl1; + lsm6dso_fifo_ctrl2_t fifo_ctrl2; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_FIFO_CTRL1, + (uint8_t *)&fifo_ctrl1, 1); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_FIFO_CTRL2, + (uint8_t *)&fifo_ctrl2, 1); + *val = ((uint16_t)fifo_ctrl2.wtm << 8) + (uint16_t)fifo_ctrl1.wtm; + } + + return ret; +} + +/** + * @brief FIFO compression feature initialization request [set]. + * + * @param ctx read / write interface definitions + * @param val change the values of FIFO_COMPR_INIT in + * reg EMB_FUNC_INIT_B + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_compression_algo_init_set(stmdev_ctx_t *ctx, + uint8_t val) +{ + lsm6dso_emb_func_init_b_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_EMB_FUNC_INIT_B, (uint8_t *)®, 1); + } + + if (ret == 0) + { + reg.fifo_compr_init = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_EMB_FUNC_INIT_B, (uint8_t *)®, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief FIFO compression feature initialization request [get]. + * + * @param ctx read / write interface definitions + * @param val change the values of FIFO_COMPR_INIT in + * reg EMB_FUNC_INIT_B + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_compression_algo_init_get(stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6dso_emb_func_init_b_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_EMB_FUNC_INIT_B, (uint8_t *)®, 1); + } + + if (ret == 0) + { + *val = reg.fifo_compr_init; + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Enable and configure compression algo.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of uncoptr_rate in + * reg FIFO_CTRL2 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_compression_algo_set(stmdev_ctx_t *ctx, + lsm6dso_uncoptr_rate_t val) +{ + lsm6dso_fifo_ctrl2_t fifo_ctrl2; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_FIFO_CTRL2, + (uint8_t *)&fifo_ctrl2, 1); + + if (ret == 0) + { + fifo_ctrl2.fifo_compr_rt_en = ((uint8_t)val & 0x04U) >> 2; + fifo_ctrl2.uncoptr_rate = (uint8_t)val & 0x03U; + ret = lsm6dso_write_reg(ctx, LSM6DSO_FIFO_CTRL2, + (uint8_t *)&fifo_ctrl2, 1); + } + + return ret; +} + +/** + * @brief Enable and configure compression algo.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of uncoptr_rate in + * reg FIFO_CTRL2 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_compression_algo_get(stmdev_ctx_t *ctx, + lsm6dso_uncoptr_rate_t *val) +{ + lsm6dso_fifo_ctrl2_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_FIFO_CTRL2, (uint8_t *)®, 1); + + switch ((reg.fifo_compr_rt_en << 2) | reg.uncoptr_rate) + { + case LSM6DSO_CMP_DISABLE: + *val = LSM6DSO_CMP_DISABLE; + break; + + case LSM6DSO_CMP_ALWAYS: + *val = LSM6DSO_CMP_ALWAYS; + break; + + case LSM6DSO_CMP_8_TO_1: + *val = LSM6DSO_CMP_8_TO_1; + break; + + case LSM6DSO_CMP_16_TO_1: + *val = LSM6DSO_CMP_16_TO_1; + break; + + case LSM6DSO_CMP_32_TO_1: + *val = LSM6DSO_CMP_32_TO_1; + break; + + default: + *val = LSM6DSO_CMP_DISABLE; + break; + } + + return ret; +} + +/** + * @brief Enables ODR CHANGE virtual sensor to be batched in FIFO.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of odrchg_en in reg FIFO_CTRL2 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fifo_virtual_sens_odr_chg_set(stmdev_ctx_t *ctx, + uint8_t val) +{ + lsm6dso_fifo_ctrl2_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_FIFO_CTRL2, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.odrchg_en = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_FIFO_CTRL2, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Enables ODR CHANGE virtual sensor to be batched in FIFO.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of odrchg_en in reg FIFO_CTRL2 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fifo_virtual_sens_odr_chg_get(stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6dso_fifo_ctrl2_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_FIFO_CTRL2, (uint8_t *)®, 1); + *val = reg.odrchg_en; + + return ret; +} + +/** + * @brief Enables/Disables compression algorithm runtime.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of fifo_compr_rt_en in + * reg FIFO_CTRL2 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_compression_algo_real_time_set(stmdev_ctx_t *ctx, + uint8_t val) +{ + lsm6dso_fifo_ctrl2_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_FIFO_CTRL2, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.fifo_compr_rt_en = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_FIFO_CTRL2, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Enables/Disables compression algorithm runtime. [get] + * + * @param ctx read / write interface definitions + * @param val change the values of fifo_compr_rt_en in reg FIFO_CTRL2 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_compression_algo_real_time_get(stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6dso_fifo_ctrl2_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_FIFO_CTRL2, (uint8_t *)®, 1); + *val = reg.fifo_compr_rt_en; + + return ret; +} + +/** + * @brief Sensing chain FIFO stop values memorization at + * threshold level.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of stop_on_wtm in reg FIFO_CTRL2 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fifo_stop_on_wtm_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_fifo_ctrl2_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_FIFO_CTRL2, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.stop_on_wtm = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_FIFO_CTRL2, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Sensing chain FIFO stop values memorization at + * threshold level.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of stop_on_wtm in reg FIFO_CTRL2 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fifo_stop_on_wtm_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_fifo_ctrl2_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_FIFO_CTRL2, (uint8_t *)®, 1); + *val = reg.stop_on_wtm; + + return ret; +} + +/** + * @brief Selects Batching Data Rate (writing frequency in FIFO) + * for accelerometer data.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of bdr_xl in reg FIFO_CTRL3 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fifo_xl_batch_set(stmdev_ctx_t *ctx, + lsm6dso_bdr_xl_t val) +{ + lsm6dso_fifo_ctrl3_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_FIFO_CTRL3, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.bdr_xl = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_FIFO_CTRL3, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Selects Batching Data Rate (writing frequency in FIFO) + * for accelerometer data.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of bdr_xl in reg FIFO_CTRL3 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fifo_xl_batch_get(stmdev_ctx_t *ctx, + lsm6dso_bdr_xl_t *val) +{ + lsm6dso_fifo_ctrl3_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_FIFO_CTRL3, (uint8_t *)®, 1); + + switch (reg.bdr_xl) + { + case LSM6DSO_XL_NOT_BATCHED: + *val = LSM6DSO_XL_NOT_BATCHED; + break; + + case LSM6DSO_XL_BATCHED_AT_12Hz5: + *val = LSM6DSO_XL_BATCHED_AT_12Hz5; + break; + + case LSM6DSO_XL_BATCHED_AT_26Hz: + *val = LSM6DSO_XL_BATCHED_AT_26Hz; + break; + + case LSM6DSO_XL_BATCHED_AT_52Hz: + *val = LSM6DSO_XL_BATCHED_AT_52Hz; + break; + + case LSM6DSO_XL_BATCHED_AT_104Hz: + *val = LSM6DSO_XL_BATCHED_AT_104Hz; + break; + + case LSM6DSO_XL_BATCHED_AT_208Hz: + *val = LSM6DSO_XL_BATCHED_AT_208Hz; + break; + + case LSM6DSO_XL_BATCHED_AT_417Hz: + *val = LSM6DSO_XL_BATCHED_AT_417Hz; + break; + + case LSM6DSO_XL_BATCHED_AT_833Hz: + *val = LSM6DSO_XL_BATCHED_AT_833Hz; + break; + + case LSM6DSO_XL_BATCHED_AT_1667Hz: + *val = LSM6DSO_XL_BATCHED_AT_1667Hz; + break; + + case LSM6DSO_XL_BATCHED_AT_3333Hz: + *val = LSM6DSO_XL_BATCHED_AT_3333Hz; + break; + + case LSM6DSO_XL_BATCHED_AT_6667Hz: + *val = LSM6DSO_XL_BATCHED_AT_6667Hz; + break; + + case LSM6DSO_XL_BATCHED_AT_6Hz5: + *val = LSM6DSO_XL_BATCHED_AT_6Hz5; + break; + + default: + *val = LSM6DSO_XL_NOT_BATCHED; + break; + } + + return ret; +} + +/** + * @brief Selects Batching Data Rate (writing frequency in FIFO) + * for gyroscope data.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of bdr_gy in reg FIFO_CTRL3 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fifo_gy_batch_set(stmdev_ctx_t *ctx, + lsm6dso_bdr_gy_t val) +{ + lsm6dso_fifo_ctrl3_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_FIFO_CTRL3, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.bdr_gy = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_FIFO_CTRL3, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Selects Batching Data Rate (writing frequency in FIFO) + * for gyroscope data.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of bdr_gy in reg FIFO_CTRL3 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fifo_gy_batch_get(stmdev_ctx_t *ctx, + lsm6dso_bdr_gy_t *val) +{ + lsm6dso_fifo_ctrl3_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_FIFO_CTRL3, (uint8_t *)®, 1); + + switch (reg.bdr_gy) + { + case LSM6DSO_GY_NOT_BATCHED: + *val = LSM6DSO_GY_NOT_BATCHED; + break; + + case LSM6DSO_GY_BATCHED_AT_12Hz5: + *val = LSM6DSO_GY_BATCHED_AT_12Hz5; + break; + + case LSM6DSO_GY_BATCHED_AT_26Hz: + *val = LSM6DSO_GY_BATCHED_AT_26Hz; + break; + + case LSM6DSO_GY_BATCHED_AT_52Hz: + *val = LSM6DSO_GY_BATCHED_AT_52Hz; + break; + + case LSM6DSO_GY_BATCHED_AT_104Hz: + *val = LSM6DSO_GY_BATCHED_AT_104Hz; + break; + + case LSM6DSO_GY_BATCHED_AT_208Hz: + *val = LSM6DSO_GY_BATCHED_AT_208Hz; + break; + + case LSM6DSO_GY_BATCHED_AT_417Hz: + *val = LSM6DSO_GY_BATCHED_AT_417Hz; + break; + + case LSM6DSO_GY_BATCHED_AT_833Hz: + *val = LSM6DSO_GY_BATCHED_AT_833Hz; + break; + + case LSM6DSO_GY_BATCHED_AT_1667Hz: + *val = LSM6DSO_GY_BATCHED_AT_1667Hz; + break; + + case LSM6DSO_GY_BATCHED_AT_3333Hz: + *val = LSM6DSO_GY_BATCHED_AT_3333Hz; + break; + + case LSM6DSO_GY_BATCHED_AT_6667Hz: + *val = LSM6DSO_GY_BATCHED_AT_6667Hz; + break; + + case LSM6DSO_GY_BATCHED_AT_6Hz5: + *val = LSM6DSO_GY_BATCHED_AT_6Hz5; + break; + + default: + *val = LSM6DSO_GY_NOT_BATCHED; + break; + } + + return ret; +} + +/** + * @brief FIFO mode selection.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of fifo_mode in reg FIFO_CTRL4 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fifo_mode_set(stmdev_ctx_t *ctx, + lsm6dso_fifo_mode_t val) +{ + lsm6dso_fifo_ctrl4_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_FIFO_CTRL4, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.fifo_mode = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_FIFO_CTRL4, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief FIFO mode selection.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of fifo_mode in reg FIFO_CTRL4 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fifo_mode_get(stmdev_ctx_t *ctx, + lsm6dso_fifo_mode_t *val) +{ + lsm6dso_fifo_ctrl4_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_FIFO_CTRL4, (uint8_t *)®, 1); + + switch (reg.fifo_mode) + { + case LSM6DSO_BYPASS_MODE: + *val = LSM6DSO_BYPASS_MODE; + break; + + case LSM6DSO_FIFO_MODE: + *val = LSM6DSO_FIFO_MODE; + break; + + case LSM6DSO_STREAM_TO_FIFO_MODE: + *val = LSM6DSO_STREAM_TO_FIFO_MODE; + break; + + case LSM6DSO_BYPASS_TO_STREAM_MODE: + *val = LSM6DSO_BYPASS_TO_STREAM_MODE; + break; + + case LSM6DSO_STREAM_MODE: + *val = LSM6DSO_STREAM_MODE; + break; + + case LSM6DSO_BYPASS_TO_FIFO_MODE: + *val = LSM6DSO_BYPASS_TO_FIFO_MODE; + break; + + default: + *val = LSM6DSO_BYPASS_MODE; + break; + } + + return ret; +} + +/** + * @brief Selects Batching Data Rate (writing frequency in FIFO) + * for temperature data.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of odr_t_batch in reg FIFO_CTRL4 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fifo_temp_batch_set(stmdev_ctx_t *ctx, + lsm6dso_odr_t_batch_t val) +{ + lsm6dso_fifo_ctrl4_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_FIFO_CTRL4, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.odr_t_batch = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_FIFO_CTRL4, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Selects Batching Data Rate (writing frequency in FIFO) + * for temperature data.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of odr_t_batch in reg FIFO_CTRL4 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fifo_temp_batch_get(stmdev_ctx_t *ctx, + lsm6dso_odr_t_batch_t *val) +{ + lsm6dso_fifo_ctrl4_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_FIFO_CTRL4, (uint8_t *)®, 1); + + switch (reg.odr_t_batch) + { + case LSM6DSO_TEMP_NOT_BATCHED: + *val = LSM6DSO_TEMP_NOT_BATCHED; + break; + + case LSM6DSO_TEMP_BATCHED_AT_1Hz6: + *val = LSM6DSO_TEMP_BATCHED_AT_1Hz6; + break; + + case LSM6DSO_TEMP_BATCHED_AT_12Hz5: + *val = LSM6DSO_TEMP_BATCHED_AT_12Hz5; + break; + + case LSM6DSO_TEMP_BATCHED_AT_52Hz: + *val = LSM6DSO_TEMP_BATCHED_AT_52Hz; + break; + + default: + *val = LSM6DSO_TEMP_NOT_BATCHED; + break; + } + + return ret; +} + +/** + * @brief Selects decimation for timestamp batching in FIFO. + * Writing rate will be the maximum rate between XL and + * GYRO BDR divided by decimation decoder.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of odr_ts_batch in reg FIFO_CTRL4 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fifo_timestamp_decimation_set(stmdev_ctx_t *ctx, + lsm6dso_odr_ts_batch_t val) +{ + lsm6dso_fifo_ctrl4_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_FIFO_CTRL4, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.odr_ts_batch = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_FIFO_CTRL4, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Selects decimation for timestamp batching in FIFO. + * Writing rate will be the maximum rate between XL and + * GYRO BDR divided by decimation decoder.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of odr_ts_batch in reg FIFO_CTRL4 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fifo_timestamp_decimation_get(stmdev_ctx_t *ctx, + lsm6dso_odr_ts_batch_t *val) +{ + lsm6dso_fifo_ctrl4_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_FIFO_CTRL4, (uint8_t *)®, 1); + + switch (reg.odr_ts_batch) + { + case LSM6DSO_NO_DECIMATION: + *val = LSM6DSO_NO_DECIMATION; + break; + + case LSM6DSO_DEC_1: + *val = LSM6DSO_DEC_1; + break; + + case LSM6DSO_DEC_8: + *val = LSM6DSO_DEC_8; + break; + + case LSM6DSO_DEC_32: + *val = LSM6DSO_DEC_32; + break; + + default: + *val = LSM6DSO_NO_DECIMATION; + break; + } + + return ret; +} + +/** + * @brief Selects the trigger for the internal counter of batching events + * between XL and gyro.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of trig_counter_bdr + * in reg COUNTER_BDR_REG1 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fifo_cnt_event_batch_set(stmdev_ctx_t *ctx, + lsm6dso_trig_counter_bdr_t val) +{ + lsm6dso_counter_bdr_reg1_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_COUNTER_BDR_REG1, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.trig_counter_bdr = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_COUNTER_BDR_REG1, + (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Selects the trigger for the internal counter of batching events + * between XL and gyro.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of trig_counter_bdr + * in reg COUNTER_BDR_REG1 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fifo_cnt_event_batch_get(stmdev_ctx_t *ctx, + lsm6dso_trig_counter_bdr_t *val) +{ + lsm6dso_counter_bdr_reg1_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_COUNTER_BDR_REG1, (uint8_t *)®, 1); + + switch (reg.trig_counter_bdr) + { + case LSM6DSO_XL_BATCH_EVENT: + *val = LSM6DSO_XL_BATCH_EVENT; + break; + + case LSM6DSO_GYRO_BATCH_EVENT: + *val = LSM6DSO_GYRO_BATCH_EVENT; + break; + + default: + *val = LSM6DSO_XL_BATCH_EVENT; + break; + } + + return ret; +} + +/** + * @brief Resets the internal counter of batching vents for a single sensor. + * This bit is automatically reset to zero if it was set to '1'.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of rst_counter_bdr in + * reg COUNTER_BDR_REG1 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_rst_batch_counter_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_counter_bdr_reg1_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_COUNTER_BDR_REG1, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.rst_counter_bdr = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_COUNTER_BDR_REG1, + (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief Resets the internal counter of batching events for a single sensor. + * This bit is automatically reset to zero if it was set to '1'.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of rst_counter_bdr in + * reg COUNTER_BDR_REG1 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_rst_batch_counter_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_counter_bdr_reg1_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_COUNTER_BDR_REG1, (uint8_t *)®, 1); + *val = reg.rst_counter_bdr; + + return ret; +} + +/** + * @brief Batch data rate counter.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of cnt_bdr_th in + * reg COUNTER_BDR_REG2 and COUNTER_BDR_REG1. + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_batch_counter_threshold_set(stmdev_ctx_t *ctx, + uint16_t val) +{ + lsm6dso_counter_bdr_reg1_t counter_bdr_reg1; + lsm6dso_counter_bdr_reg2_t counter_bdr_reg2; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_COUNTER_BDR_REG1, + (uint8_t *)&counter_bdr_reg1, 1); + + if (ret == 0) + { + counter_bdr_reg2.cnt_bdr_th = 0x00FFU & (uint8_t)val; + counter_bdr_reg1.cnt_bdr_th = (uint8_t)(0x0700U & val) >> 8; + ret = lsm6dso_write_reg(ctx, LSM6DSO_COUNTER_BDR_REG1, + (uint8_t *)&counter_bdr_reg1, 1); + } + + if (ret == 0) + { + ret = lsm6dso_write_reg(ctx, LSM6DSO_COUNTER_BDR_REG2, + (uint8_t *)&counter_bdr_reg2, 1); + } + + return ret; +} + +/** + * @brief Batch data rate counter.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of cnt_bdr_th in + * reg COUNTER_BDR_REG2 and COUNTER_BDR_REG1. + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_batch_counter_threshold_get(stmdev_ctx_t *ctx, + uint16_t *val) +{ + lsm6dso_counter_bdr_reg1_t counter_bdr_reg1; + lsm6dso_counter_bdr_reg2_t counter_bdr_reg2; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_COUNTER_BDR_REG1, + (uint8_t *)&counter_bdr_reg1, 1); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_COUNTER_BDR_REG2, + (uint8_t *)&counter_bdr_reg2, 1); + *val = ((uint16_t)counter_bdr_reg1.cnt_bdr_th << 8) + + (uint16_t)counter_bdr_reg2.cnt_bdr_th; + } + + return ret; +} + +/** + * @brief Number of unread sensor data(TAG + 6 bytes) stored in FIFO.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of diff_fifo in reg FIFO_STATUS1 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fifo_data_level_get(stmdev_ctx_t *ctx, uint16_t *val) +{ + lsm6dso_fifo_status1_t fifo_status1; + lsm6dso_fifo_status2_t fifo_status2; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_FIFO_STATUS1, + (uint8_t *)&fifo_status1, 1); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_FIFO_STATUS2, + (uint8_t *)&fifo_status2, 1); + *val = ((uint16_t)fifo_status2.diff_fifo << 8) + + (uint16_t)fifo_status1.diff_fifo; + } + + return ret; +} + +/** + * @brief FIFO status.[get] + * + * @param ctx read / write interface definitions + * @param val registers FIFO_STATUS2 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fifo_status_get(stmdev_ctx_t *ctx, + lsm6dso_fifo_status2_t *val) +{ + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_FIFO_STATUS2, (uint8_t *) val, 1); + + return ret; +} + +/** + * @brief Smart FIFO full status.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of fifo_full_ia in reg FIFO_STATUS2 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fifo_full_flag_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_fifo_status2_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_FIFO_STATUS2, (uint8_t *)®, 1); + *val = reg.fifo_full_ia; + + return ret; +} + +/** + * @brief FIFO overrun status.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of fifo_over_run_latched in + * reg FIFO_STATUS2 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fifo_ovr_flag_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_fifo_status2_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_FIFO_STATUS2, (uint8_t *)®, 1); + *val = reg.fifo_ovr_ia; + + return ret; +} + +/** + * @brief FIFO watermark status.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of fifo_wtm_ia in reg FIFO_STATUS2 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fifo_wtm_flag_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_fifo_status2_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_FIFO_STATUS2, (uint8_t *)®, 1); + *val = reg.fifo_wtm_ia; + + return ret; +} + +/** + * @brief Identifies the sensor in FIFO_DATA_OUT.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of tag_sensor in reg FIFO_DATA_OUT_TAG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fifo_sensor_tag_get(stmdev_ctx_t *ctx, + lsm6dso_fifo_tag_t *val) +{ + lsm6dso_fifo_data_out_tag_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_FIFO_DATA_OUT_TAG, + (uint8_t *)®, 1); + + switch (reg.tag_sensor) + { + case LSM6DSO_GYRO_NC_TAG: + *val = LSM6DSO_GYRO_NC_TAG; + break; + + case LSM6DSO_XL_NC_TAG: + *val = LSM6DSO_XL_NC_TAG; + break; + + case LSM6DSO_TEMPERATURE_TAG: + *val = LSM6DSO_TEMPERATURE_TAG; + break; + + case LSM6DSO_CFG_CHANGE_TAG: + *val = LSM6DSO_CFG_CHANGE_TAG; + break; + + case LSM6DSO_XL_NC_T_2_TAG: + *val = LSM6DSO_XL_NC_T_2_TAG; + break; + + case LSM6DSO_XL_NC_T_1_TAG: + *val = LSM6DSO_XL_NC_T_1_TAG; + break; + + case LSM6DSO_XL_2XC_TAG: + *val = LSM6DSO_XL_2XC_TAG; + break; + + case LSM6DSO_XL_3XC_TAG: + *val = LSM6DSO_XL_3XC_TAG; + break; + + case LSM6DSO_GYRO_NC_T_2_TAG: + *val = LSM6DSO_GYRO_NC_T_2_TAG; + break; + + case LSM6DSO_GYRO_NC_T_1_TAG: + *val = LSM6DSO_GYRO_NC_T_1_TAG; + break; + + case LSM6DSO_GYRO_2XC_TAG: + *val = LSM6DSO_GYRO_2XC_TAG; + break; + + case LSM6DSO_GYRO_3XC_TAG: + *val = LSM6DSO_GYRO_3XC_TAG; + break; + + case LSM6DSO_SENSORHUB_SLAVE0_TAG: + *val = LSM6DSO_SENSORHUB_SLAVE0_TAG; + break; + + case LSM6DSO_SENSORHUB_SLAVE1_TAG: + *val = LSM6DSO_SENSORHUB_SLAVE1_TAG; + break; + + case LSM6DSO_SENSORHUB_SLAVE2_TAG: + *val = LSM6DSO_SENSORHUB_SLAVE2_TAG; + break; + + case LSM6DSO_SENSORHUB_SLAVE3_TAG: + *val = LSM6DSO_SENSORHUB_SLAVE3_TAG; + break; + + case LSM6DSO_STEP_CPUNTER_TAG: + *val = LSM6DSO_STEP_CPUNTER_TAG; + break; + + case LSM6DSO_GAME_ROTATION_TAG: + *val = LSM6DSO_GAME_ROTATION_TAG; + break; + + case LSM6DSO_GEOMAG_ROTATION_TAG: + *val = LSM6DSO_GEOMAG_ROTATION_TAG; + break; + + case LSM6DSO_ROTATION_TAG: + *val = LSM6DSO_ROTATION_TAG; + break; + + case LSM6DSO_SENSORHUB_NACK_TAG: + *val = LSM6DSO_SENSORHUB_NACK_TAG; + break; + + default: + *val = LSM6DSO_GYRO_NC_TAG; + break; + } + + return ret; +} + +/** + * @brief : Enable FIFO batching of pedometer embedded + * function values.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of gbias_fifo_en in + * reg LSM6DSO_EMB_FUNC_FIFO_CFG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fifo_pedo_batch_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_emb_func_fifo_cfg_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_EMB_FUNC_FIFO_CFG, + (uint8_t *)®, 1); + } + + if (ret == 0) + { + reg.pedo_fifo_en = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_EMB_FUNC_FIFO_CFG, + (uint8_t *)®, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Enable FIFO batching of pedometer embedded function values.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of pedo_fifo_en in + * reg LSM6DSO_EMB_FUNC_FIFO_CFG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fifo_pedo_batch_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_emb_func_fifo_cfg_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_EMB_FUNC_FIFO_CFG, + (uint8_t *)®, 1); + } + + if (ret == 0) + { + *val = reg.pedo_fifo_en; + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Enable FIFO batching data of first slave.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of batch_ext_sens_0_en in + * reg SLV0_CONFIG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sh_batch_slave_0_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_slv0_config_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_SLV0_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + reg.batch_ext_sens_0_en = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_SLV0_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Enable FIFO batching data of first slave.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of batch_ext_sens_0_en in + * reg SLV0_CONFIG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sh_batch_slave_0_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_slv0_config_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_SLV0_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + *val = reg.batch_ext_sens_0_en; + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Enable FIFO batching data of second slave.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of batch_ext_sens_1_en in + * reg SLV1_CONFIG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sh_batch_slave_1_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_slv1_config_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_SLV1_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + reg.batch_ext_sens_1_en = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_SLV1_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Enable FIFO batching data of second slave.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of batch_ext_sens_1_en in + * reg SLV1_CONFIG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sh_batch_slave_1_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_slv1_config_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_SLV1_CONFIG, (uint8_t *)®, 1); + *val = reg.batch_ext_sens_1_en; + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Enable FIFO batching data of third slave.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of batch_ext_sens_2_en in + * reg SLV2_CONFIG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sh_batch_slave_2_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_slv2_config_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_SLV2_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + reg.batch_ext_sens_2_en = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_SLV2_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Enable FIFO batching data of third slave.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of batch_ext_sens_2_en in + * reg SLV2_CONFIG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sh_batch_slave_2_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_slv2_config_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_SLV2_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + *val = reg.batch_ext_sens_2_en; + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Enable FIFO batching data of fourth slave.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of batch_ext_sens_3_en + * in reg SLV3_CONFIG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sh_batch_slave_3_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_slv3_config_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_SLV3_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + reg.batch_ext_sens_3_en = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_SLV3_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Enable FIFO batching data of fourth slave.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of batch_ext_sens_3_en in + * reg SLV3_CONFIG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sh_batch_slave_3_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_slv3_config_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_SLV3_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + *val = reg.batch_ext_sens_3_en; + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DSO_DEN_functionality + * @brief This section groups all the functions concerning + * DEN functionality. + * @{ + * + */ + +/** + * @brief DEN functionality marking mode.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of den_mode in reg CTRL6_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_den_mode_set(stmdev_ctx_t *ctx, + lsm6dso_den_mode_t val) +{ + lsm6dso_ctrl6_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL6_C, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.den_mode = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL6_C, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief DEN functionality marking mode.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of den_mode in reg CTRL6_C + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_den_mode_get(stmdev_ctx_t *ctx, + lsm6dso_den_mode_t *val) +{ + lsm6dso_ctrl6_c_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL6_C, (uint8_t *)®, 1); + + switch (reg.den_mode) + { + case LSM6DSO_DEN_DISABLE: + *val = LSM6DSO_DEN_DISABLE; + break; + + case LSM6DSO_LEVEL_FIFO: + *val = LSM6DSO_LEVEL_FIFO; + break; + + case LSM6DSO_LEVEL_LETCHED: + *val = LSM6DSO_LEVEL_LETCHED; + break; + + case LSM6DSO_LEVEL_TRIGGER: + *val = LSM6DSO_LEVEL_TRIGGER; + break; + + case LSM6DSO_EDGE_TRIGGER: + *val = LSM6DSO_EDGE_TRIGGER; + break; + + default: + *val = LSM6DSO_DEN_DISABLE; + break; + } + + return ret; +} + +/** + * @brief DEN active level configuration.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of den_lh in reg CTRL9_XL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_den_polarity_set(stmdev_ctx_t *ctx, + lsm6dso_den_lh_t val) +{ + lsm6dso_ctrl9_xl_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL9_XL, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.den_lh = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL9_XL, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief DEN active level configuration.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of den_lh in reg CTRL9_XL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_den_polarity_get(stmdev_ctx_t *ctx, + lsm6dso_den_lh_t *val) +{ + lsm6dso_ctrl9_xl_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL9_XL, (uint8_t *)®, 1); + + switch (reg.den_lh) + { + case LSM6DSO_DEN_ACT_LOW: + *val = LSM6DSO_DEN_ACT_LOW; + break; + + case LSM6DSO_DEN_ACT_HIGH: + *val = LSM6DSO_DEN_ACT_HIGH; + break; + + default: + *val = LSM6DSO_DEN_ACT_LOW; + break; + } + + return ret; +} + +/** + * @brief DEN enable.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of den_xl_g in reg CTRL9_XL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_den_enable_set(stmdev_ctx_t *ctx, + lsm6dso_den_xl_g_t val) +{ + lsm6dso_ctrl9_xl_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL9_XL, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.den_xl_g = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL9_XL, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief DEN enable.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of den_xl_g in reg CTRL9_XL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_den_enable_get(stmdev_ctx_t *ctx, + lsm6dso_den_xl_g_t *val) +{ + lsm6dso_ctrl9_xl_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL9_XL, (uint8_t *)®, 1); + + switch (reg.den_xl_g) + { + case LSM6DSO_STAMP_IN_GY_DATA: + *val = LSM6DSO_STAMP_IN_GY_DATA; + break; + + case LSM6DSO_STAMP_IN_XL_DATA: + *val = LSM6DSO_STAMP_IN_XL_DATA; + break; + + case LSM6DSO_STAMP_IN_GY_XL_DATA: + *val = LSM6DSO_STAMP_IN_GY_XL_DATA; + break; + + default: + *val = LSM6DSO_STAMP_IN_GY_DATA; + break; + } + + return ret; +} + +/** + * @brief DEN value stored in LSB of X-axis.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of den_z in reg CTRL9_XL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_den_mark_axis_x_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_ctrl9_xl_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL9_XL, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.den_z = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL9_XL, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief DEN value stored in LSB of X-axis.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of den_z in reg CTRL9_XL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_den_mark_axis_x_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_ctrl9_xl_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL9_XL, (uint8_t *)®, 1); + *val = reg.den_z; + + return ret; +} + +/** + * @brief DEN value stored in LSB of Y-axis.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of den_y in reg CTRL9_XL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_den_mark_axis_y_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_ctrl9_xl_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL9_XL, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.den_y = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL9_XL, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief DEN value stored in LSB of Y-axis.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of den_y in reg CTRL9_XL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_den_mark_axis_y_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_ctrl9_xl_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL9_XL, (uint8_t *)®, 1); + *val = reg.den_y; + + return ret; +} + +/** + * @brief DEN value stored in LSB of Z-axis.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of den_x in reg CTRL9_XL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_den_mark_axis_z_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_ctrl9_xl_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL9_XL, (uint8_t *)®, 1); + + if (ret == 0) + { + reg.den_x = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL9_XL, (uint8_t *)®, 1); + } + + return ret; +} + +/** + * @brief DEN value stored in LSB of Z-axis.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of den_x in reg CTRL9_XL + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_den_mark_axis_z_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_ctrl9_xl_t reg; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL9_XL, (uint8_t *)®, 1); + *val = reg.den_x; + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DSO_Pedometer + * @brief This section groups all the functions that manage pedometer. + * @{ + * + */ + +/** + * @brief Enable pedometer algorithm.[set] + * + * @param ctx read / write interface definitions + * @param val turn on and configure pedometer + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_pedo_sens_set(stmdev_ctx_t *ctx, + lsm6dso_pedo_md_t val) +{ + lsm6dso_pedo_cmd_reg_t pedo_cmd_reg; + int32_t ret; + + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_PEDO_CMD_REG, + (uint8_t *)&pedo_cmd_reg); + + if (ret == 0) + { + pedo_cmd_reg.fp_rejection_en = ((uint8_t)val & 0x10U) >> 4; + pedo_cmd_reg.ad_det_en = ((uint8_t)val & 0x20U) >> 5; + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_PEDO_CMD_REG, + (uint8_t *)&pedo_cmd_reg); + } + + return ret; +} + +/** + * @brief Enable pedometer algorithm.[get] + * + * @param ctx read / write interface definitions + * @param val turn on and configure pedometer + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_pedo_sens_get(stmdev_ctx_t *ctx, + lsm6dso_pedo_md_t *val) +{ + lsm6dso_pedo_cmd_reg_t pedo_cmd_reg; + int32_t ret; + + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_PEDO_CMD_REG, + (uint8_t *)&pedo_cmd_reg); + + switch ((pedo_cmd_reg.ad_det_en << 5) | (pedo_cmd_reg.fp_rejection_en + << 4)) + { + case LSM6DSO_PEDO_BASE_MODE: + *val = LSM6DSO_PEDO_BASE_MODE; + break; + + case LSM6DSO_FALSE_STEP_REJ: + *val = LSM6DSO_FALSE_STEP_REJ; + break; + + case LSM6DSO_FALSE_STEP_REJ_ADV_MODE: + *val = LSM6DSO_FALSE_STEP_REJ_ADV_MODE; + break; + + default: + *val = LSM6DSO_PEDO_BASE_MODE; + break; + } + + return ret; +} + +/** + * @brief Interrupt status bit for step detection.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of is_step_det in reg EMB_FUNC_STATUS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_pedo_step_detect_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_emb_func_status_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_EMB_FUNC_STATUS, (uint8_t *)®, 1); + } + + if (ret == 0) + { + *val = reg.is_step_det; + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Pedometer debounce configuration register (r/w).[set] + * + * @param ctx read / write interface definitions + * @param buff buffer that contains data to write + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_pedo_debounce_steps_set(stmdev_ctx_t *ctx, + uint8_t *buff) +{ + int32_t ret; + + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_PEDO_DEB_STEPS_CONF, + buff); + + return ret; +} + +/** + * @brief Pedometer debounce configuration register (r/w).[get] + * + * @param ctx read / write interface definitions + * @param buff buffer that stores data read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_pedo_debounce_steps_get(stmdev_ctx_t *ctx, + uint8_t *buff) +{ + int32_t ret; + + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_PEDO_DEB_STEPS_CONF, buff); + + return ret; +} + +/** + * @brief Time period register for step detection on delta time (r/w).[set] + * + * @param ctx read / write interface definitions + * @param buff buffer that contains data to write + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_pedo_steps_period_set(stmdev_ctx_t *ctx, uint16_t val) +{ + uint8_t buff[2]; + int32_t ret; + + buff[1] = (uint8_t)(val / 256U); + buff[0] = (uint8_t)(val - (buff[1] * 256U)); + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_PEDO_SC_DELTAT_L, + &buff[0]); + + if (ret == 0) + { + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_PEDO_SC_DELTAT_H, + &buff[1]); + } + + return ret; +} + +/** + * @brief Time period register for step detection on delta time (r/w).[get] + * + * @param ctx read / write interface definitions + * @param buff buffer that stores data read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_pedo_steps_period_get(stmdev_ctx_t *ctx, + uint16_t *val) +{ + uint8_t buff[2]; + int32_t ret; + + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_PEDO_SC_DELTAT_L, + &buff[0]); + + if (ret == 0) + { + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_PEDO_SC_DELTAT_H, + &buff[1]); + *val = buff[1]; + *val = (*val * 256U) + buff[0]; + } + + return ret; +} + +/** + * @brief Set when user wants to generate interrupt on count overflow + * event/every step.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of carry_count_en in reg PEDO_CMD_REG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_pedo_int_mode_set(stmdev_ctx_t *ctx, + lsm6dso_carry_count_en_t val) +{ + lsm6dso_pedo_cmd_reg_t reg; + int32_t ret; + + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_PEDO_CMD_REG, + (uint8_t *)®); + + if (ret == 0) + { + reg.carry_count_en = (uint8_t)val; + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_PEDO_CMD_REG, + (uint8_t *)®); + } + + return ret; +} + +/** + * @brief Set when user wants to generate interrupt on count overflow + * event/every step.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of carry_count_en in reg PEDO_CMD_REG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_pedo_int_mode_get(stmdev_ctx_t *ctx, + lsm6dso_carry_count_en_t *val) +{ + lsm6dso_pedo_cmd_reg_t reg; + int32_t ret; + + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_PEDO_CMD_REG, + (uint8_t *)®); + + switch (reg.carry_count_en) + { + case LSM6DSO_EVERY_STEP: + *val = LSM6DSO_EVERY_STEP; + break; + + case LSM6DSO_COUNT_OVERFLOW: + *val = LSM6DSO_COUNT_OVERFLOW; + break; + + default: + *val = LSM6DSO_EVERY_STEP; + break; + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DSO_significant_motion + * @brief This section groups all the functions that manage the + * significant motion detection. + * @{ + * + */ + +/** + * @brief Interrupt status bit for significant motion detection.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of is_sigmot in reg EMB_FUNC_STATUS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_motion_flag_data_ready_get(stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6dso_emb_func_status_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_EMB_FUNC_STATUS, (uint8_t *)®, 1); + } + + if (ret == 0) + { + *val = reg.is_sigmot; + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DSO_tilt_detection + * @brief This section groups all the functions that manage the tilt + * event detection. + * @{ + * + */ + +/** + * @brief Interrupt status bit for tilt detection.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of is_tilt in reg EMB_FUNC_STATUS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_tilt_flag_data_ready_get(stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6dso_emb_func_status_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_EMB_FUNC_STATUS, (uint8_t *)®, 1); + } + + if (ret == 0) + { + *val = reg.is_tilt; + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DSO_ magnetometer_sensor + * @brief This section groups all the functions that manage additional + * magnetometer sensor. + * @{ + * + */ + +/** + * @brief External magnetometer sensitivity value register.[set] + * + * @param ctx read / write interface definitions + * @param buff buffer that contains data to write + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_mag_sensitivity_set(stmdev_ctx_t *ctx, uint16_t val) +{ + uint8_t buff[2]; + int32_t ret; + + buff[1] = (uint8_t)(val / 256U); + buff[0] = (uint8_t)(val - (buff[1] * 256U)); + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_MAG_SENSITIVITY_L, + &buff[0]); + + if (ret == 0) + { + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_MAG_SENSITIVITY_H, + &buff[1]); + } + + return ret; +} + +/** + * @brief External magnetometer sensitivity value register.[get] + * + * @param ctx read / write interface definitions + * @param buff buffer that stores data read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_mag_sensitivity_get(stmdev_ctx_t *ctx, uint16_t *val) +{ + uint8_t buff[2]; + int32_t ret; + + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_MAG_SENSITIVITY_L, + &buff[0]); + + if (ret == 0) + { + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_MAG_SENSITIVITY_H, + &buff[1]); + *val = buff[1]; + *val = (*val * 256U) + buff[0]; + } + + return ret; +} + +/** + * @brief Offset for hard-iron compensation register (r/w).[set] + * + * @param ctx read / write interface definitions + * @param buff buffer that contains data to write + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_mag_offset_set(stmdev_ctx_t *ctx, int16_t *val) +{ + uint8_t buff[6]; + int32_t ret; + + buff[1] = (uint8_t)((uint16_t)val[0] / 256U); + buff[0] = (uint8_t)((uint16_t)val[0] - (buff[1] * 256U)); + buff[3] = (uint8_t)((uint16_t)val[1] / 256U); + buff[2] = (uint8_t)((uint16_t)val[1] - (buff[3] * 256U)); + buff[5] = (uint8_t)((uint16_t)val[2] / 256U); + buff[4] = (uint8_t)((uint16_t)val[2] - (buff[5] * 256U)); + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_MAG_OFFX_L, &buff[0]); + + if (ret == 0) + { + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_MAG_OFFX_H, &buff[1]); + } + + if (ret == 0) + { + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_MAG_OFFY_L, &buff[2]); + } + + if (ret == 0) + { + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_MAG_OFFY_H, &buff[3]); + } + + if (ret == 0) + { + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_MAG_OFFZ_L, &buff[4]); + } + + if (ret == 0) + { + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_MAG_OFFZ_H, &buff[5]); + } + + return ret; +} + +/** + * @brief Offset for hard-iron compensation register (r/w).[get] + * + * @param ctx read / write interface definitions + * @param buff buffer that stores data read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_mag_offset_get(stmdev_ctx_t *ctx, int16_t *val) +{ + uint8_t buff[6]; + int32_t ret; + + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_MAG_OFFX_L, &buff[0]); + + if (ret == 0) + { + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_MAG_OFFX_H, &buff[1]); + } + + if (ret == 0) + { + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_MAG_OFFY_L, &buff[2]); + } + + if (ret == 0) + { + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_MAG_OFFY_H, &buff[3]); + } + + if (ret == 0) + { + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_MAG_OFFZ_L, &buff[4]); + } + + if (ret == 0) + { + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_MAG_OFFZ_H, &buff[5]); + val[0] = (int16_t)buff[1]; + val[0] = (val[0] * 256) + (int16_t)buff[0]; + val[1] = (int16_t)buff[3]; + val[1] = (val[1] * 256) + (int16_t)buff[2]; + val[2] = (int16_t)buff[5]; + val[2] = (val[2] * 256) + (int16_t)buff[4]; + } + + return ret; +} + +/** + * @brief Soft-iron (3x3 symmetric) matrix correction + * register (r/w). The value is expressed as + * half-precision floating-point format: + * SEEEEEFFFFFFFFFF + * S: 1 sign bit; + * E: 5 exponent bits; + * F: 10 fraction bits).[set] + * + * @param ctx read / write interface definitions + * @param buff buffer that contains data to write + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_mag_soft_iron_set(stmdev_ctx_t *ctx, int16_t *val) +{ + uint8_t buff[12]; + int32_t ret; + + uint8_t index; + buff[1] = (uint8_t)((uint16_t)val[0] / 256U); + buff[0] = (uint8_t)((uint16_t)val[0] - (buff[1] * 256U)); + buff[3] = (uint8_t)((uint16_t)val[1] / 256U); + buff[2] = (uint8_t)((uint16_t)val[1] - (buff[3] * 256U)); + buff[5] = (uint8_t)((uint16_t)val[2] / 256U); + buff[4] = (uint8_t)((uint16_t)val[2] - (buff[5] * 256U)); + buff[7] = (uint8_t)((uint16_t)val[3] / 256U); + buff[6] = (uint8_t)((uint16_t)val[3] - (buff[7] * 256U)); + buff[9] = (uint8_t)((uint16_t)val[4] / 256U); + buff[8] = (uint8_t)((uint16_t)val[4] - (buff[9] * 256U)); + buff[11] = (uint8_t)((uint16_t)val[5] / 256U); + buff[10] = (uint8_t)((uint16_t)val[5] - (buff[11] * 256U)); + index = 0x00U; + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_MAG_SI_XX_L, + &buff[index]); + + if (ret == 0) + { + index++; + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_MAG_SI_XX_H, + &buff[index]); + } + + if (ret == 0) + { + index++; + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_MAG_SI_XY_L, + &buff[index]); + } + + if (ret == 0) + { + index++; + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_MAG_SI_XY_H, + &buff[index]); + } + + if (ret == 0) + { + index++; + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_MAG_SI_XZ_L, + &buff[index]); + } + + if (ret == 0) + { + index++; + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_MAG_SI_XZ_H, + &buff[index]); + } + + if (ret == 0) + { + index++; + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_MAG_SI_YY_L, + &buff[index]); + } + + if (ret == 0) + { + index++; + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_MAG_SI_YY_H, + &buff[index]); + } + + if (ret == 0) + { + index++; + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_MAG_SI_YZ_L, + &buff[index]); + } + + if (ret == 0) + { + index++; + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_MAG_SI_YZ_H, + &buff[index]); + } + + if (ret == 0) + { + index++; + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_MAG_SI_ZZ_L, + &buff[index]); + } + + if (ret == 0) + { + index++; + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_MAG_SI_ZZ_H, + &buff[index]); + } + + return ret; +} + +/** + * @brief Soft-iron (3x3 symmetric) matrix + * correction register (r/w). + * The value is expressed as half-precision + * floating-point format: + * SEEEEEFFFFFFFFFF + * S: 1 sign bit; + * E: 5 exponent bits; + * F: 10 fraction bits.[get] + * + * @param ctx read / write interface definitions + * @param buff buffer that stores data read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_mag_soft_iron_get(stmdev_ctx_t *ctx, int16_t *val) +{ + uint8_t buff[12]; + int32_t ret; + + uint8_t index; + index = 0x00U; + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_MAG_SI_XX_L, &buff[index]); + + if (ret == 0) + { + index++; + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_MAG_SI_XX_H, &buff[index]); + } + + if (ret == 0) + { + index++; + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_MAG_SI_XY_L, &buff[index]); + } + + if (ret == 0) + { + index++; + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_MAG_SI_XY_H, &buff[index]); + } + + if (ret == 0) + { + index++; + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_MAG_SI_XZ_L, &buff[index]); + } + + if (ret == 0) + { + index++; + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_MAG_SI_XZ_H, &buff[index]); + } + + if (ret == 0) + { + index++; + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_MAG_SI_YY_L, &buff[index]); + } + + if (ret == 0) + { + index++; + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_MAG_SI_YY_H, &buff[index]); + } + + if (ret == 0) + { + index++; + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_MAG_SI_YZ_L, &buff[index]); + } + + if (ret == 0) + { + index++; + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_MAG_SI_YZ_H, &buff[index]); + } + + if (ret == 0) + { + index++; + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_MAG_SI_ZZ_L, &buff[index]); + } + + if (ret == 0) + { + index++; + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_MAG_SI_ZZ_H, &buff[index]); + } + + val[0] = (int16_t)buff[1]; + val[0] = (val[0] * 256) + (int16_t)buff[0]; + val[1] = (int16_t)buff[3]; + val[1] = (val[1] * 256) + (int16_t)buff[2]; + val[2] = (int16_t)buff[5]; + val[2] = (val[2] * 256) + (int16_t)buff[4]; + val[3] = (int16_t)buff[7]; + val[3] = (val[3] * 256) + (int16_t)buff[6]; + val[4] = (int16_t)buff[9]; + val[4] = (val[4] * 256) + (int16_t)buff[8]; + val[5] = (int16_t)buff[11]; + val[5] = (val[5] * 256) + (int16_t)buff[10]; + + return ret; +} + +/** + * @brief Magnetometer Z-axis coordinates + * rotation (to be aligned to + * accelerometer/gyroscope axes + * orientation).[set] + * + * @param ctx read / write interface definitions + * @param val change the values of mag_z_axis in reg MAG_CFG_A + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_mag_z_orient_set(stmdev_ctx_t *ctx, + lsm6dso_mag_z_axis_t val) +{ + lsm6dso_mag_cfg_a_t reg; + int32_t ret; + + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_MAG_CFG_A, + (uint8_t *)®); + + if (ret == 0) + { + reg.mag_z_axis = (uint8_t) val; + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_MAG_CFG_A, + (uint8_t *)®); + } + + return ret; +} + +/** + * @brief Magnetometer Z-axis coordinates + * rotation (to be aligned to + * accelerometer/gyroscope axes + * orientation).[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of mag_z_axis in reg MAG_CFG_A + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_mag_z_orient_get(stmdev_ctx_t *ctx, + lsm6dso_mag_z_axis_t *val) +{ + lsm6dso_mag_cfg_a_t reg; + int32_t ret; + + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_MAG_CFG_A, + (uint8_t *)®); + + switch (reg.mag_z_axis) + { + case LSM6DSO_Z_EQ_Y: + *val = LSM6DSO_Z_EQ_Y; + break; + + case LSM6DSO_Z_EQ_MIN_Y: + *val = LSM6DSO_Z_EQ_MIN_Y; + break; + + case LSM6DSO_Z_EQ_X: + *val = LSM6DSO_Z_EQ_X; + break; + + case LSM6DSO_Z_EQ_MIN_X: + *val = LSM6DSO_Z_EQ_MIN_X; + break; + + case LSM6DSO_Z_EQ_MIN_Z: + *val = LSM6DSO_Z_EQ_MIN_Z; + break; + + case LSM6DSO_Z_EQ_Z: + *val = LSM6DSO_Z_EQ_Z; + break; + + default: + *val = LSM6DSO_Z_EQ_Y; + break; + } + + return ret; +} + +/** + * @brief Magnetometer Y-axis coordinates + * rotation (to be aligned to + * accelerometer/gyroscope axes + * orientation).[set] + * + * @param ctx read / write interface definitions + * @param val change the values of mag_y_axis in reg MAG_CFG_A + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_mag_y_orient_set(stmdev_ctx_t *ctx, + lsm6dso_mag_y_axis_t val) +{ + lsm6dso_mag_cfg_a_t reg; + int32_t ret; + + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_MAG_CFG_A, + (uint8_t *)®); + + if (ret == 0) + { + reg.mag_y_axis = (uint8_t)val; + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_MAG_CFG_A, + (uint8_t *) ®); + } + + return ret; +} + +/** + * @brief Magnetometer Y-axis coordinates + * rotation (to be aligned to + * accelerometer/gyroscope axes + * orientation).[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of mag_y_axis in reg MAG_CFG_A + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_mag_y_orient_get(stmdev_ctx_t *ctx, + lsm6dso_mag_y_axis_t *val) +{ + lsm6dso_mag_cfg_a_t reg; + int32_t ret; + + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_MAG_CFG_A, + (uint8_t *)®); + + switch (reg.mag_y_axis) + { + case LSM6DSO_Y_EQ_Y: + *val = LSM6DSO_Y_EQ_Y; + break; + + case LSM6DSO_Y_EQ_MIN_Y: + *val = LSM6DSO_Y_EQ_MIN_Y; + break; + + case LSM6DSO_Y_EQ_X: + *val = LSM6DSO_Y_EQ_X; + break; + + case LSM6DSO_Y_EQ_MIN_X: + *val = LSM6DSO_Y_EQ_MIN_X; + break; + + case LSM6DSO_Y_EQ_MIN_Z: + *val = LSM6DSO_Y_EQ_MIN_Z; + break; + + case LSM6DSO_Y_EQ_Z: + *val = LSM6DSO_Y_EQ_Z; + break; + + default: + *val = LSM6DSO_Y_EQ_Y; + break; + } + + return ret; +} + +/** + * @brief Magnetometer X-axis coordinates + * rotation (to be aligned to + * accelerometer/gyroscope axes + * orientation).[set] + * + * @param ctx read / write interface definitions + * @param val change the values of mag_x_axis in reg MAG_CFG_B + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_mag_x_orient_set(stmdev_ctx_t *ctx, + lsm6dso_mag_x_axis_t val) +{ + lsm6dso_mag_cfg_b_t reg; + int32_t ret; + + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_MAG_CFG_B, + (uint8_t *)®); + + if (ret == 0) + { + reg.mag_x_axis = (uint8_t)val; + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_MAG_CFG_B, + (uint8_t *)®); + } + + return ret; +} + +/** + * @brief Magnetometer X-axis coordinates + * rotation (to be aligned to + * accelerometer/gyroscope axes + * orientation).[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of mag_x_axis in reg MAG_CFG_B + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_mag_x_orient_get(stmdev_ctx_t *ctx, + lsm6dso_mag_x_axis_t *val) +{ + lsm6dso_mag_cfg_b_t reg; + int32_t ret; + + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_MAG_CFG_B, + (uint8_t *)®); + + switch (reg.mag_x_axis) + { + case LSM6DSO_X_EQ_Y: + *val = LSM6DSO_X_EQ_Y; + break; + + case LSM6DSO_X_EQ_MIN_Y: + *val = LSM6DSO_X_EQ_MIN_Y; + break; + + case LSM6DSO_X_EQ_X: + *val = LSM6DSO_X_EQ_X; + break; + + case LSM6DSO_X_EQ_MIN_X: + *val = LSM6DSO_X_EQ_MIN_X; + break; + + case LSM6DSO_X_EQ_MIN_Z: + *val = LSM6DSO_X_EQ_MIN_Z; + break; + + case LSM6DSO_X_EQ_Z: + *val = LSM6DSO_X_EQ_Z; + break; + + default: + *val = LSM6DSO_X_EQ_Y; + break; + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DSO_finite_state_machine + * @brief This section groups all the functions that manage the + * state_machine. + * @{ + * + */ + +/** + * @brief Interrupt status bit for FSM long counter + * timeout interrupt event.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of is_fsm_lc in reg EMB_FUNC_STATUS + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_long_cnt_flag_data_ready_get(stmdev_ctx_t *ctx, + uint8_t *val) +{ + lsm6dso_emb_func_status_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_EMB_FUNC_STATUS, (uint8_t *)®, 1); + } + + if (ret == 0) + { + *val = reg.is_fsm_lc; + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Final State Machine enable.[set] + * + * @param ctx read / write interface definitions + * @param val union of registers from FSM_ENABLE_A to FSM_ENABLE_B + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fsm_enable_set(stmdev_ctx_t *ctx, + lsm6dso_emb_fsm_enable_t *val) +{ + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + + if (ret == 0) + { + ret = lsm6dso_write_reg(ctx, LSM6DSO_FSM_ENABLE_A, + (uint8_t *)&val->fsm_enable_a, 1); + } + + if (ret == 0) + { + ret = lsm6dso_write_reg(ctx, LSM6DSO_FSM_ENABLE_B, + (uint8_t *)&val->fsm_enable_b, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Final State Machine enable.[get] + * + * @param ctx read / write interface definitions + * @param val union of registers from FSM_ENABLE_A to FSM_ENABLE_B + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fsm_enable_get(stmdev_ctx_t *ctx, + lsm6dso_emb_fsm_enable_t *val) +{ + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_FSM_ENABLE_A, (uint8_t *) val, 2); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief FSM long counter status register. Long counter value is an + * unsigned integer value (16-bit format).[set] + * + * @param ctx read / write interface definitions + * @param buff buffer that contains data to write + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_long_cnt_set(stmdev_ctx_t *ctx, uint16_t val) +{ + uint8_t buff[2]; + int32_t ret; + + buff[1] = (uint8_t)(val / 256U); + buff[0] = (uint8_t)(val - (buff[1] * 256U)); + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + + if (ret == 0) + { + ret = lsm6dso_write_reg(ctx, LSM6DSO_FSM_LONG_COUNTER_L, buff, 2); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief FSM long counter status register. Long counter value is an + * unsigned integer value (16-bit format).[get] + * + * @param ctx read / write interface definitions + * @param buff buffer that stores data read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_long_cnt_get(stmdev_ctx_t *ctx, uint16_t *val) +{ + uint8_t buff[2]; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_FSM_LONG_COUNTER_L, buff, 2); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + *val = buff[1]; + *val = (*val * 256U) + buff[0]; + } + + return ret; +} + +/** + * @brief Clear FSM long counter value.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of fsm_lc_clr in + * reg FSM_LONG_COUNTER_CLEAR + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_long_clr_set(stmdev_ctx_t *ctx, + lsm6dso_fsm_lc_clr_t val) +{ + lsm6dso_fsm_long_counter_clear_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_FSM_LONG_COUNTER_CLEAR, + (uint8_t *)®, 1); + } + + if (ret == 0) + { + reg. fsm_lc_clr = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_FSM_LONG_COUNTER_CLEAR, + (uint8_t *)®, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Clear FSM long counter value.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of fsm_lc_clr in + * reg FSM_LONG_COUNTER_CLEAR + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_long_clr_get(stmdev_ctx_t *ctx, + lsm6dso_fsm_lc_clr_t *val) +{ + lsm6dso_fsm_long_counter_clear_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_FSM_LONG_COUNTER_CLEAR, + (uint8_t *)®, 1); + } + + if (ret == 0) + { + switch (reg.fsm_lc_clr) + { + case LSM6DSO_LC_NORMAL: + *val = LSM6DSO_LC_NORMAL; + break; + + case LSM6DSO_LC_CLEAR: + *val = LSM6DSO_LC_CLEAR; + break; + + case LSM6DSO_LC_CLEAR_DONE: + *val = LSM6DSO_LC_CLEAR_DONE; + break; + + default: + *val = LSM6DSO_LC_NORMAL; + break; + } + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief FSM output registers[get] + * + * @param ctx read / write interface definitions + * @param val struct of registers from FSM_OUTS1 to FSM_OUTS16 + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fsm_out_get(stmdev_ctx_t *ctx, lsm6dso_fsm_out_t *val) +{ + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_FSM_OUTS1, (uint8_t *)val, 16); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Finite State Machine ODR configuration.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of fsm_odr in reg EMB_FUNC_ODR_CFG_B + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fsm_data_rate_set(stmdev_ctx_t *ctx, + lsm6dso_fsm_odr_t val) +{ + lsm6dso_emb_func_odr_cfg_b_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_EMB_FUNC_ODR_CFG_B, + (uint8_t *)®, 1); + } + + if (ret == 0) + { + reg.not_used_01 = 3; /* set default values */ + reg.not_used_02 = 2; /* set default values */ + reg.fsm_odr = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_EMB_FUNC_ODR_CFG_B, + (uint8_t *)®, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Finite State Machine ODR configuration.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of fsm_odr in reg EMB_FUNC_ODR_CFG_B + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fsm_data_rate_get(stmdev_ctx_t *ctx, + lsm6dso_fsm_odr_t *val) +{ + lsm6dso_emb_func_odr_cfg_b_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_EMB_FUNC_ODR_CFG_B, + (uint8_t *)®, 1); + } + + if (ret == 0) + { + switch (reg.fsm_odr) + { + case LSM6DSO_ODR_FSM_12Hz5: + *val = LSM6DSO_ODR_FSM_12Hz5; + break; + + case LSM6DSO_ODR_FSM_26Hz: + *val = LSM6DSO_ODR_FSM_26Hz; + break; + + case LSM6DSO_ODR_FSM_52Hz: + *val = LSM6DSO_ODR_FSM_52Hz; + break; + + case LSM6DSO_ODR_FSM_104Hz: + *val = LSM6DSO_ODR_FSM_104Hz; + break; + + default: + *val = LSM6DSO_ODR_FSM_12Hz5; + break; + } + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief FSM initialization request.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of fsm_init in reg FSM_INIT + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fsm_init_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_emb_func_init_b_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_EMB_FUNC_INIT_B, (uint8_t *)®, 1); + } + + if (ret == 0) + { + reg.fsm_init = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_EMB_FUNC_INIT_B, (uint8_t *)®, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief FSM initialization request.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of fsm_init in reg FSM_INIT + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fsm_init_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_emb_func_init_b_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_EMB_FUNC_INIT_B, (uint8_t *)®, 1); + } + + if (ret == 0) + { + *val = reg.fsm_init; + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief FSM long counter timeout register (r/w). The long counter + * timeout value is an unsigned integer value (16-bit format). + * When the long counter value reached this value, + * the FSM generates an interrupt.[set] + * + * @param ctx read / write interface definitions + * @param val the value of long counter + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_long_cnt_int_value_set(stmdev_ctx_t *ctx, + uint16_t val) +{ + uint8_t buff[2]; + int32_t ret; + + buff[1] = (uint8_t)(val / 256U); + buff[0] = (uint8_t)(val - (buff[1] * 256U)); + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_FSM_LC_TIMEOUT_L, + &buff[0]); + + if (ret == 0) + { + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_FSM_LC_TIMEOUT_H, + &buff[1]); + } + + return ret; +} + +/** + * @brief FSM long counter timeout register (r/w). The long counter + * timeout value is an unsigned integer value (16-bit format). + * When the long counter value reached this value, + * the FSM generates an interrupt.[get] + * + * @param ctx read / write interface definitions + * @param val buffer that stores the value of long counter + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_long_cnt_int_value_get(stmdev_ctx_t *ctx, + uint16_t *val) +{ + uint8_t buff[2]; + int32_t ret; + + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_FSM_LC_TIMEOUT_L, + &buff[0]); + + if (ret == 0) + { + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_FSM_LC_TIMEOUT_H, + &buff[1]); + *val = buff[1]; + *val = (*val * 256U) + buff[0]; + } + + return ret; +} + +/** + * @brief FSM number of programs register.[set] + * + * @param ctx read / write interface definitions + * @param val value to write + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fsm_number_of_programs_set(stmdev_ctx_t *ctx, + uint8_t val) +{ + int32_t ret; + + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_FSM_PROGRAMS, &val); + + return ret; +} + +/** + * @brief FSM number of programs register.[get] + * + * @param ctx read / write interface definitions + * @param val buffer that stores data read. + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fsm_number_of_programs_get(stmdev_ctx_t *ctx, + uint8_t *val) +{ + int32_t ret; + + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_FSM_PROGRAMS, val); + + return ret; +} + +/** + * @brief FSM start address register (r/w). + * First available address is 0x033C.[set] + * + * @param ctx read / write interface definitions + * @param val the value of start address + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fsm_start_address_set(stmdev_ctx_t *ctx, uint16_t val) +{ + uint8_t buff[2]; + int32_t ret; + + buff[1] = (uint8_t)(val / 256U); + buff[0] = (uint8_t)(val - (buff[1] * 256U)); + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_FSM_START_ADD_L, + &buff[0]); + + if (ret == 0) + { + ret = lsm6dso_ln_pg_write_byte(ctx, LSM6DSO_FSM_START_ADD_H, + &buff[1]); + } + + return ret; +} + +/** + * @brief FSM start address register (r/w). + * First available address is 0x033C.[get] + * + * @param ctx read / write interface definitions + * @param val buffer the value of start address. + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_fsm_start_address_get(stmdev_ctx_t *ctx, + uint16_t *val) +{ + uint8_t buff[2]; + int32_t ret; + + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_FSM_START_ADD_L, &buff[0]); + + if (ret == 0) + { + ret = lsm6dso_ln_pg_read_byte(ctx, LSM6DSO_FSM_START_ADD_H, &buff[1]); + *val = buff[1]; + *val = (*val * 256U) + buff[0]; + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LSM6DSO_Sensor_hub + * @brief This section groups all the functions that manage the + * sensor hub. + * @{ + * + */ + +/** + * @brief Sensor hub output registers.[get] + * + * @param ctx read / write interface definitions + * @param val values read from registers SENSOR_HUB_1 to SENSOR_HUB_18 + * @param len number of consecutive register to read (max 18) + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sh_read_data_raw_get(stmdev_ctx_t *ctx, uint8_t *val, + uint8_t len) +{ + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_SENSOR_HUB_1, (uint8_t *) val, + len); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Number of external sensors to be read by the sensor hub.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of aux_sens_on in reg MASTER_CONFIG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sh_slave_connected_set(stmdev_ctx_t *ctx, + lsm6dso_aux_sens_on_t val) +{ + lsm6dso_master_config_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_MASTER_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + reg.aux_sens_on = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_MASTER_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Number of external sensors to be read by the sensor hub.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of aux_sens_on in reg MASTER_CONFIG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sh_slave_connected_get(stmdev_ctx_t *ctx, + lsm6dso_aux_sens_on_t *val) +{ + lsm6dso_master_config_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_MASTER_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + switch (reg.aux_sens_on) + { + case LSM6DSO_SLV_0: + *val = LSM6DSO_SLV_0; + break; + + case LSM6DSO_SLV_0_1: + *val = LSM6DSO_SLV_0_1; + break; + + case LSM6DSO_SLV_0_1_2: + *val = LSM6DSO_SLV_0_1_2; + break; + + case LSM6DSO_SLV_0_1_2_3: + *val = LSM6DSO_SLV_0_1_2_3; + break; + + default: + *val = LSM6DSO_SLV_0; + break; + } + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Sensor hub I2C master enable.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of master_on in reg MASTER_CONFIG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sh_master_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_master_config_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_MASTER_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + reg.master_on = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_MASTER_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Sensor hub I2C master enable.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of master_on in reg MASTER_CONFIG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sh_master_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_master_config_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_MASTER_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + *val = reg.master_on; + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Master I2C pull-up enable.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of shub_pu_en in reg MASTER_CONFIG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sh_pin_mode_set(stmdev_ctx_t *ctx, + lsm6dso_shub_pu_en_t val) +{ + lsm6dso_master_config_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_MASTER_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + reg.shub_pu_en = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_MASTER_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Master I2C pull-up enable.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of shub_pu_en in reg MASTER_CONFIG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sh_pin_mode_get(stmdev_ctx_t *ctx, + lsm6dso_shub_pu_en_t *val) +{ + lsm6dso_master_config_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_MASTER_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + switch (reg.shub_pu_en) + { + case LSM6DSO_EXT_PULL_UP: + *val = LSM6DSO_EXT_PULL_UP; + break; + + case LSM6DSO_INTERNAL_PULL_UP: + *val = LSM6DSO_INTERNAL_PULL_UP; + break; + + default: + *val = LSM6DSO_EXT_PULL_UP; + break; + } + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief I2C interface pass-through.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of pass_through_mode in + * reg MASTER_CONFIG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sh_pass_through_set(stmdev_ctx_t *ctx, uint8_t val) +{ + lsm6dso_master_config_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_MASTER_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + reg.pass_through_mode = val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_MASTER_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief I2C interface pass-through.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of pass_through_mode in + * reg MASTER_CONFIG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sh_pass_through_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_master_config_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_MASTER_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + *val = reg.pass_through_mode; + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Sensor hub trigger signal selection.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of start_config in reg MASTER_CONFIG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sh_syncro_mode_set(stmdev_ctx_t *ctx, + lsm6dso_start_config_t val) +{ + lsm6dso_master_config_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_MASTER_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + reg.start_config = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_MASTER_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Sensor hub trigger signal selection.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of start_config in reg MASTER_CONFIG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sh_syncro_mode_get(stmdev_ctx_t *ctx, + lsm6dso_start_config_t *val) +{ + lsm6dso_master_config_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_MASTER_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + switch (reg.start_config) + { + case LSM6DSO_EXT_ON_INT2_PIN: + *val = LSM6DSO_EXT_ON_INT2_PIN; + break; + + case LSM6DSO_XL_GY_DRDY: + *val = LSM6DSO_XL_GY_DRDY; + break; + + default: + *val = LSM6DSO_EXT_ON_INT2_PIN; + break; + } + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Slave 0 write operation is performed only at the first + * sensor hub cycle.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of write_once in reg MASTER_CONFIG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sh_write_mode_set(stmdev_ctx_t *ctx, + lsm6dso_write_once_t val) +{ + lsm6dso_master_config_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_MASTER_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + reg.write_once = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_MASTER_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Slave 0 write operation is performed only at the first sensor + * hub cycle.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of write_once in reg MASTER_CONFIG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sh_write_mode_get(stmdev_ctx_t *ctx, + lsm6dso_write_once_t *val) +{ + lsm6dso_master_config_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_MASTER_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + switch (reg.write_once) + { + case LSM6DSO_EACH_SH_CYCLE: + *val = LSM6DSO_EACH_SH_CYCLE; + break; + + case LSM6DSO_ONLY_FIRST_CYCLE: + *val = LSM6DSO_ONLY_FIRST_CYCLE; + break; + + default: + *val = LSM6DSO_EACH_SH_CYCLE; + break; + } + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Reset Master logic and output registers.[set] + * + * @param ctx read / write interface definitions + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sh_reset_set(stmdev_ctx_t *ctx) +{ + lsm6dso_master_config_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_MASTER_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + reg.rst_master_regs = PROPERTY_ENABLE; + ret = lsm6dso_write_reg(ctx, LSM6DSO_MASTER_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + reg.rst_master_regs = PROPERTY_DISABLE; + ret = lsm6dso_write_reg(ctx, LSM6DSO_MASTER_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Reset Master logic and output registers.[get] + * + * @param ctx read / write interface definitions + * @param val change the values of rst_master_regs in reg MASTER_CONFIG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sh_reset_get(stmdev_ctx_t *ctx, uint8_t *val) +{ + lsm6dso_master_config_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_MASTER_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + *val = reg.rst_master_regs; + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Rate at which the master communicates.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of shub_odr in reg slv1_CONFIG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sh_data_rate_set(stmdev_ctx_t *ctx, + lsm6dso_shub_odr_t val) +{ + lsm6dso_slv0_config_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_SLV0_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + reg.shub_odr = (uint8_t)val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_SLV0_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Rate at which the master communicates.[get] + * + * @param ctx read / write interface definitions + * @param val Get the values of shub_odr in reg slv1_CONFIG + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sh_data_rate_get(stmdev_ctx_t *ctx, + lsm6dso_shub_odr_t *val) +{ + lsm6dso_slv0_config_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_SLV0_CONFIG, (uint8_t *)®, 1); + } + + if (ret == 0) + { + switch (reg.shub_odr) + { + case LSM6DSO_SH_ODR_104Hz: + *val = LSM6DSO_SH_ODR_104Hz; + break; + + case LSM6DSO_SH_ODR_52Hz: + *val = LSM6DSO_SH_ODR_52Hz; + break; + + case LSM6DSO_SH_ODR_26Hz: + *val = LSM6DSO_SH_ODR_26Hz; + break; + + case LSM6DSO_SH_ODR_13Hz: + *val = LSM6DSO_SH_ODR_13Hz; + break; + + default: + *val = LSM6DSO_SH_ODR_104Hz; + break; + } + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Configure slave 0 for perform a write.[set] + * + * @param ctx read / write interface definitions + * @param val a structure that contain + * - uint8_t slv1_add; 8 bit i2c device address + * - uint8_t slv1_subadd; 8 bit register device address + * - uint8_t slv1_data; 8 bit data to write + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sh_cfg_write(stmdev_ctx_t *ctx, + lsm6dso_sh_cfg_write_t *val) +{ + lsm6dso_slv0_add_t reg; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + + if (ret == 0) + { + reg.slave0 = val->slv0_add; + reg.rw_0 = 0; + ret = lsm6dso_write_reg(ctx, LSM6DSO_SLV0_ADD, (uint8_t *)®, 1); + } + + if (ret == 0) + { + ret = lsm6dso_write_reg(ctx, LSM6DSO_SLV0_SUBADD, + &(val->slv0_subadd), 1); + } + + if (ret == 0) + { + ret = lsm6dso_write_reg(ctx, LSM6DSO_DATAWRITE_SLV0, + &(val->slv0_data), 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Configure slave 0 for perform a read.[set] + * + * @param ctx read / write interface definitions + * @param val Structure that contain + * - uint8_t slv1_add; 8 bit i2c device address + * - uint8_t slv1_subadd; 8 bit register device address + * - uint8_t slv1_len; num of bit to read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sh_slv0_cfg_read(stmdev_ctx_t *ctx, + lsm6dso_sh_cfg_read_t *val) +{ + lsm6dso_slv0_add_t slv0_add; + lsm6dso_slv0_config_t slv0_config; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + + if (ret == 0) + { + slv0_add.slave0 = val->slv_add; + slv0_add.rw_0 = 1; + ret = lsm6dso_write_reg(ctx, LSM6DSO_SLV0_ADD, (uint8_t *)&slv0_add, 1); + } + + if (ret == 0) + { + ret = lsm6dso_write_reg(ctx, LSM6DSO_SLV0_SUBADD, + &(val->slv_subadd), 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_SLV0_CONFIG, + (uint8_t *)&slv0_config, 1); + } + + if (ret == 0) + { + slv0_config.slave0_numop = val->slv_len; + ret = lsm6dso_write_reg(ctx, LSM6DSO_SLV0_CONFIG, + (uint8_t *)&slv0_config, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Configure slave 0 for perform a write/read.[set] + * + * @param ctx read / write interface definitions + * @param val Structure that contain + * - uint8_t slv1_add; 8 bit i2c device address + * - uint8_t slv1_subadd; 8 bit register device address + * - uint8_t slv1_len; num of bit to read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sh_slv1_cfg_read(stmdev_ctx_t *ctx, + lsm6dso_sh_cfg_read_t *val) +{ + lsm6dso_slv1_add_t slv1_add; + lsm6dso_slv1_config_t slv1_config; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + + if (ret == 0) + { + slv1_add.slave1_add = val->slv_add; + slv1_add.r_1 = 1; + ret = lsm6dso_write_reg(ctx, LSM6DSO_SLV1_ADD, (uint8_t *)&slv1_add, 1); + } + + if (ret == 0) + { + ret = lsm6dso_write_reg(ctx, LSM6DSO_SLV1_SUBADD, + &(val->slv_subadd), 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_SLV1_CONFIG, + (uint8_t *)&slv1_config, 1); + } + + if (ret == 0) + { + slv1_config.slave1_numop = val->slv_len; + ret = lsm6dso_write_reg(ctx, LSM6DSO_SLV1_CONFIG, + (uint8_t *)&slv1_config, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Configure slave 0 for perform a write/read.[set] + * + * @param ctx read / write interface definitions + * @param val Structure that contain + * - uint8_t slv2_add; 8 bit i2c device address + * - uint8_t slv2_subadd; 8 bit register device address + * - uint8_t slv2_len; num of bit to read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sh_slv2_cfg_read(stmdev_ctx_t *ctx, + lsm6dso_sh_cfg_read_t *val) +{ + lsm6dso_slv2_add_t slv2_add; + lsm6dso_slv2_config_t slv2_config; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + + if (ret == 0) + { + slv2_add.slave2_add = val->slv_add; + slv2_add.r_2 = 1; + ret = lsm6dso_write_reg(ctx, LSM6DSO_SLV2_ADD, (uint8_t *)&slv2_add, 1); + } + + if (ret == 0) + { + ret = lsm6dso_write_reg(ctx, LSM6DSO_SLV2_SUBADD, + &(val->slv_subadd), 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_SLV2_CONFIG, + (uint8_t *)&slv2_config, 1); + } + + if (ret == 0) + { + slv2_config.slave2_numop = val->slv_len; + ret = lsm6dso_write_reg(ctx, LSM6DSO_SLV2_CONFIG, + (uint8_t *)&slv2_config, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Configure slave 0 for perform a write/read.[set] + * + * @param ctx read / write interface definitions + * @param val Structure that contain + * - uint8_t slv3_add; 8 bit i2c device address + * - uint8_t slv3_subadd; 8 bit register device address + * - uint8_t slv3_len; num of bit to read + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sh_slv3_cfg_read(stmdev_ctx_t *ctx, + lsm6dso_sh_cfg_read_t *val) +{ + lsm6dso_slv3_add_t slv3_add; + lsm6dso_slv3_config_t slv3_config; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + + if (ret == 0) + { + slv3_add.slave3_add = val->slv_add; + slv3_add.r_3 = 1; + ret = lsm6dso_write_reg(ctx, LSM6DSO_SLV3_ADD, (uint8_t *)&slv3_add, 1); + } + + if (ret == 0) + { + ret = lsm6dso_write_reg(ctx, LSM6DSO_SLV3_SUBADD, + &(val->slv_subadd), 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_SLV3_CONFIG, + (uint8_t *)&slv3_config, 1); + } + + if (ret == 0) + { + slv3_config.slave3_numop = val->slv_len; + ret = lsm6dso_write_reg(ctx, LSM6DSO_SLV3_CONFIG, + (uint8_t *)&slv3_config, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Sensor hub source register.[get] + * + * @param ctx read / write interface definitions + * @param val union of registers from STATUS_MASTER to + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_sh_status_get(stmdev_ctx_t *ctx, + lsm6dso_status_master_t *val) +{ + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_STATUS_MASTER, (uint8_t *) val, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup Basic configuration + * @brief This section groups all the functions concerning + * device basic configuration. + * @{ + * + */ + +/** + * @brief Device "Who am I".[get] + * + * @param ctx communication interface handler. Use NULL to ignore + * this interface.(ptr) + * @param aux_ctx auxiliary communication interface handler. Use NULL + * to ignore this interface.(ptr) + * @param val ID values read from the two interfaces. ID values + * will be the same.(ptr) + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_id_get(stmdev_ctx_t *ctx, stmdev_ctx_t *aux_ctx, + lsm6dso_id_t *val) +{ + int32_t ret = 0; + + if (ctx != NULL) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_WHO_AM_I, + (uint8_t *) & (val->ui), 1); + } + + if (aux_ctx != NULL) + { + if (ret == 0) + { + ret = lsm6dso_read_reg(aux_ctx, LSM6DSO_WHO_AM_I, + (uint8_t *) & (val->aux), 1); + } + } + + return ret; +} + +/** + * @brief Re-initialize the device.[set] + * + * @param ctx communication interface handler.(ptr) + * @param val re-initialization mode. Refer to datasheet + * and application note for more information + * about differencies between boot and sw_reset + * procedure. + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_init_set(stmdev_ctx_t *ctx, lsm6dso_init_t val) +{ + lsm6dso_emb_func_init_a_t emb_func_init_a; + lsm6dso_emb_func_init_b_t emb_func_init_b; + lsm6dso_ctrl3_c_t ctrl3_c; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_EMB_FUNC_INIT_B, + (uint8_t *)&emb_func_init_b, 1); + } + + if (ret == 0) + { + emb_func_init_b.fifo_compr_init = (uint8_t)val + & ((uint8_t)LSM6DSO_FIFO_COMP >> 2); + emb_func_init_b.fsm_init = (uint8_t)val + & ((uint8_t)LSM6DSO_FSM >> 3); + ret = lsm6dso_write_reg(ctx, LSM6DSO_EMB_FUNC_INIT_B, + (uint8_t *)&emb_func_init_b, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_EMB_FUNC_INIT_A, + (uint8_t *)&emb_func_init_a, 1); + } + + if (ret == 0) + { + emb_func_init_a.step_det_init = ((uint8_t)val + & (uint8_t)LSM6DSO_PEDO) >> 5; + emb_func_init_a.tilt_init = ((uint8_t)val + & (uint8_t)LSM6DSO_TILT) >> 6; + emb_func_init_a.sig_mot_init = ((uint8_t)val + & (uint8_t)LSM6DSO_SMOTION) >> 7; + ret = lsm6dso_write_reg(ctx, LSM6DSO_EMB_FUNC_INIT_A, + (uint8_t *)&emb_func_init_a, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL3_C, (uint8_t *)&ctrl3_c, 1); + } + + if (((val == LSM6DSO_BOOT) || (val == LSM6DSO_RESET)) && + (ret == 0)) + { + ctrl3_c.boot = (uint8_t)val & (uint8_t)LSM6DSO_BOOT; + ctrl3_c.sw_reset = ((uint8_t)val & (uint8_t)LSM6DSO_RESET) >> 1; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL3_C, (uint8_t *)&ctrl3_c, 1); + } + + if ((val == LSM6DSO_DRV_RDY) + && ((ctrl3_c.bdu == PROPERTY_DISABLE) + || (ctrl3_c.if_inc == PROPERTY_DISABLE)) && (ret == 0)) + { + ctrl3_c.bdu = PROPERTY_ENABLE; + ctrl3_c.if_inc = PROPERTY_ENABLE; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL3_C, (uint8_t *)&ctrl3_c, 1); + } + + return ret; +} + +/** + * @brief Configures the bus operating mode.[set] + * + * @param ctx communication interface handler. Use NULL to ignore + * this interface.(ptr) + * @param aux_ctx auxiliary communication interface handler. Use NULL + * to ignore this interface.(ptr) + * @param val configures the bus operating mode for both the + * main and the auxiliary interface. + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_bus_mode_set(stmdev_ctx_t *ctx, stmdev_ctx_t *aux_ctx, + lsm6dso_bus_mode_t val) +{ + lsm6dso_ctrl1_ois_t ctrl1_ois; + lsm6dso_i3c_bus_avb_t i3c_bus_avb; + lsm6dso_ctrl9_xl_t ctrl9_xl; + lsm6dso_ctrl3_c_t ctrl3_c; + lsm6dso_ctrl4_c_t ctrl4_c; + uint8_t bit_val; + int32_t ret; + + ret = 0; + + if (aux_ctx != NULL) + { + ret = lsm6dso_read_reg(aux_ctx, LSM6DSO_CTRL1_OIS, + (uint8_t *)&ctrl1_ois, 1); + bit_val = ((uint8_t)val.aux_bus_md & 0x04U) >> 2; + + if ((ret == 0) && (ctrl1_ois.sim_ois != bit_val)) + { + ctrl1_ois.sim_ois = bit_val; + ret = lsm6dso_write_reg(aux_ctx, LSM6DSO_CTRL1_OIS, + (uint8_t *)&ctrl1_ois, 1); + } + } + + if (ctx != NULL) + { + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL9_XL, + (uint8_t *)&ctrl9_xl, 1); + } + + bit_val = ((uint8_t)val.ui_bus_md & 0x04U) >> 2; + + if ((ret == 0) && (ctrl9_xl.i3c_disable != bit_val)) + { + ctrl9_xl.i3c_disable = bit_val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL9_XL, + (uint8_t *)&ctrl9_xl, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_I3C_BUS_AVB, + (uint8_t *)&i3c_bus_avb, 1); + } + + bit_val = ((uint8_t)val.ui_bus_md & 0x30U) >> 4; + + if ((ret == 0) && (i3c_bus_avb.i3c_bus_avb_sel != bit_val)) + { + i3c_bus_avb.i3c_bus_avb_sel = bit_val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_I3C_BUS_AVB, + (uint8_t *)&i3c_bus_avb, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL4_C, + (uint8_t *)&ctrl4_c, 1); + } + + bit_val = ((uint8_t)val.ui_bus_md & 0x02U) >> 1; + + if ((ret == 0) && (ctrl4_c.i2c_disable != bit_val)) + { + ctrl4_c.i2c_disable = bit_val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL4_C, + (uint8_t *)&ctrl4_c, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL3_C, + (uint8_t *)&ctrl3_c, 1); + } + + bit_val = (uint8_t)val.ui_bus_md & 0x01U; + + if ((ret == 0) && (ctrl3_c.sim != bit_val)) + { + ctrl3_c.sim = bit_val; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL3_C, + (uint8_t *)&ctrl3_c, 1); + } + } + + return ret; +} + +/** + * @brief Get the bus operating mode.[get] + * + * @param ctx communication interface handler. Use NULL to ignore + * this interface.(ptr) + * @param aux_ctx auxiliary communication interface handler. Use NULL + * to ignore this interface.(ptr) + * @param val retrieves the bus operating mode for both the main + * and the auxiliary interface.(ptr) + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_bus_mode_get(stmdev_ctx_t *ctx, stmdev_ctx_t *aux_ctx, + lsm6dso_bus_mode_t *val) +{ + lsm6dso_ctrl1_ois_t ctrl1_ois; + lsm6dso_i3c_bus_avb_t i3c_bus_avb; + lsm6dso_ctrl9_xl_t ctrl9_xl; + lsm6dso_ctrl3_c_t ctrl3_c; + lsm6dso_ctrl4_c_t ctrl4_c; + int32_t ret = 0; + + if (aux_ctx != NULL) + { + ret = lsm6dso_read_reg(aux_ctx, LSM6DSO_CTRL1_OIS, + (uint8_t *)&ctrl1_ois, 1); + + switch (ctrl1_ois.sim_ois) + { + case LSM6DSO_SPI_4W_AUX: + val->aux_bus_md = LSM6DSO_SPI_4W_AUX; + break; + + case LSM6DSO_SPI_3W_AUX: + val->aux_bus_md = LSM6DSO_SPI_3W_AUX; + break; + + default: + val->aux_bus_md = LSM6DSO_SPI_4W_AUX; + break; + } + } + + if (ctx != NULL) + { + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL9_XL, + (uint8_t *)&ctrl9_xl, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_I3C_BUS_AVB, + (uint8_t *)&i3c_bus_avb, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL4_C, + (uint8_t *)&ctrl4_c, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL3_C, + (uint8_t *)&ctrl3_c, 1); + + switch ((i3c_bus_avb.i3c_bus_avb_sel << 4) & + (ctrl9_xl.i3c_disable << 2) & + (ctrl4_c.i2c_disable << 1) & ctrl3_c.sim) + { + case LSM6DSO_SEL_BY_HW: + val->ui_bus_md = LSM6DSO_SEL_BY_HW; + break; + + case LSM6DSO_SPI_4W: + val->ui_bus_md = LSM6DSO_SPI_4W; + break; + + case LSM6DSO_SPI_3W: + val->ui_bus_md = LSM6DSO_SPI_3W; + break; + + case LSM6DSO_I2C: + val->ui_bus_md = LSM6DSO_I2C; + break; + + case LSM6DSO_I3C_T_50us: + val->ui_bus_md = LSM6DSO_I3C_T_50us; + break; + + case LSM6DSO_I3C_T_2us: + val->ui_bus_md = LSM6DSO_I3C_T_2us; + break; + + case LSM6DSO_I3C_T_1ms: + val->ui_bus_md = LSM6DSO_I3C_T_1ms; + break; + + case LSM6DSO_I3C_T_25ms: + val->ui_bus_md = LSM6DSO_I3C_T_25ms; + break; + + default: + val->ui_bus_md = LSM6DSO_SEL_BY_HW; + break; + } + } + } + + return ret; +} + +/** + * @brief Get the status of the device.[get] + * + * @param ctx communication interface handler. Use NULL to ignore + * this interface.(ptr) + * @param aux_ctx auxiliary communication interface handler. Use NULL + * to ignore this interface.(ptr) + * @param val the status of the device.(ptr) + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_status_get(stmdev_ctx_t *ctx, stmdev_ctx_t *aux_ctx, + lsm6dso_status_t *val) +{ + lsm6dso_status_spiaux_t status_spiaux; + lsm6dso_status_reg_t status_reg; + lsm6dso_ctrl3_c_t ctrl3_c; + int32_t ret; + ret = 0; + + if (aux_ctx != NULL) + { + ret = lsm6dso_read_reg(aux_ctx, LSM6DSO_STATUS_SPIAUX, + (uint8_t *)&status_spiaux, 1); + val->ois_drdy_xl = status_spiaux.xlda; + val->ois_drdy_g = status_spiaux.gda; + val->ois_gyro_settling = status_spiaux.gyro_settling; + } + + if (ctx != NULL) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL3_C, (uint8_t *)&ctrl3_c, 1); + val->sw_reset = ctrl3_c.sw_reset; + val->boot = ctrl3_c.boot; + + if ((ret == 0) && (ctrl3_c.sw_reset == PROPERTY_DISABLE) && + (ctrl3_c.boot == PROPERTY_DISABLE)) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_STATUS_REG, + (uint8_t *)&status_reg, 1); + val->drdy_xl = status_reg.xlda; + val->drdy_g = status_reg.gda; + val->drdy_temp = status_reg.tda; + } + } + + return ret; +} + +/** + * @brief Electrical pin configuration.[set] + * + * @param ctx communication interface handler.(ptr) + * @param val the electrical settings for the configurable + * pins. + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_pin_conf_set(stmdev_ctx_t *ctx, + lsm6dso_pin_conf_t val) +{ + lsm6dso_i3c_bus_avb_t i3c_bus_avb; + lsm6dso_pin_ctrl_t pin_ctrl; + lsm6dso_ctrl3_c_t ctrl3_c; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_PIN_CTRL, (uint8_t *)&pin_ctrl, 1); + + if (ret == 0) + { + pin_ctrl.ois_pu_dis = ~val.aux_sdo_ocs_pull_up; + pin_ctrl.sdo_pu_en = val.sdo_sa0_pull_up; + ret = lsm6dso_write_reg(ctx, LSM6DSO_PIN_CTRL, (uint8_t *)&pin_ctrl, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL3_C, (uint8_t *)&ctrl3_c, 1); + } + + if (ret == 0) + { + ctrl3_c.pp_od = ~val.int1_int2_push_pull; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL3_C, (uint8_t *)&ctrl3_c, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_I3C_BUS_AVB, + (uint8_t *)&i3c_bus_avb, 1); + } + + if (ret == 0) + { + i3c_bus_avb.pd_dis_int1 = ~val.int1_pull_down; + ret = lsm6dso_write_reg(ctx, LSM6DSO_I3C_BUS_AVB, + (uint8_t *)&i3c_bus_avb, 1); + } + + return ret; +} + +/** + * @brief Electrical pin configuration.[get] + * + * @param ctx communication interface handler.(ptr) + * @param val the electrical settings for the configurable + * pins.(ptr) + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_pin_conf_get(stmdev_ctx_t *ctx, + lsm6dso_pin_conf_t *val) +{ + lsm6dso_i3c_bus_avb_t i3c_bus_avb; + lsm6dso_pin_ctrl_t pin_ctrl; + lsm6dso_ctrl3_c_t ctrl3_c; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_PIN_CTRL, (uint8_t *)&pin_ctrl, 1); + + if (ret == 0) + { + val->aux_sdo_ocs_pull_up = ~pin_ctrl.ois_pu_dis; + val->aux_sdo_ocs_pull_up = pin_ctrl.sdo_pu_en; + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL3_C, (uint8_t *)&ctrl3_c, 1); + } + + if (ret == 0) + { + val->int1_int2_push_pull = ~ctrl3_c.pp_od; + ret = lsm6dso_read_reg(ctx, LSM6DSO_I3C_BUS_AVB, + (uint8_t *)&i3c_bus_avb, 1); + } + + if (ret == 0) + { + val->int1_pull_down = ~i3c_bus_avb.pd_dis_int1; + } + + return ret; +} + +/** + * @brief Interrupt pins hardware signal configuration.[set] + * + * @param ctx communication interface handler.(ptr) + * @param val the pins hardware signal settings. + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_interrupt_mode_set(stmdev_ctx_t *ctx, + lsm6dso_int_mode_t val) +{ + lsm6dso_tap_cfg0_t tap_cfg0; + lsm6dso_page_rw_t page_rw; + lsm6dso_ctrl3_c_t ctrl3_c; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL3_C, (uint8_t *)&ctrl3_c, 1); + + if (ret == 0) + { + ctrl3_c.h_lactive = val.active_low; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL3_C, (uint8_t *)&ctrl3_c, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_TAP_CFG0, (uint8_t *) &tap_cfg0, 1); + } + + if (ret == 0) + { + tap_cfg0.lir = val.base_latched; + tap_cfg0.int_clr_on_read = val.base_latched | val.emb_latched; + ret = lsm6dso_write_reg(ctx, LSM6DSO_TAP_CFG0, (uint8_t *) &tap_cfg0, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_PAGE_RW, (uint8_t *) &page_rw, 1); + } + + if (ret == 0) + { + page_rw.emb_func_lir = val.emb_latched; + ret = lsm6dso_write_reg(ctx, LSM6DSO_PAGE_RW, (uint8_t *) &page_rw, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Interrupt pins hardware signal configuration.[get] + * + * @param ctx communication interface handler.(ptr) + * @param val the pins hardware signal settings.(ptr) + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_interrupt_mode_get(stmdev_ctx_t *ctx, + lsm6dso_int_mode_t *val) +{ + lsm6dso_tap_cfg0_t tap_cfg0; + lsm6dso_page_rw_t page_rw; + lsm6dso_ctrl3_c_t ctrl3_c; + int32_t ret; + + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL3_C, (uint8_t *)&ctrl3_c, 1); + + if (ret == 0) + { + ctrl3_c.h_lactive = val->active_low; + ret = lsm6dso_read_reg(ctx, LSM6DSO_TAP_CFG0, (uint8_t *) &tap_cfg0, 1); + } + + if (ret == 0) + { + tap_cfg0.lir = val->base_latched; + tap_cfg0.int_clr_on_read = val->base_latched | val->emb_latched; + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_PAGE_RW, (uint8_t *) &page_rw, 1); + } + + if (ret == 0) + { + page_rw.emb_func_lir = val->emb_latched; + ret = lsm6dso_write_reg(ctx, LSM6DSO_PAGE_RW, (uint8_t *) &page_rw, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Route interrupt signals on int1 pin.[set] + * + * @param ctx communication interface handler.(ptr) + * @param val the signals to route on int1 pin. + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_pin_int1_route_set(stmdev_ctx_t *ctx, + lsm6dso_pin_int1_route_t val) +{ + lsm6dso_pin_int2_route_t pin_int2_route; + lsm6dso_emb_func_int1_t emb_func_int1; + lsm6dso_fsm_int1_a_t fsm_int1_a; + lsm6dso_fsm_int1_b_t fsm_int1_b; + lsm6dso_int1_ctrl_t int1_ctrl; + lsm6dso_int2_ctrl_t int2_ctrl; + lsm6dso_tap_cfg2_t tap_cfg2; + lsm6dso_md2_cfg_t md2_cfg; + lsm6dso_md1_cfg_t md1_cfg; + lsm6dso_ctrl4_c_t ctrl4_c; + int32_t ret; + int1_ctrl.int1_drdy_xl = val.drdy_xl; + int1_ctrl.int1_drdy_g = val.drdy_g; + int1_ctrl.int1_boot = val.boot; + int1_ctrl.int1_fifo_th = val.fifo_th; + int1_ctrl.int1_fifo_ovr = val.fifo_ovr; + int1_ctrl.int1_fifo_full = val.fifo_full; + int1_ctrl.int1_cnt_bdr = val.fifo_bdr; + int1_ctrl.den_drdy_flag = val.den_flag; + md1_cfg.int1_shub = val.sh_endop; + md1_cfg.int1_6d = val.six_d; + md1_cfg.int1_double_tap = val.double_tap; + md1_cfg.int1_ff = val.free_fall; + md1_cfg.int1_wu = val.wake_up; + md1_cfg.int1_single_tap = val.single_tap; + md1_cfg.int1_sleep_change = val.sleep_change; + emb_func_int1.not_used_01 = 0; + emb_func_int1.int1_step_detector = val.step_detector; + emb_func_int1.int1_tilt = val.tilt; + emb_func_int1.int1_sig_mot = val.sig_mot; + emb_func_int1.not_used_02 = 0; + emb_func_int1.int1_fsm_lc = val.fsm_lc; + fsm_int1_a.int1_fsm1 = val.fsm1; + fsm_int1_a.int1_fsm2 = val.fsm2; + fsm_int1_a.int1_fsm3 = val.fsm3; + fsm_int1_a.int1_fsm4 = val.fsm4; + fsm_int1_a.int1_fsm5 = val.fsm5; + fsm_int1_a.int1_fsm6 = val.fsm6; + fsm_int1_a.int1_fsm7 = val.fsm7; + fsm_int1_a.int1_fsm8 = val.fsm8; + fsm_int1_b.int1_fsm9 = val.fsm9 ; + fsm_int1_b.int1_fsm10 = val.fsm10; + fsm_int1_b.int1_fsm11 = val.fsm11; + fsm_int1_b.int1_fsm12 = val.fsm12; + fsm_int1_b.int1_fsm13 = val.fsm13; + fsm_int1_b.int1_fsm14 = val.fsm14; + fsm_int1_b.int1_fsm15 = val.fsm15; + fsm_int1_b.int1_fsm16 = val.fsm16; + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL4_C, (uint8_t *)&ctrl4_c, 1); + + if (ret == 0) + { + if ((val.drdy_temp | val.timestamp) != PROPERTY_DISABLE) + { + ctrl4_c.int2_on_int1 = PROPERTY_ENABLE; + } + + else + { + ctrl4_c.int2_on_int1 = PROPERTY_DISABLE; + } + + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL4_C, (uint8_t *)&ctrl4_c, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + } + + if (ret == 0) + { + ret = lsm6dso_write_reg(ctx, LSM6DSO_EMB_FUNC_INT1, + (uint8_t *)&emb_func_int1, 1); + } + + if (ret == 0) + { + ret = lsm6dso_write_reg(ctx, LSM6DSO_FSM_INT1_A, + (uint8_t *)&fsm_int1_a, 1); + } + + if (ret == 0) + { + ret = lsm6dso_write_reg(ctx, LSM6DSO_FSM_INT1_B, + (uint8_t *)&fsm_int1_b, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + if (ret == 0) + { + if ((emb_func_int1.int1_fsm_lc + | emb_func_int1.int1_sig_mot + | emb_func_int1.int1_step_detector + | emb_func_int1.int1_tilt + | fsm_int1_a.int1_fsm1 + | fsm_int1_a.int1_fsm2 + | fsm_int1_a.int1_fsm3 + | fsm_int1_a.int1_fsm4 + | fsm_int1_a.int1_fsm5 + | fsm_int1_a.int1_fsm6 + | fsm_int1_a.int1_fsm7 + | fsm_int1_a.int1_fsm8 + | fsm_int1_b.int1_fsm9 + | fsm_int1_b.int1_fsm10 + | fsm_int1_b.int1_fsm11 + | fsm_int1_b.int1_fsm12 + | fsm_int1_b.int1_fsm13 + | fsm_int1_b.int1_fsm14 + | fsm_int1_b.int1_fsm15 + | fsm_int1_b.int1_fsm16) != PROPERTY_DISABLE) + { + md1_cfg.int1_emb_func = PROPERTY_ENABLE; + } + + else + { + md1_cfg.int1_emb_func = PROPERTY_DISABLE; + } + + ret = lsm6dso_write_reg(ctx, LSM6DSO_INT1_CTRL, + (uint8_t *)&int1_ctrl, 1); + } + + if (ret == 0) + { + ret = lsm6dso_write_reg(ctx, LSM6DSO_MD1_CFG, (uint8_t *)&md1_cfg, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_INT2_CTRL, (uint8_t *)&int2_ctrl, 1); + } + + if (ret == 0) + { + int2_ctrl.int2_drdy_temp = val.drdy_temp; + ret = lsm6dso_write_reg(ctx, LSM6DSO_INT2_CTRL, (uint8_t *)&int2_ctrl, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_MD2_CFG, (uint8_t *)&md2_cfg, 1); + } + + if (ret == 0) + { + md2_cfg.int2_timestamp = val.timestamp; + ret = lsm6dso_write_reg(ctx, LSM6DSO_MD2_CFG, (uint8_t *)&md2_cfg, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_TAP_CFG2, (uint8_t *) &tap_cfg2, 1); + } + + if (ret == 0) + { + ret = lsm6dso_pin_int2_route_get(ctx, NULL, &pin_int2_route); + } + + if (ret == 0) + { + if ((pin_int2_route.fifo_bdr + | pin_int2_route.drdy_g + | pin_int2_route.drdy_temp + | pin_int2_route.drdy_xl + | pin_int2_route.fifo_full + | pin_int2_route.fifo_ovr + | pin_int2_route.fifo_th + | pin_int2_route.six_d + | pin_int2_route.double_tap + | pin_int2_route.free_fall + | pin_int2_route.wake_up + | pin_int2_route.single_tap + | pin_int2_route.sleep_change + | int1_ctrl.den_drdy_flag + | int1_ctrl.int1_boot + | int1_ctrl.int1_cnt_bdr + | int1_ctrl.int1_drdy_g + | int1_ctrl.int1_drdy_xl + | int1_ctrl.int1_fifo_full + | int1_ctrl.int1_fifo_ovr + | int1_ctrl.int1_fifo_th + | md1_cfg.int1_shub + | md1_cfg.int1_6d + | md1_cfg.int1_double_tap + | md1_cfg.int1_ff + | md1_cfg.int1_wu + | md1_cfg.int1_single_tap + | md1_cfg.int1_sleep_change) != PROPERTY_DISABLE) + { + tap_cfg2.interrupts_enable = PROPERTY_ENABLE; + } + + else + { + tap_cfg2.interrupts_enable = PROPERTY_DISABLE; + } + + ret = lsm6dso_write_reg(ctx, LSM6DSO_TAP_CFG2, (uint8_t *) &tap_cfg2, 1); + } + + return ret; +} + +/** + * @brief Route interrupt signals on int1 pin.[get] + * + * @param ctx communication interface handler.(ptr) + * @param val the signals that are routed on int1 pin.(ptr) + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_pin_int1_route_get(stmdev_ctx_t *ctx, + lsm6dso_pin_int1_route_t *val) +{ + lsm6dso_emb_func_int1_t emb_func_int1; + lsm6dso_fsm_int1_a_t fsm_int1_a; + lsm6dso_fsm_int1_b_t fsm_int1_b; + lsm6dso_int1_ctrl_t int1_ctrl; + lsm6dso_int2_ctrl_t int2_ctrl; + lsm6dso_md2_cfg_t md2_cfg; + lsm6dso_md1_cfg_t md1_cfg; + lsm6dso_ctrl4_c_t ctrl4_c; + int32_t ret; + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_EMB_FUNC_INT1, + (uint8_t *)&emb_func_int1, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_FSM_INT1_A, + (uint8_t *)&fsm_int1_a, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_FSM_INT1_B, + (uint8_t *)&fsm_int1_b, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_INT1_CTRL, + (uint8_t *)&int1_ctrl, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_MD1_CFG, (uint8_t *)&md1_cfg, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL4_C, (uint8_t *)&ctrl4_c, 1); + } + + if (ctrl4_c.int2_on_int1 == PROPERTY_ENABLE) + { + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_INT2_CTRL, (uint8_t *)&int2_ctrl, 1); + val->drdy_temp = int2_ctrl.int2_drdy_temp; + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_MD2_CFG, (uint8_t *)&md2_cfg, 1); + val->timestamp = md2_cfg.int2_timestamp; + } + } + + else + { + val->drdy_temp = PROPERTY_DISABLE; + val->timestamp = PROPERTY_DISABLE; + } + + val->drdy_xl = int1_ctrl.int1_drdy_xl; + val->drdy_g = int1_ctrl.int1_drdy_g; + val->boot = int1_ctrl.int1_boot; + val->fifo_th = int1_ctrl.int1_fifo_th; + val->fifo_ovr = int1_ctrl.int1_fifo_ovr; + val->fifo_full = int1_ctrl.int1_fifo_full; + val->fifo_bdr = int1_ctrl.int1_cnt_bdr; + val->den_flag = int1_ctrl.den_drdy_flag; + val->sh_endop = md1_cfg.int1_shub; + val->six_d = md1_cfg.int1_6d; + val->double_tap = md1_cfg.int1_double_tap; + val->free_fall = md1_cfg.int1_ff; + val->wake_up = md1_cfg.int1_wu; + val->single_tap = md1_cfg.int1_single_tap; + val->sleep_change = md1_cfg.int1_sleep_change; + val->step_detector = emb_func_int1.int1_step_detector; + val->tilt = emb_func_int1.int1_tilt; + val->sig_mot = emb_func_int1.int1_sig_mot; + val->fsm_lc = emb_func_int1.int1_fsm_lc; + val->fsm1 = fsm_int1_a.int1_fsm1; + val->fsm2 = fsm_int1_a.int1_fsm2; + val->fsm3 = fsm_int1_a.int1_fsm3; + val->fsm4 = fsm_int1_a.int1_fsm4; + val->fsm5 = fsm_int1_a.int1_fsm5; + val->fsm6 = fsm_int1_a.int1_fsm6; + val->fsm7 = fsm_int1_a.int1_fsm7; + val->fsm8 = fsm_int1_a.int1_fsm8; + val->fsm9 = fsm_int1_b.int1_fsm9; + val->fsm10 = fsm_int1_b.int1_fsm10; + val->fsm11 = fsm_int1_b.int1_fsm11; + val->fsm12 = fsm_int1_b.int1_fsm12; + val->fsm13 = fsm_int1_b.int1_fsm13; + val->fsm14 = fsm_int1_b.int1_fsm14; + val->fsm15 = fsm_int1_b.int1_fsm15; + val->fsm16 = fsm_int1_b.int1_fsm16; + + return ret; +} + +/** + * @brief Route interrupt signals on int2 pin.[set] + * + * @param ctx communication interface handler. Use NULL to ignore + * this interface.(ptr) + * @param aux_ctx auxiliary communication interface handler. Use NULL + * to ignore this interface.(ptr) + * @param val the signals to route on int2 pin. + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_pin_int2_route_set(stmdev_ctx_t *ctx, + stmdev_ctx_t *aux_ctx, + lsm6dso_pin_int2_route_t val) +{ + lsm6dso_pin_int1_route_t pin_int1_route; + lsm6dso_emb_func_int2_t emb_func_int2; + lsm6dso_fsm_int2_a_t fsm_int2_a; + lsm6dso_fsm_int2_b_t fsm_int2_b; + lsm6dso_int2_ctrl_t int2_ctrl; + lsm6dso_tap_cfg2_t tap_cfg2; + lsm6dso_md2_cfg_t md2_cfg; + lsm6dso_ctrl4_c_t ctrl4_c; + lsm6dso_int_ois_t int_ois; + int32_t ret; + ret = 0; + + if (aux_ctx != NULL) + { + ret = lsm6dso_read_reg(aux_ctx, LSM6DSO_INT_OIS, + (uint8_t *)&int_ois, 1); + + if (ret == 0) + { + int_ois.int2_drdy_ois = val.drdy_ois; + ret = lsm6dso_write_reg(aux_ctx, LSM6DSO_INT_OIS, + (uint8_t *)&int_ois, 1); + } + } + + if (ctx != NULL) + { + int2_ctrl.int2_drdy_xl = val.drdy_xl; + int2_ctrl.int2_drdy_g = val.drdy_g; + int2_ctrl.int2_drdy_temp = val.drdy_temp; + int2_ctrl.int2_fifo_th = val.fifo_th; + int2_ctrl.int2_fifo_ovr = val.fifo_ovr; + int2_ctrl.int2_fifo_full = val.fifo_full; + int2_ctrl.int2_cnt_bdr = val.fifo_bdr; + int2_ctrl.not_used_01 = 0; + md2_cfg.int2_timestamp = val.timestamp; + md2_cfg.int2_6d = val.six_d; + md2_cfg.int2_double_tap = val.double_tap; + md2_cfg.int2_ff = val.free_fall; + md2_cfg.int2_wu = val.wake_up; + md2_cfg.int2_single_tap = val.single_tap; + md2_cfg.int2_sleep_change = val.sleep_change; + emb_func_int2.not_used_01 = 0; + emb_func_int2. int2_step_detector = val.step_detector; + emb_func_int2.int2_tilt = val.tilt; + emb_func_int2.int2_sig_mot = val.sig_mot; + emb_func_int2.not_used_02 = 0; + emb_func_int2.int2_fsm_lc = val.fsm_lc; + fsm_int2_a.int2_fsm1 = val.fsm1; + fsm_int2_a.int2_fsm2 = val.fsm2; + fsm_int2_a.int2_fsm3 = val.fsm3; + fsm_int2_a.int2_fsm4 = val.fsm4; + fsm_int2_a.int2_fsm5 = val.fsm5; + fsm_int2_a.int2_fsm6 = val.fsm6; + fsm_int2_a.int2_fsm7 = val.fsm7; + fsm_int2_a.int2_fsm8 = val.fsm8; + fsm_int2_b.int2_fsm9 = val.fsm9 ; + fsm_int2_b.int2_fsm10 = val.fsm10; + fsm_int2_b.int2_fsm11 = val.fsm11; + fsm_int2_b.int2_fsm12 = val.fsm12; + fsm_int2_b.int2_fsm13 = val.fsm13; + fsm_int2_b.int2_fsm14 = val.fsm14; + fsm_int2_b.int2_fsm15 = val.fsm15; + fsm_int2_b.int2_fsm16 = val.fsm16; + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL4_C, (uint8_t *)&ctrl4_c, 1); + + if (ret == 0) + { + if ((val.drdy_temp | val.timestamp) != PROPERTY_DISABLE) + { + ctrl4_c.int2_on_int1 = PROPERTY_DISABLE; + } + + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL4_C, (uint8_t *)&ctrl4_c, 1); + } + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + } + + if (ret == 0) + { + ret = lsm6dso_write_reg(ctx, LSM6DSO_EMB_FUNC_INT2, + (uint8_t *)&emb_func_int2, 1); + } + + if (ret == 0) + { + ret = lsm6dso_write_reg(ctx, LSM6DSO_FSM_INT2_A, + (uint8_t *)&fsm_int2_a, 1); + } + + if (ret == 0) + { + ret = lsm6dso_write_reg(ctx, LSM6DSO_FSM_INT2_B, + (uint8_t *)&fsm_int2_b, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + if (ret == 0) + { + if ((emb_func_int2.int2_fsm_lc + | emb_func_int2.int2_sig_mot + | emb_func_int2.int2_step_detector + | emb_func_int2.int2_tilt + | fsm_int2_a.int2_fsm1 + | fsm_int2_a.int2_fsm2 + | fsm_int2_a.int2_fsm3 + | fsm_int2_a.int2_fsm4 + | fsm_int2_a.int2_fsm5 + | fsm_int2_a.int2_fsm6 + | fsm_int2_a.int2_fsm7 + | fsm_int2_a.int2_fsm8 + | fsm_int2_b.int2_fsm9 + | fsm_int2_b.int2_fsm10 + | fsm_int2_b.int2_fsm11 + | fsm_int2_b.int2_fsm12 + | fsm_int2_b.int2_fsm13 + | fsm_int2_b.int2_fsm14 + | fsm_int2_b.int2_fsm15 + | fsm_int2_b.int2_fsm16) != PROPERTY_DISABLE) + { + md2_cfg.int2_emb_func = PROPERTY_ENABLE; + } + + else + { + md2_cfg.int2_emb_func = PROPERTY_DISABLE; + } + + ret = lsm6dso_write_reg(ctx, LSM6DSO_INT2_CTRL, + (uint8_t *)&int2_ctrl, 1); + } + + if (ret == 0) + { + ret = lsm6dso_write_reg(ctx, LSM6DSO_MD2_CFG, (uint8_t *)&md2_cfg, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_TAP_CFG2, (uint8_t *) &tap_cfg2, 1); + } + + if (ret == 0) + { + ret = lsm6dso_pin_int1_route_get(ctx, &pin_int1_route); + } + + if (ret == 0) + { + if ((val.fifo_bdr + | val.drdy_g + | val.drdy_temp + | val.drdy_xl + | val.fifo_full + | val.fifo_ovr + | val.fifo_th + | val.six_d + | val.double_tap + | val.free_fall + | val.wake_up + | val.single_tap + | val.sleep_change + | pin_int1_route.den_flag + | pin_int1_route.boot + | pin_int1_route.fifo_bdr + | pin_int1_route.drdy_g + | pin_int1_route.drdy_xl + | pin_int1_route.fifo_full + | pin_int1_route.fifo_ovr + | pin_int1_route.fifo_th + | pin_int1_route.six_d + | pin_int1_route.double_tap + | pin_int1_route.free_fall + | pin_int1_route.wake_up + | pin_int1_route.single_tap + | pin_int1_route.sleep_change) != PROPERTY_DISABLE) + { + tap_cfg2.interrupts_enable = PROPERTY_ENABLE; + } + + else + { + tap_cfg2.interrupts_enable = PROPERTY_DISABLE; + } + + ret = lsm6dso_write_reg(ctx, LSM6DSO_TAP_CFG2, (uint8_t *) &tap_cfg2, 1); + } + } + + return ret; +} + +/** + * @brief Route interrupt signals on int2 pin.[get] + * + * @param ctx communication interface handler. Use NULL to ignore + * this interface.(ptr) + * @param aux_ctx auxiliary communication interface handler. Use NULL + * to ignore this interface.(ptr) + * @param val the signals that are routed on int2 pin.(ptr) + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_pin_int2_route_get(stmdev_ctx_t *ctx, + stmdev_ctx_t *aux_ctx, + lsm6dso_pin_int2_route_t *val) +{ + lsm6dso_emb_func_int2_t emb_func_int2; + lsm6dso_fsm_int2_a_t fsm_int2_a; + lsm6dso_fsm_int2_b_t fsm_int2_b; + lsm6dso_int2_ctrl_t int2_ctrl; + lsm6dso_md2_cfg_t md2_cfg; + lsm6dso_ctrl4_c_t ctrl4_c; + lsm6dso_int_ois_t int_ois; + int32_t ret; + ret = 0; + + if (aux_ctx != NULL) + { + ret = lsm6dso_read_reg(aux_ctx, LSM6DSO_INT_OIS, + (uint8_t *)&int_ois, 1); + val->drdy_ois = int_ois.int2_drdy_ois; + } + + if (ctx != NULL) + { + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_EMB_FUNC_INT2, + (uint8_t *)&emb_func_int2, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_FSM_INT2_A, + (uint8_t *)&fsm_int2_a, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_FSM_INT2_B, + (uint8_t *)&fsm_int2_b, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_INT2_CTRL, + (uint8_t *)&int2_ctrl, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_MD2_CFG, + (uint8_t *)&md2_cfg, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL4_C, (uint8_t *)&ctrl4_c, 1); + } + + if (ctrl4_c.int2_on_int1 == PROPERTY_DISABLE) + { + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_INT2_CTRL, + (uint8_t *)&int2_ctrl, 1); + val->drdy_temp = int2_ctrl.int2_drdy_temp; + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_MD2_CFG, (uint8_t *)&md2_cfg, 1); + val->timestamp = md2_cfg.int2_timestamp; + } + } + + else + { + val->drdy_temp = PROPERTY_DISABLE; + val->timestamp = PROPERTY_DISABLE; + } + + val->drdy_xl = int2_ctrl.int2_drdy_xl; + val->drdy_g = int2_ctrl.int2_drdy_g; + val->drdy_temp = int2_ctrl.int2_drdy_temp; + val->fifo_th = int2_ctrl.int2_fifo_th; + val->fifo_ovr = int2_ctrl.int2_fifo_ovr; + val->fifo_full = int2_ctrl.int2_fifo_full; + val->fifo_bdr = int2_ctrl.int2_cnt_bdr; + val->timestamp = md2_cfg.int2_timestamp; + val->six_d = md2_cfg.int2_6d; + val->double_tap = md2_cfg.int2_double_tap; + val->free_fall = md2_cfg.int2_ff; + val->wake_up = md2_cfg.int2_wu; + val->single_tap = md2_cfg.int2_single_tap; + val->sleep_change = md2_cfg.int2_sleep_change; + val->step_detector = emb_func_int2. int2_step_detector; + val->tilt = emb_func_int2.int2_tilt; + val->fsm_lc = emb_func_int2.int2_fsm_lc; + val->fsm1 = fsm_int2_a.int2_fsm1; + val->fsm2 = fsm_int2_a.int2_fsm2; + val->fsm3 = fsm_int2_a.int2_fsm3; + val->fsm4 = fsm_int2_a.int2_fsm4; + val->fsm5 = fsm_int2_a.int2_fsm5; + val->fsm6 = fsm_int2_a.int2_fsm6; + val->fsm7 = fsm_int2_a.int2_fsm7; + val->fsm8 = fsm_int2_a.int2_fsm8; + val->fsm9 = fsm_int2_b.int2_fsm9; + val->fsm10 = fsm_int2_b.int2_fsm10; + val->fsm11 = fsm_int2_b.int2_fsm11; + val->fsm12 = fsm_int2_b.int2_fsm12; + val->fsm13 = fsm_int2_b.int2_fsm13; + val->fsm14 = fsm_int2_b.int2_fsm14; + val->fsm15 = fsm_int2_b.int2_fsm15; + val->fsm16 = fsm_int2_b.int2_fsm16; + } + + return ret; +} + +/** + * @brief Get the status of all the interrupt sources.[get] + * + * @param ctx communication interface handler.(ptr) + * @param val the status of all the interrupt sources.(ptr) + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_all_sources_get(stmdev_ctx_t *ctx, + lsm6dso_all_sources_t *val) +{ + lsm6dso_emb_func_status_mainpage_t emb_func_status_mainpage; + lsm6dso_status_master_mainpage_t status_master_mainpage; + lsm6dso_fsm_status_a_mainpage_t fsm_status_a_mainpage; + lsm6dso_fsm_status_b_mainpage_t fsm_status_b_mainpage; + lsm6dso_fifo_status1_t fifo_status1; + lsm6dso_fifo_status2_t fifo_status2; + lsm6dso_all_int_src_t all_int_src; + lsm6dso_wake_up_src_t wake_up_src; + lsm6dso_status_reg_t status_reg; + lsm6dso_tap_src_t tap_src; + lsm6dso_d6d_src_t d6d_src; + uint8_t reg[5]; + int32_t ret; + ret = lsm6dso_read_reg(ctx, LSM6DSO_ALL_INT_SRC, reg, 5); + + if (ret == 0) + { + bytecpy((uint8_t *)&all_int_src, ®[0]); + bytecpy((uint8_t *)&wake_up_src, ®[1]); + bytecpy((uint8_t *)&tap_src, ®[2]); + bytecpy((uint8_t *)&d6d_src, ®[3]); + bytecpy((uint8_t *)&status_reg, ®[4]); + val->timestamp = all_int_src.timestamp_endcount; + val->wake_up_z = wake_up_src.z_wu; + val->wake_up_y = wake_up_src.y_wu; + val->wake_up_x = wake_up_src.x_wu; + val->wake_up = wake_up_src.wu_ia; + val->sleep_state = wake_up_src.sleep_state; + val->free_fall = wake_up_src.ff_ia; + val->sleep_change = wake_up_src.sleep_change_ia; + val->tap_x = tap_src.x_tap; + val->tap_y = tap_src.y_tap; + val->tap_z = tap_src.z_tap; + val->tap_sign = tap_src.tap_sign; + val->double_tap = tap_src.double_tap; + val->single_tap = tap_src.single_tap; + val->six_d_xl = d6d_src.xl; + val->six_d_xh = d6d_src.xh; + val->six_d_yl = d6d_src.yl; + val->six_d_yh = d6d_src.yh; + val->six_d_zl = d6d_src.zl; + val->six_d_zh = d6d_src.zh; + val->six_d = d6d_src.d6d_ia; + val->den_flag = d6d_src.den_drdy; + val->drdy_xl = status_reg.xlda; + val->drdy_g = status_reg.gda; + val->drdy_temp = status_reg.tda; + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_EMB_FUNC_STATUS_MAINPAGE, reg, 3); + } + + if (ret == 0) + { + bytecpy((uint8_t *)&emb_func_status_mainpage, ®[0]); + bytecpy((uint8_t *)&fsm_status_a_mainpage, ®[1]); + bytecpy((uint8_t *)&fsm_status_b_mainpage, ®[2]); + val->step_detector = emb_func_status_mainpage.is_step_det; + val->tilt = emb_func_status_mainpage.is_tilt; + val->sig_mot = emb_func_status_mainpage.is_sigmot; + val->fsm_lc = emb_func_status_mainpage.is_fsm_lc; + val->fsm1 = fsm_status_a_mainpage.is_fsm1; + val->fsm2 = fsm_status_a_mainpage.is_fsm2; + val->fsm3 = fsm_status_a_mainpage.is_fsm3; + val->fsm4 = fsm_status_a_mainpage.is_fsm4; + val->fsm5 = fsm_status_a_mainpage.is_fsm5; + val->fsm6 = fsm_status_a_mainpage.is_fsm6; + val->fsm7 = fsm_status_a_mainpage.is_fsm7; + val->fsm8 = fsm_status_a_mainpage.is_fsm8; + val->fsm9 = fsm_status_b_mainpage.is_fsm9; + val->fsm10 = fsm_status_b_mainpage.is_fsm10; + val->fsm11 = fsm_status_b_mainpage.is_fsm11; + val->fsm12 = fsm_status_b_mainpage.is_fsm12; + val->fsm13 = fsm_status_b_mainpage.is_fsm13; + val->fsm14 = fsm_status_b_mainpage.is_fsm14; + val->fsm15 = fsm_status_b_mainpage.is_fsm15; + val->fsm16 = fsm_status_b_mainpage.is_fsm16; + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_STATUS_MASTER_MAINPAGE, reg, 3); + } + + if (ret == 0) + { + bytecpy((uint8_t *)&status_master_mainpage, ®[0]); + bytecpy((uint8_t *)&fifo_status1, ®[1]); + bytecpy((uint8_t *)&fifo_status2, ®[2]); + val->sh_endop = status_master_mainpage.sens_hub_endop; + val->sh_slave0_nack = status_master_mainpage.slave0_nack; + val->sh_slave1_nack = status_master_mainpage.slave1_nack; + val->sh_slave2_nack = status_master_mainpage.slave2_nack; + val->sh_slave3_nack = status_master_mainpage.slave3_nack; + val->sh_wr_once = status_master_mainpage.wr_once_done; + val->fifo_diff = (256U * fifo_status2.diff_fifo) + + fifo_status1.diff_fifo; + val->fifo_ovr_latched = fifo_status2.over_run_latched; + val->fifo_bdr = fifo_status2.counter_bdr_ia; + val->fifo_full = fifo_status2.fifo_full_ia; + val->fifo_ovr = fifo_status2.fifo_ovr_ia; + val->fifo_th = fifo_status2.fifo_wtm_ia; + } + + return ret; +} + +/** + * @brief Sensor conversion parameters selection.[set] + * + * @param ctx communication interface handler. Use NULL to ignore + * this interface.(ptr) + * @param aux_ctx auxiliary communication interface handler. Use NULL + * to ignore this interface.(ptr) + * @param val set the sensor conversion parameters by checking + * the constraints of the device.(ptr) + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_mode_set(stmdev_ctx_t *ctx, stmdev_ctx_t *aux_ctx, + lsm6dso_md_t *val) +{ + lsm6dso_func_cfg_access_t func_cfg_access; + lsm6dso_ctrl1_ois_t ctrl1_ois; + lsm6dso_ctrl2_ois_t ctrl2_ois; + lsm6dso_ctrl3_ois_t ctrl3_ois; + lsm6dso_ctrl1_xl_t ctrl1_xl; + lsm6dso_ctrl8_xl_t ctrl8_xl; + lsm6dso_ctrl2_g_t ctrl2_g; + lsm6dso_ctrl3_c_t ctrl3_c; + lsm6dso_ctrl4_c_t ctrl4_c; + lsm6dso_ctrl5_c_t ctrl5_c; + lsm6dso_ctrl6_c_t ctrl6_c; + lsm6dso_ctrl7_g_t ctrl7_g; + uint8_t xl_hm_mode; + uint8_t g_hm_mode; + uint8_t xl_ulp_en; + uint8_t odr_gy; + uint8_t odr_xl; + uint8_t reg[8]; + int32_t ret; + + ret = 0; + /* FIXME: Remove warnings with STM32CubeIDE */ + ctrl3_c.not_used_01 = 0; + ctrl4_c.not_used_01 = 0; + ctrl5_c.xl_ulp_en = 0; + /* reading input configuration */ + xl_hm_mode = ((uint8_t)val->ui.xl.odr & 0x10U) >> 4; + xl_ulp_en = ((uint8_t)val->ui.xl.odr & 0x20U) >> 5; + odr_xl = (uint8_t)val->ui.xl.odr & 0x0FU; + + /* if enable xl ultra low power mode disable gy and OIS chain */ + if (xl_ulp_en == PROPERTY_ENABLE) + { + val->ois.xl.odr = LSM6DSO_XL_OIS_OFF; + val->ois.gy.odr = LSM6DSO_GY_OIS_OFF; + val->ui.gy.odr = LSM6DSO_GY_UI_OFF; + } + + /* if OIS xl is enabled also gyro OIS is enabled */ + if (val->ois.xl.odr == LSM6DSO_XL_OIS_6667Hz_HP) + { + val->ois.gy.odr = LSM6DSO_GY_OIS_6667Hz_HP; + } + + g_hm_mode = ((uint8_t)val->ui.gy.odr & 0x10U) >> 4; + odr_gy = (uint8_t)val->ui.gy.odr & 0x0FU; + + /* reading registers to be configured */ + if (ctx != NULL) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL1_XL, reg, 8); + bytecpy((uint8_t *)&ctrl1_xl, ®[0]); + bytecpy((uint8_t *)&ctrl2_g, ®[1]); + bytecpy((uint8_t *)&ctrl3_c, ®[2]); + bytecpy((uint8_t *)&ctrl4_c, ®[3]); + bytecpy((uint8_t *)&ctrl5_c, ®[4]); + bytecpy((uint8_t *)&ctrl6_c, ®[5]); + bytecpy((uint8_t *)&ctrl7_g, ®[6]); + bytecpy((uint8_t *)&ctrl8_xl, ®[7]); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_FUNC_CFG_ACCESS, + (uint8_t *)&func_cfg_access, 1); + } + + /* if toggle xl ultra low power mode, turn off xl before reconfigure */ + if (ctrl5_c.xl_ulp_en != xl_ulp_en) + { + ctrl1_xl.odr_xl = (uint8_t) 0x00U; + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL1_XL, + (uint8_t *)&ctrl1_xl, 1); + } + } + + /* reading OIS registers to be configured */ + if (aux_ctx != NULL) + { + if (ret == 0) + { + ret = lsm6dso_read_reg(aux_ctx, LSM6DSO_CTRL1_OIS, reg, 3); + } + + bytecpy((uint8_t *)&ctrl1_ois, ®[0]); + bytecpy((uint8_t *)&ctrl2_ois, ®[1]); + bytecpy((uint8_t *)&ctrl3_ois, ®[2]); + } + + else + { + if (ctx != NULL) + { + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL1_OIS, reg, 3); + } + + bytecpy((uint8_t *)&ctrl1_ois, ®[0]); + bytecpy((uint8_t *)&ctrl2_ois, ®[1]); + bytecpy((uint8_t *)&ctrl3_ois, ®[2]); + } + } + + /* Check the Finite State Machine data rate constraints */ + if (val->fsm.sens != LSM6DSO_FSM_DISABLE) + { + switch (val->fsm.odr) + { + case LSM6DSO_FSM_12Hz5: + if ((val->fsm.sens != LSM6DSO_FSM_GY) && (odr_xl == 0x00U)) + { + odr_xl = 0x01U; + } + + if ((val->fsm.sens != LSM6DSO_FSM_XL) && (odr_gy == 0x00U)) + { + xl_ulp_en = PROPERTY_DISABLE; + odr_gy = 0x01U; + } + + break; + + case LSM6DSO_FSM_26Hz: + if ((val->fsm.sens != LSM6DSO_FSM_GY) && (odr_xl < 0x02U)) + { + odr_xl = 0x02U; + } + + if ((val->fsm.sens != LSM6DSO_FSM_XL) && (odr_gy < 0x02U)) + { + xl_ulp_en = PROPERTY_DISABLE; + odr_gy = 0x02U; + } + + break; + + case LSM6DSO_FSM_52Hz: + if ((val->fsm.sens != LSM6DSO_FSM_GY) && (odr_xl < 0x03U)) + { + odr_xl = 0x03U; + } + + if ((val->fsm.sens != LSM6DSO_FSM_XL) && (odr_gy < 0x03U)) + { + xl_ulp_en = PROPERTY_DISABLE; + odr_gy = 0x03U; + } + + break; + + case LSM6DSO_FSM_104Hz: + if ((val->fsm.sens != LSM6DSO_FSM_GY) && (odr_xl < 0x04U)) + { + odr_xl = 0x04U; + } + + if ((val->fsm.sens != LSM6DSO_FSM_XL) && (odr_gy < 0x04U)) + { + xl_ulp_en = PROPERTY_DISABLE; + odr_gy = 0x04U; + } + + break; + + default: + odr_xl = 0x00U; + odr_gy = 0x00U; + break; + } + } + + /* Updating the accelerometer data rate configuration */ + switch ((ctrl5_c.xl_ulp_en << 5) | (ctrl6_c.xl_hm_mode << 4) | + ctrl1_xl.odr_xl) + { + case LSM6DSO_XL_UI_OFF: + val->ui.xl.odr = LSM6DSO_XL_UI_OFF; + break; + + case LSM6DSO_XL_UI_12Hz5_HP: + val->ui.xl.odr = LSM6DSO_XL_UI_12Hz5_HP; + break; + + case LSM6DSO_XL_UI_26Hz_HP: + val->ui.xl.odr = LSM6DSO_XL_UI_26Hz_HP; + break; + + case LSM6DSO_XL_UI_52Hz_HP: + val->ui.xl.odr = LSM6DSO_XL_UI_52Hz_HP; + break; + + case LSM6DSO_XL_UI_104Hz_HP: + val->ui.xl.odr = LSM6DSO_XL_UI_104Hz_HP; + break; + + case LSM6DSO_XL_UI_208Hz_HP: + val->ui.xl.odr = LSM6DSO_XL_UI_208Hz_HP; + break; + + case LSM6DSO_XL_UI_416Hz_HP: + val->ui.xl.odr = LSM6DSO_XL_UI_416Hz_HP; + break; + + case LSM6DSO_XL_UI_833Hz_HP: + val->ui.xl.odr = LSM6DSO_XL_UI_833Hz_HP; + break; + + case LSM6DSO_XL_UI_1667Hz_HP: + val->ui.xl.odr = LSM6DSO_XL_UI_1667Hz_HP; + break; + + case LSM6DSO_XL_UI_3333Hz_HP: + val->ui.xl.odr = LSM6DSO_XL_UI_3333Hz_HP; + break; + + case LSM6DSO_XL_UI_6667Hz_HP: + val->ui.xl.odr = LSM6DSO_XL_UI_6667Hz_HP; + break; + + case LSM6DSO_XL_UI_1Hz6_LP: + val->ui.xl.odr = LSM6DSO_XL_UI_1Hz6_LP; + break; + + case LSM6DSO_XL_UI_12Hz5_LP: + val->ui.xl.odr = LSM6DSO_XL_UI_12Hz5_LP; + break; + + case LSM6DSO_XL_UI_26Hz_LP: + val->ui.xl.odr = LSM6DSO_XL_UI_26Hz_LP; + break; + + case LSM6DSO_XL_UI_52Hz_LP: + val->ui.xl.odr = LSM6DSO_XL_UI_52Hz_LP; + break; + + case LSM6DSO_XL_UI_104Hz_NM: + val->ui.xl.odr = LSM6DSO_XL_UI_104Hz_NM; + break; + + case LSM6DSO_XL_UI_208Hz_NM: + val->ui.xl.odr = LSM6DSO_XL_UI_208Hz_NM; + break; + + case LSM6DSO_XL_UI_1Hz6_ULP: + val->ui.xl.odr = LSM6DSO_XL_UI_1Hz6_ULP; + break; + + case LSM6DSO_XL_UI_12Hz5_ULP: + val->ui.xl.odr = LSM6DSO_XL_UI_12Hz5_ULP; + break; + + case LSM6DSO_XL_UI_26Hz_ULP: + val->ui.xl.odr = LSM6DSO_XL_UI_26Hz_ULP; + break; + + case LSM6DSO_XL_UI_52Hz_ULP: + val->ui.xl.odr = LSM6DSO_XL_UI_52Hz_ULP; + break; + + case LSM6DSO_XL_UI_104Hz_ULP: + val->ui.xl.odr = LSM6DSO_XL_UI_104Hz_ULP; + break; + + case LSM6DSO_XL_UI_208Hz_ULP: + val->ui.xl.odr = LSM6DSO_XL_UI_208Hz_ULP; + break; + + default: + val->ui.xl.odr = LSM6DSO_XL_UI_OFF; + break; + } + + /* Updating the accelerometer data rate configuration */ + switch ((ctrl7_g.g_hm_mode << 4) | ctrl2_g.odr_g) + { + case LSM6DSO_GY_UI_OFF: + val->ui.gy.odr = LSM6DSO_GY_UI_OFF; + break; + + case LSM6DSO_GY_UI_12Hz5_LP: + val->ui.gy.odr = LSM6DSO_GY_UI_12Hz5_LP; + break; + + case LSM6DSO_GY_UI_12Hz5_HP: + val->ui.gy.odr = LSM6DSO_GY_UI_12Hz5_HP; + break; + + case LSM6DSO_GY_UI_26Hz_LP: + val->ui.gy.odr = LSM6DSO_GY_UI_26Hz_LP; + break; + + case LSM6DSO_GY_UI_26Hz_HP: + val->ui.gy.odr = LSM6DSO_GY_UI_26Hz_HP; + break; + + case LSM6DSO_GY_UI_52Hz_LP: + val->ui.gy.odr = LSM6DSO_GY_UI_52Hz_LP; + break; + + case LSM6DSO_GY_UI_52Hz_HP: + val->ui.gy.odr = LSM6DSO_GY_UI_52Hz_HP; + break; + + case LSM6DSO_GY_UI_104Hz_NM: + val->ui.gy.odr = LSM6DSO_GY_UI_104Hz_NM; + break; + + case LSM6DSO_GY_UI_104Hz_HP: + val->ui.gy.odr = LSM6DSO_GY_UI_104Hz_HP; + break; + + case LSM6DSO_GY_UI_208Hz_NM: + val->ui.gy.odr = LSM6DSO_GY_UI_208Hz_NM; + break; + + case LSM6DSO_GY_UI_208Hz_HP: + val->ui.gy.odr = LSM6DSO_GY_UI_208Hz_HP; + break; + + case LSM6DSO_GY_UI_416Hz_HP: + val->ui.gy.odr = LSM6DSO_GY_UI_416Hz_HP; + break; + + case LSM6DSO_GY_UI_833Hz_HP: + val->ui.gy.odr = LSM6DSO_GY_UI_833Hz_HP; + break; + + case LSM6DSO_GY_UI_1667Hz_HP: + val->ui.gy.odr = LSM6DSO_GY_UI_1667Hz_HP; + break; + + case LSM6DSO_GY_UI_3333Hz_HP: + val->ui.gy.odr = LSM6DSO_GY_UI_3333Hz_HP; + break; + + case LSM6DSO_GY_UI_6667Hz_HP: + val->ui.gy.odr = LSM6DSO_GY_UI_6667Hz_HP; + break; + + default: + val->ui.gy.odr = LSM6DSO_GY_UI_OFF; + break; + } + + /* Check accelerometer full scale constraints */ + /* Full scale of 16g must be the same for UI and OIS */ + if ((val->ui.xl.fs == LSM6DSO_XL_UI_16g) || + (val->ois.xl.fs == LSM6DSO_XL_OIS_16g)) + { + val->ui.xl.fs = LSM6DSO_XL_UI_16g; + val->ois.xl.fs = LSM6DSO_XL_OIS_16g; + } + + /* prapare new configuration */ + + /* Full scale of 16g must be the same for UI and OIS */ + if (val->ui.xl.fs == LSM6DSO_XL_UI_16g) + { + ctrl8_xl.xl_fs_mode = PROPERTY_DISABLE; + } + + else + { + ctrl8_xl.xl_fs_mode = PROPERTY_ENABLE; + } + + /* OIS new configuration */ + ctrl7_g.ois_on_en = val->ois.ctrl_md & 0x01U; + + switch (val->ois.ctrl_md) + { + case LSM6DSO_OIS_ONLY_AUX: + ctrl1_ois.fs_g_ois = (uint8_t)val->ois.gy.fs; + ctrl1_ois.ois_en_spi2 = (uint8_t)val->ois.gy.odr | + (uint8_t)val->ois.xl.odr; + ctrl1_ois.mode4_en = (uint8_t) val->ois.xl.odr; + ctrl3_ois.fs_xl_ois = (uint8_t)val->ois.xl.fs; + break; + + case LSM6DSO_OIS_MIXED: + ctrl1_ois.fs_g_ois = (uint8_t)val->ois.gy.fs; + ctrl7_g.ois_on = (uint8_t)val->ois.gy.odr | (uint8_t)val->ois.xl.odr; + ctrl1_ois.mode4_en = (uint8_t) val->ois.xl.odr; + ctrl3_ois.fs_xl_ois = (uint8_t)val->ois.xl.fs; + break; + + default: + ctrl1_ois.fs_g_ois = (uint8_t)val->ois.gy.fs; + ctrl1_ois.ois_en_spi2 = (uint8_t)val->ois.gy.odr | + (uint8_t)val->ois.xl.odr; + ctrl1_ois.mode4_en = (uint8_t) val->ois.xl.odr; + ctrl3_ois.fs_xl_ois = (uint8_t)val->ois.xl.fs; + break; + } + + /* UI new configuration */ + ctrl1_xl.odr_xl = odr_xl; + ctrl1_xl.fs_xl = (uint8_t)val->ui.xl.fs; + ctrl5_c.xl_ulp_en = xl_ulp_en; + ctrl6_c.xl_hm_mode = xl_hm_mode; + ctrl7_g.g_hm_mode = g_hm_mode; + ctrl2_g.odr_g = odr_gy; + ctrl2_g.fs_g = (uint8_t) val->ui.gy.fs; + + /* writing checked configuration */ + if (ctx != NULL) + { + bytecpy(®[0], (uint8_t *)&ctrl1_xl); + bytecpy(®[1], (uint8_t *)&ctrl2_g); + bytecpy(®[2], (uint8_t *)&ctrl3_c); + bytecpy(®[3], (uint8_t *)&ctrl4_c); + bytecpy(®[4], (uint8_t *)&ctrl5_c); + bytecpy(®[5], (uint8_t *)&ctrl6_c); + bytecpy(®[6], (uint8_t *)&ctrl7_g); + bytecpy(®[7], (uint8_t *)&ctrl8_xl); + + if (ret == 0) + { + ret = lsm6dso_write_reg(ctx, LSM6DSO_CTRL1_XL, (uint8_t *)®, 8); + } + + if (ret == 0) + { + ret = lsm6dso_write_reg(ctx, LSM6DSO_FUNC_CFG_ACCESS, + (uint8_t *)&func_cfg_access, 1); + } + } + + /* writing OIS checked configuration */ + if (aux_ctx != NULL) + { + bytecpy(®[0], (uint8_t *)&ctrl1_ois); + bytecpy(®[1], (uint8_t *)&ctrl2_ois); + bytecpy(®[2], (uint8_t *)&ctrl3_ois); + + if (ret == 0) + { + ret = lsm6dso_write_reg(aux_ctx, LSM6DSO_CTRL1_OIS, reg, 3); + } + } + + return ret; +} + +/** + * @brief Sensor conversion parameters selection.[get] + * + * @param ctx communication interface handler. Use NULL to ignore + * this interface.(ptr) + * @param aux_ctx auxiliary communication interface handler. Use NULL + * to ignore this interface.(ptr) + * @param val get the sensor conversion parameters.(ptr) + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_mode_get(stmdev_ctx_t *ctx, stmdev_ctx_t *aux_ctx, + lsm6dso_md_t *val) +{ + lsm6dso_emb_func_odr_cfg_b_t emb_func_odr_cfg_b; + lsm6dso_func_cfg_access_t func_cfg_access; + lsm6dso_emb_func_en_b_t emb_func_en_b; + lsm6dso_fsm_enable_a_t fsm_enable_a; + lsm6dso_fsm_enable_b_t fsm_enable_b; + lsm6dso_ctrl1_ois_t ctrl1_ois; + lsm6dso_ctrl2_ois_t ctrl2_ois; + lsm6dso_ctrl3_ois_t ctrl3_ois; + lsm6dso_ctrl1_xl_t ctrl1_xl; + lsm6dso_ctrl2_g_t ctrl2_g; + lsm6dso_ctrl3_c_t ctrl3_c; + lsm6dso_ctrl4_c_t ctrl4_c; + lsm6dso_ctrl5_c_t ctrl5_c; + lsm6dso_ctrl6_c_t ctrl6_c; + lsm6dso_ctrl7_g_t ctrl7_g; + uint8_t reg[8]; + int32_t ret; + + ret = 0; + + /* reading the registers of the device */ + if (ctx != NULL) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL1_XL, reg, 7); + bytecpy((uint8_t *)&ctrl1_xl, ®[0]); + bytecpy((uint8_t *)&ctrl2_g, ®[1]); + bytecpy((uint8_t *)&ctrl3_c, ®[2]); + bytecpy((uint8_t *)&ctrl4_c, ®[3]); + bytecpy((uint8_t *)&ctrl5_c, ®[4]); + bytecpy((uint8_t *)&ctrl6_c, ®[5]); + bytecpy((uint8_t *)&ctrl7_g, ®[6]); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_FUNC_CFG_ACCESS, + (uint8_t *)&func_cfg_access, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_EMB_FUNC_ODR_CFG_B, reg, 1); + bytecpy((uint8_t *)&emb_func_odr_cfg_b, ®[0]); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_EMB_FUNC_EN_B, + (uint8_t *)&emb_func_en_b, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_FSM_ENABLE_A, reg, 2); + bytecpy((uint8_t *)&fsm_enable_a, ®[0]); + bytecpy((uint8_t *)&fsm_enable_b, ®[1]); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + } + + if (aux_ctx != NULL) + { + if (ret == 0) + { + ret = lsm6dso_read_reg(aux_ctx, LSM6DSO_CTRL1_OIS, reg, 3); + } + + bytecpy((uint8_t *)&ctrl1_ois, ®[0]); + bytecpy((uint8_t *)&ctrl2_ois, ®[1]); + bytecpy((uint8_t *)&ctrl3_ois, ®[2]); + } + + else + { + if (ctx != NULL) + { + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_CTRL1_OIS, reg, 3); + } + + bytecpy((uint8_t *)&ctrl1_ois, ®[0]); + bytecpy((uint8_t *)&ctrl2_ois, ®[1]); + bytecpy((uint8_t *)&ctrl3_ois, ®[2]); + } + } + + /* fill the input structure */ + + /* get accelerometer configuration */ + switch ((ctrl5_c.xl_ulp_en << 5) | (ctrl6_c.xl_hm_mode << 4) | + ctrl1_xl.odr_xl) + { + case LSM6DSO_XL_UI_OFF: + val->ui.xl.odr = LSM6DSO_XL_UI_OFF; + break; + + case LSM6DSO_XL_UI_12Hz5_HP: + val->ui.xl.odr = LSM6DSO_XL_UI_12Hz5_HP; + break; + + case LSM6DSO_XL_UI_26Hz_HP: + val->ui.xl.odr = LSM6DSO_XL_UI_26Hz_HP; + break; + + case LSM6DSO_XL_UI_52Hz_HP: + val->ui.xl.odr = LSM6DSO_XL_UI_52Hz_HP; + break; + + case LSM6DSO_XL_UI_104Hz_HP: + val->ui.xl.odr = LSM6DSO_XL_UI_104Hz_HP; + break; + + case LSM6DSO_XL_UI_208Hz_HP: + val->ui.xl.odr = LSM6DSO_XL_UI_208Hz_HP; + break; + + case LSM6DSO_XL_UI_416Hz_HP: + val->ui.xl.odr = LSM6DSO_XL_UI_416Hz_HP; + break; + + case LSM6DSO_XL_UI_833Hz_HP: + val->ui.xl.odr = LSM6DSO_XL_UI_833Hz_HP; + break; + + case LSM6DSO_XL_UI_1667Hz_HP: + val->ui.xl.odr = LSM6DSO_XL_UI_1667Hz_HP; + break; + + case LSM6DSO_XL_UI_3333Hz_HP: + val->ui.xl.odr = LSM6DSO_XL_UI_3333Hz_HP; + break; + + case LSM6DSO_XL_UI_6667Hz_HP: + val->ui.xl.odr = LSM6DSO_XL_UI_6667Hz_HP; + break; + + case LSM6DSO_XL_UI_1Hz6_LP: + val->ui.xl.odr = LSM6DSO_XL_UI_1Hz6_LP; + break; + + case LSM6DSO_XL_UI_12Hz5_LP: + val->ui.xl.odr = LSM6DSO_XL_UI_12Hz5_LP; + break; + + case LSM6DSO_XL_UI_26Hz_LP: + val->ui.xl.odr = LSM6DSO_XL_UI_26Hz_LP; + break; + + case LSM6DSO_XL_UI_52Hz_LP: + val->ui.xl.odr = LSM6DSO_XL_UI_52Hz_LP; + break; + + case LSM6DSO_XL_UI_104Hz_NM: + val->ui.xl.odr = LSM6DSO_XL_UI_104Hz_NM; + break; + + case LSM6DSO_XL_UI_208Hz_NM: + val->ui.xl.odr = LSM6DSO_XL_UI_208Hz_NM; + break; + + case LSM6DSO_XL_UI_1Hz6_ULP: + val->ui.xl.odr = LSM6DSO_XL_UI_1Hz6_ULP; + break; + + case LSM6DSO_XL_UI_12Hz5_ULP: + val->ui.xl.odr = LSM6DSO_XL_UI_12Hz5_ULP; + break; + + case LSM6DSO_XL_UI_26Hz_ULP: + val->ui.xl.odr = LSM6DSO_XL_UI_26Hz_ULP; + break; + + case LSM6DSO_XL_UI_52Hz_ULP: + val->ui.xl.odr = LSM6DSO_XL_UI_52Hz_ULP; + break; + + case LSM6DSO_XL_UI_104Hz_ULP: + val->ui.xl.odr = LSM6DSO_XL_UI_104Hz_ULP; + break; + + case LSM6DSO_XL_UI_208Hz_ULP: + val->ui.xl.odr = LSM6DSO_XL_UI_208Hz_ULP; + break; + + default: + val->ui.xl.odr = LSM6DSO_XL_UI_OFF; + break; + } + + switch (ctrl1_xl.fs_xl) + { + case LSM6DSO_XL_UI_2g: + val->ui.xl.fs = LSM6DSO_XL_UI_2g; + break; + + case LSM6DSO_XL_UI_4g: + val->ui.xl.fs = LSM6DSO_XL_UI_4g; + break; + + case LSM6DSO_XL_UI_8g: + val->ui.xl.fs = LSM6DSO_XL_UI_8g; + break; + + case LSM6DSO_XL_UI_16g: + val->ui.xl.fs = LSM6DSO_XL_UI_16g; + break; + + default: + val->ui.xl.fs = LSM6DSO_XL_UI_2g; + break; + } + + /* get gyroscope configuration */ + switch ((ctrl7_g.g_hm_mode << 4) | ctrl2_g.odr_g) + { + case LSM6DSO_GY_UI_OFF: + val->ui.gy.odr = LSM6DSO_GY_UI_OFF; + break; + + case LSM6DSO_GY_UI_12Hz5_LP: + val->ui.gy.odr = LSM6DSO_GY_UI_12Hz5_LP; + break; + + case LSM6DSO_GY_UI_12Hz5_HP: + val->ui.gy.odr = LSM6DSO_GY_UI_12Hz5_HP; + break; + + case LSM6DSO_GY_UI_26Hz_LP: + val->ui.gy.odr = LSM6DSO_GY_UI_26Hz_LP; + break; + + case LSM6DSO_GY_UI_26Hz_HP: + val->ui.gy.odr = LSM6DSO_GY_UI_26Hz_HP; + break; + + case LSM6DSO_GY_UI_52Hz_LP: + val->ui.gy.odr = LSM6DSO_GY_UI_52Hz_LP; + break; + + case LSM6DSO_GY_UI_52Hz_HP: + val->ui.gy.odr = LSM6DSO_GY_UI_52Hz_HP; + break; + + case LSM6DSO_GY_UI_104Hz_NM: + val->ui.gy.odr = LSM6DSO_GY_UI_104Hz_NM; + break; + + case LSM6DSO_GY_UI_104Hz_HP: + val->ui.gy.odr = LSM6DSO_GY_UI_104Hz_HP; + break; + + case LSM6DSO_GY_UI_208Hz_NM: + val->ui.gy.odr = LSM6DSO_GY_UI_208Hz_NM; + break; + + case LSM6DSO_GY_UI_208Hz_HP: + val->ui.gy.odr = LSM6DSO_GY_UI_208Hz_HP; + break; + + case LSM6DSO_GY_UI_416Hz_HP: + val->ui.gy.odr = LSM6DSO_GY_UI_416Hz_HP; + break; + + case LSM6DSO_GY_UI_833Hz_HP: + val->ui.gy.odr = LSM6DSO_GY_UI_833Hz_HP; + break; + + case LSM6DSO_GY_UI_1667Hz_HP: + val->ui.gy.odr = LSM6DSO_GY_UI_1667Hz_HP; + break; + + case LSM6DSO_GY_UI_3333Hz_HP: + val->ui.gy.odr = LSM6DSO_GY_UI_3333Hz_HP; + break; + + case LSM6DSO_GY_UI_6667Hz_HP: + val->ui.gy.odr = LSM6DSO_GY_UI_6667Hz_HP; + break; + + default: + val->ui.gy.odr = LSM6DSO_GY_UI_OFF; + break; + } + + switch (ctrl2_g.fs_g) + { + case LSM6DSO_GY_UI_125dps: + val->ui.gy.fs = LSM6DSO_GY_UI_125dps; + break; + + case LSM6DSO_GY_UI_250dps: + val->ui.gy.fs = LSM6DSO_GY_UI_250dps; + break; + + case LSM6DSO_GY_UI_500dps: + val->ui.gy.fs = LSM6DSO_GY_UI_500dps; + break; + + case LSM6DSO_GY_UI_1000dps: + val->ui.gy.fs = LSM6DSO_GY_UI_1000dps; + break; + + case LSM6DSO_GY_UI_2000dps: + val->ui.gy.fs = LSM6DSO_GY_UI_2000dps; + break; + + default: + val->ui.gy.fs = LSM6DSO_GY_UI_125dps; + break; + } + + /* get finite state machine configuration */ + if ((fsm_enable_a.fsm1_en | fsm_enable_a.fsm2_en | + fsm_enable_a.fsm3_en | + fsm_enable_a.fsm4_en | fsm_enable_a.fsm5_en | fsm_enable_a.fsm6_en | + fsm_enable_a.fsm7_en | fsm_enable_a.fsm8_en | fsm_enable_b.fsm9_en | + fsm_enable_b.fsm10_en | fsm_enable_b.fsm11_en | + fsm_enable_b.fsm12_en | fsm_enable_b.fsm13_en | + fsm_enable_b.fsm14_en | fsm_enable_b.fsm15_en | + fsm_enable_b.fsm16_en) == PROPERTY_ENABLE) + { + switch (emb_func_odr_cfg_b.fsm_odr) + { + case LSM6DSO_FSM_12Hz5: + val->fsm.odr = LSM6DSO_FSM_12Hz5; + break; + + case LSM6DSO_FSM_26Hz: + val->fsm.odr = LSM6DSO_FSM_26Hz; + break; + + case LSM6DSO_FSM_52Hz: + val->fsm.odr = LSM6DSO_FSM_52Hz; + break; + + case LSM6DSO_FSM_104Hz: + val->fsm.odr = LSM6DSO_FSM_104Hz; + break; + + default: + val->fsm.odr = LSM6DSO_FSM_12Hz5; + break; + } + + val->fsm.sens = LSM6DSO_FSM_XL_GY; + + if (val->ui.gy.odr == LSM6DSO_GY_UI_OFF) + { + val->fsm.sens = LSM6DSO_FSM_XL; + } + + if (val->ui.xl.odr == LSM6DSO_XL_UI_OFF) + { + val->fsm.sens = LSM6DSO_FSM_GY; + } + } + + else + { + val->fsm.sens = LSM6DSO_FSM_DISABLE; + } + + /* get ois configuration */ + + /* OIS configuration mode */ + switch (ctrl7_g.ois_on_en) + { + case LSM6DSO_OIS_ONLY_AUX: + switch (ctrl3_ois.fs_xl_ois) + { + case LSM6DSO_XL_OIS_2g: + val->ois.xl.fs = LSM6DSO_XL_OIS_2g; + break; + + case LSM6DSO_XL_OIS_4g: + val->ois.xl.fs = LSM6DSO_XL_OIS_4g; + break; + + case LSM6DSO_XL_OIS_8g: + val->ois.xl.fs = LSM6DSO_XL_OIS_8g; + break; + + case LSM6DSO_XL_OIS_16g: + val->ois.xl.fs = LSM6DSO_XL_OIS_16g; + break; + + default: + val->ois.xl.fs = LSM6DSO_XL_OIS_2g; + break; + } + + switch (ctrl1_ois.mode4_en) + { + case LSM6DSO_XL_OIS_OFF: + val->ois.xl.odr = LSM6DSO_XL_OIS_OFF; + break; + + case LSM6DSO_XL_OIS_6667Hz_HP: + val->ois.xl.odr = LSM6DSO_XL_OIS_6667Hz_HP; + break; + + default: + val->ois.xl.odr = LSM6DSO_XL_OIS_OFF; + break; + } + + switch (ctrl1_ois.fs_g_ois) + { + case LSM6DSO_GY_OIS_250dps: + val->ois.gy.fs = LSM6DSO_GY_OIS_250dps; + break; + + case LSM6DSO_GY_OIS_500dps: + val->ois.gy.fs = LSM6DSO_GY_OIS_500dps; + break; + + case LSM6DSO_GY_OIS_1000dps: + val->ois.gy.fs = LSM6DSO_GY_OIS_1000dps; + break; + + case LSM6DSO_GY_OIS_2000dps: + val->ois.gy.fs = LSM6DSO_GY_OIS_2000dps; + break; + + default: + val->ois.gy.fs = LSM6DSO_GY_OIS_250dps; + break; + } + + switch (ctrl1_ois.ois_en_spi2) + { + case LSM6DSO_GY_OIS_OFF: + val->ois.gy.odr = LSM6DSO_GY_OIS_OFF; + break; + + case LSM6DSO_GY_OIS_6667Hz_HP: + val->ois.gy.odr = LSM6DSO_GY_OIS_6667Hz_HP; + break; + + default: + val->ois.gy.odr = LSM6DSO_GY_OIS_OFF; + break; + } + + val->ois.ctrl_md = LSM6DSO_OIS_ONLY_AUX; + break; + + case LSM6DSO_OIS_MIXED: + switch (ctrl3_ois.fs_xl_ois) + { + case LSM6DSO_XL_OIS_2g: + val->ois.xl.fs = LSM6DSO_XL_OIS_2g; + break; + + case LSM6DSO_XL_OIS_4g: + val->ois.xl.fs = LSM6DSO_XL_OIS_4g; + break; + + case LSM6DSO_XL_OIS_8g: + val->ois.xl.fs = LSM6DSO_XL_OIS_8g; + break; + + case LSM6DSO_XL_OIS_16g: + val->ois.xl.fs = LSM6DSO_XL_OIS_16g; + break; + + default: + val->ois.xl.fs = LSM6DSO_XL_OIS_2g; + break; + } + + switch (ctrl1_ois.mode4_en) + { + case LSM6DSO_XL_OIS_OFF: + val->ois.xl.odr = LSM6DSO_XL_OIS_OFF; + break; + + case LSM6DSO_XL_OIS_6667Hz_HP: + val->ois.xl.odr = LSM6DSO_XL_OIS_6667Hz_HP; + break; + + default: + val->ois.xl.odr = LSM6DSO_XL_OIS_OFF; + break; + } + + switch (ctrl1_ois.fs_g_ois) + { + case LSM6DSO_GY_OIS_250dps: + val->ois.gy.fs = LSM6DSO_GY_OIS_250dps; + break; + + case LSM6DSO_GY_OIS_500dps: + val->ois.gy.fs = LSM6DSO_GY_OIS_500dps; + break; + + case LSM6DSO_GY_OIS_1000dps: + val->ois.gy.fs = LSM6DSO_GY_OIS_1000dps; + break; + + case LSM6DSO_GY_OIS_2000dps: + val->ois.gy.fs = LSM6DSO_GY_OIS_2000dps; + break; + + default: + val->ois.gy.fs = LSM6DSO_GY_OIS_250dps; + break; + } + + switch (ctrl1_ois.ois_en_spi2) + { + case LSM6DSO_GY_OIS_OFF: + val->ois.gy.odr = LSM6DSO_GY_OIS_OFF; + break; + + case LSM6DSO_GY_OIS_6667Hz_HP: + val->ois.gy.odr = LSM6DSO_GY_OIS_6667Hz_HP; + break; + + default: + val->ois.gy.odr = LSM6DSO_GY_OIS_OFF; + break; + } + + val->ois.ctrl_md = LSM6DSO_OIS_MIXED; + break; + + default: + ctrl1_ois.fs_g_ois = (uint8_t)val->ois.gy.fs; + ctrl1_ois.ois_en_spi2 = (uint8_t)val->ois.gy.odr | + (uint8_t)val->ois.xl.odr; + ctrl1_ois.mode4_en = (uint8_t) val->ois.xl.odr; + ctrl3_ois.fs_xl_ois = (uint8_t)val->ois.xl.fs; + val->ois.ctrl_md = LSM6DSO_OIS_ONLY_AUX; + break; + } + + return ret; +} + +/** + * @brief Read data in engineering unit.[get] + * + * @param ctx communication interface handler.(ptr) + * @param md the sensor conversion parameters.(ptr) + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_data_get(stmdev_ctx_t *ctx, stmdev_ctx_t *aux_ctx, + lsm6dso_md_t *md, lsm6dso_data_t *data) +{ + uint8_t buff[14]; + int32_t ret; + + uint8_t i; + uint8_t j; + ret = 0; + + /* read data */ + if (ctx != NULL) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_OUT_TEMP_L, buff, 14); + } + + j = 0; + /* temperature conversion */ + data->ui.heat.raw = (int16_t)buff[j + 1U]; + data->ui.heat.raw = (((int16_t)data->ui.heat.raw * (int16_t)256) + + (int16_t)buff[j]); + j += 2U; + data->ui.heat.deg_c = lsm6dso_from_lsb_to_celsius(( + int16_t)data->ui.heat.raw); + + /* angular rate conversion */ + for (i = 0U; i < 3U; i++) + { + data->ui.gy.raw[i] = (int16_t)buff[j + 1U]; + data->ui.gy.raw[i] = (data->ui.gy.raw[i] * 256) + (int16_t) buff[j]; + j += 2U; + + switch (md->ui.gy.fs) + { + case LSM6DSO_GY_UI_250dps: + data->ui.gy.mdps[i] = lsm6dso_from_fs250_to_mdps(data->ui.gy.raw[i]); + break; + + case LSM6DSO_GY_UI_125dps: + data->ui.gy.mdps[i] = lsm6dso_from_fs125_to_mdps(data->ui.gy.raw[i]); + break; + + case LSM6DSO_GY_UI_500dps: + data->ui.gy.mdps[i] = lsm6dso_from_fs500_to_mdps(data->ui.gy.raw[i]); + break; + + case LSM6DSO_GY_UI_1000dps: + data->ui.gy.mdps[i] = lsm6dso_from_fs1000_to_mdps(data->ui.gy.raw[i]); + break; + + case LSM6DSO_GY_UI_2000dps: + data->ui.gy.mdps[i] = lsm6dso_from_fs2000_to_mdps(data->ui.gy.raw[i]); + break; + + default: + data->ui.gy.mdps[i] = 0.0f; + break; + } + } + + /* acceleration conversion */ + for (i = 0U; i < 3U; i++) + { + data->ui.xl.raw[i] = (int16_t)buff[j + 1U]; + data->ui.xl.raw[i] = (data->ui.xl.raw[i] * 256) + (int16_t) buff[j]; + j += 2U; + + switch (md->ui.xl.fs) + { + case LSM6DSO_XL_UI_2g: + data->ui.xl.mg[i] = lsm6dso_from_fs2_to_mg(data->ui.xl.raw[i]); + break; + + case LSM6DSO_XL_UI_4g: + data->ui.xl.mg[i] = lsm6dso_from_fs4_to_mg(data->ui.xl.raw[i]); + break; + + case LSM6DSO_XL_UI_8g: + data->ui.xl.mg[i] = lsm6dso_from_fs8_to_mg(data->ui.xl.raw[i]); + break; + + case LSM6DSO_XL_UI_16g: + data->ui.xl.mg[i] = lsm6dso_from_fs16_to_mg(data->ui.xl.raw[i]); + break; + + default: + data->ui.xl.mg[i] = 0.0f; + break; + } + } + + /* read data from ois chain */ + if (aux_ctx != NULL) + { + if (ret == 0) + { + ret = lsm6dso_read_reg(aux_ctx, LSM6DSO_OUTX_L_G, buff, 12); + } + } + + j = 0; + + /* ois angular rate conversion */ + for (i = 0U; i < 3U; i++) + { + data->ois.gy.raw[i] = (int16_t) buff[j + 1U]; + data->ois.gy.raw[i] = (data->ois.gy.raw[i] * 256) + (int16_t) buff[j]; + j += 2U; + + switch (md->ois.gy.fs) + { + case LSM6DSO_GY_UI_250dps: + data->ois.gy.mdps[i] = lsm6dso_from_fs250_to_mdps( + data->ois.gy.raw[i]); + break; + + case LSM6DSO_GY_UI_125dps: + data->ois.gy.mdps[i] = lsm6dso_from_fs125_to_mdps( + data->ois.gy.raw[i]); + break; + + case LSM6DSO_GY_UI_500dps: + data->ois.gy.mdps[i] = lsm6dso_from_fs500_to_mdps( + data->ois.gy.raw[i]); + break; + + case LSM6DSO_GY_UI_1000dps: + data->ois.gy.mdps[i] = lsm6dso_from_fs1000_to_mdps( + data->ois.gy.raw[i]); + break; + + case LSM6DSO_GY_UI_2000dps: + data->ois.gy.mdps[i] = lsm6dso_from_fs2000_to_mdps( + data->ois.gy.raw[i]); + break; + + default: + data->ois.gy.mdps[i] = 0.0f; + break; + } + } + + /* ois acceleration conversion */ + for (i = 0U; i < 3U; i++) + { + data->ois.xl.raw[i] = (int16_t) buff[j + 1U]; + data->ois.xl.raw[i] = (data->ois.xl.raw[i] * 256) + (int16_t) buff[j]; + j += 2U; + + switch (md->ois.xl.fs) + { + case LSM6DSO_XL_UI_2g: + data->ois.xl.mg[i] = lsm6dso_from_fs2_to_mg(data->ois.xl.raw[i]); + break; + + case LSM6DSO_XL_UI_4g: + data->ois.xl.mg[i] = lsm6dso_from_fs4_to_mg(data->ois.xl.raw[i]); + break; + + case LSM6DSO_XL_UI_8g: + data->ois.xl.mg[i] = lsm6dso_from_fs8_to_mg(data->ois.xl.raw[i]); + break; + + case LSM6DSO_XL_UI_16g: + data->ois.xl.mg[i] = lsm6dso_from_fs16_to_mg(data->ois.xl.raw[i]); + break; + + default: + data->ois.xl.mg[i] = 0.0f; + break; + } + } + + return ret; +} + +/** + * @brief Embedded functions.[set] + * + * @param ctx read / write interface definitions + * @param val change the values of registers + * EMB_FUNC_EN_A e EMB_FUNC_EN_B. + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_embedded_sens_set(stmdev_ctx_t *ctx, + lsm6dso_emb_sens_t *val) +{ + lsm6dso_emb_func_en_a_t emb_func_en_a; + lsm6dso_emb_func_en_b_t emb_func_en_b; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_EMB_FUNC_EN_A, + (uint8_t *)&emb_func_en_a, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_EMB_FUNC_EN_B, + (uint8_t *)&emb_func_en_b, 1); + emb_func_en_b.fsm_en = val->fsm; + emb_func_en_a.tilt_en = val->tilt; + emb_func_en_a.pedo_en = val->step; + emb_func_en_b.pedo_adv_en = val->step_adv; + emb_func_en_a.sign_motion_en = val->sig_mot; + emb_func_en_b.fifo_compr_en = val->fifo_compr; + } + + if (ret == 0) + { + ret = lsm6dso_write_reg(ctx, LSM6DSO_EMB_FUNC_EN_A, + (uint8_t *)&emb_func_en_a, 1); + } + + if (ret == 0) + { + ret = lsm6dso_write_reg(ctx, LSM6DSO_EMB_FUNC_EN_B, + (uint8_t *)&emb_func_en_b, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief Embedded functions.[get] + * + * @param ctx read / write interface definitions + * @param val get the values of registers + * EMB_FUNC_EN_A e EMB_FUNC_EN_B. + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_embedded_sens_get(stmdev_ctx_t *ctx, + lsm6dso_emb_sens_t *emb_sens) +{ + lsm6dso_emb_func_en_a_t emb_func_en_a; + lsm6dso_emb_func_en_b_t emb_func_en_b; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_EMB_FUNC_EN_A, + (uint8_t *)&emb_func_en_a, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_EMB_FUNC_EN_B, + (uint8_t *)&emb_func_en_b, 1); + emb_sens->fsm = emb_func_en_b.fsm_en; + emb_sens->tilt = emb_func_en_a.tilt_en; + emb_sens->step = emb_func_en_a.pedo_en; + emb_sens->step_adv = emb_func_en_b.pedo_adv_en; + emb_sens->sig_mot = emb_func_en_a.sign_motion_en; + emb_sens->fifo_compr = emb_func_en_b.fifo_compr_en; + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @brief turn off all embedded functions.[get] + * + * @param ctx read / write interface definitions + * @param val get the values of registers + * EMB_FUNC_EN_A e EMB_FUNC_EN_B. + * @retval interface status (MANDATORY: return 0 -> no Error) + * + */ +int32_t lsm6dso_embedded_sens_off(stmdev_ctx_t *ctx) +{ + lsm6dso_emb_func_en_a_t emb_func_en_a; + lsm6dso_emb_func_en_b_t emb_func_en_b; + int32_t ret; + + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_EMBEDDED_FUNC_BANK); + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_EMB_FUNC_EN_A, + (uint8_t *)&emb_func_en_a, 1); + } + + if (ret == 0) + { + ret = lsm6dso_read_reg(ctx, LSM6DSO_EMB_FUNC_EN_B, + (uint8_t *)&emb_func_en_b, 1); + emb_func_en_b.fsm_en = PROPERTY_DISABLE; + emb_func_en_a.tilt_en = PROPERTY_DISABLE; + emb_func_en_a.pedo_en = PROPERTY_DISABLE; + emb_func_en_b.pedo_adv_en = PROPERTY_DISABLE; + emb_func_en_a.sign_motion_en = PROPERTY_DISABLE; + emb_func_en_b.fifo_compr_en = PROPERTY_DISABLE; + } + + if (ret == 0) + { + ret = lsm6dso_write_reg(ctx, LSM6DSO_EMB_FUNC_EN_A, + (uint8_t *)&emb_func_en_a, 1); + } + + if (ret == 0) + { + ret = lsm6dso_write_reg(ctx, LSM6DSO_EMB_FUNC_EN_B, + (uint8_t *)&emb_func_en_b, 1); + } + + if (ret == 0) + { + ret = lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @} + * + */ diff --git a/airmouse/lib/lsm6dso-api/lsm6dso_reg.h b/airmouse/lib/lsm6dso-api/lsm6dso_reg.h new file mode 100644 index 00000000000..b72f6232748 --- /dev/null +++ b/airmouse/lib/lsm6dso-api/lsm6dso_reg.h @@ -0,0 +1,4486 @@ +/** + ****************************************************************************** + * @file lsm6dso_reg.h + * @author Sensors Software Solution Team + * @brief This file contains all the functions prototypes for the + * lsm6dso_reg.c driver. + ****************************************************************************** + * @attention + * + * Copyright (c) 2019 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef LSM6DSO_REGS_H +#define LSM6DSO_REGS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include +#include +#include + +/** @addtogroup LSM6DSO + * @{ + * + */ + +/** @defgroup Endianness definitions + * @{ + * + */ + +#ifndef DRV_BYTE_ORDER +#ifndef __BYTE_ORDER__ + +#define DRV_LITTLE_ENDIAN 1234 +#define DRV_BIG_ENDIAN 4321 + +/** if _BYTE_ORDER is not defined, choose the endianness of your architecture + * by uncommenting the define which fits your platform endianness + */ +//#define DRV_BYTE_ORDER DRV_BIG_ENDIAN +#define DRV_BYTE_ORDER DRV_LITTLE_ENDIAN + +#else /* defined __BYTE_ORDER__ */ + +#define DRV_LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__ +#define DRV_BIG_ENDIAN __ORDER_BIG_ENDIAN__ +#define DRV_BYTE_ORDER __BYTE_ORDER__ + +#endif /* __BYTE_ORDER__*/ +#endif /* DRV_BYTE_ORDER */ + +/** + * @} + * + */ + +/** @defgroup STMicroelectronics sensors common types + * @{ + * + */ + +#ifndef MEMS_SHARED_TYPES +#define MEMS_SHARED_TYPES + +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} bitwise_t; + +#define PROPERTY_DISABLE (0U) +#define PROPERTY_ENABLE (1U) + +/** @addtogroup Interfaces_Functions + * @brief This section provide a set of functions used to read and + * write a generic register of the device. + * MANDATORY: return 0 -> no Error. + * @{ + * + */ + +typedef int32_t (*stmdev_write_ptr)(void *, uint8_t, uint8_t *, uint16_t); +typedef int32_t (*stmdev_read_ptr)(void *, uint8_t, uint8_t *, uint16_t); +typedef void (*stmdev_mdelay_ptr)(uint32_t millisec); + +typedef struct +{ + /** Component mandatory fields **/ + stmdev_write_ptr write_reg; + stmdev_read_ptr read_reg; + /** Component optional fields **/ + stmdev_mdelay_ptr mdelay; + /** Customizable optional pointer **/ + void *handle; +} stmdev_ctx_t; + +#ifndef __weak +#define __weak __attribute__((weak)) +#endif /* __weak */ + +/* + * These are the basic platform dependent I/O routines to read + * and write device registers connected on a standard bus. + * The driver keeps offering a default implementation based on function + * pointers to read/write routines for backward compatibility. + * The __weak directive allows the final application to overwrite + * them with a custom implementation. + */ +int32_t lsm6dso_read_reg(stmdev_ctx_t *ctx, uint8_t reg, + uint8_t *data, + uint16_t len); +int32_t lsm6dso_write_reg(stmdev_ctx_t *ctx, uint8_t reg, + uint8_t *data, + uint16_t len); + +/** + * @} + * + */ + +#endif /* MEMS_SHARED_TYPES */ + +#ifndef MEMS_UCF_SHARED_TYPES +#define MEMS_UCF_SHARED_TYPES + +/** @defgroup Generic address-data structure definition + * @brief This structure is useful to load a predefined configuration + * of a sensor. + * You can create a sensor configuration by your own or using + * Unico / Unicleo tools available on STMicroelectronics + * web site. + * + * @{ + * + */ + +typedef struct +{ + uint8_t address; + uint8_t data; +} ucf_line_t; + +/** + * @} + * + */ + +#endif /* MEMS_UCF_SHARED_TYPES */ + +/** + * @} + * + */ + +/** @defgroup LSM6DSO_Infos + * @{ + * + */ + +/** I2C Device Address 8 bit format if SA0=0 -> D5 if SA0=1 -> D7 **/ +#define LSM6DSO_I2C_ADD_L 0xD5 +#define LSM6DSO_I2C_ADD_H 0xD7 + +/** Device Identification (Who am I) **/ +#define LSM6DSO_ID 0x6C + +/** + * @} + * + */ + +#define LSM6DSO_FUNC_CFG_ACCESS 0x01U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t not_used_01 : 6; +uint8_t reg_access : + 2; /* shub_reg_access + func_cfg_access */ +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN +uint8_t reg_access : + 2; /* shub_reg_access + func_cfg_access */ + uint8_t not_used_01 : 6; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_func_cfg_access_t; + +#define LSM6DSO_PIN_CTRL 0x02U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t not_used_01 : 6; + uint8_t sdo_pu_en : 1; + uint8_t ois_pu_dis : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t ois_pu_dis : 1; + uint8_t sdo_pu_en : 1; + uint8_t not_used_01 : 6; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_pin_ctrl_t; + +#define LSM6DSO_FIFO_CTRL1 0x07U +typedef struct +{ + uint8_t wtm : 8; +} lsm6dso_fifo_ctrl1_t; + +#define LSM6DSO_FIFO_CTRL2 0x08U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t wtm : 1; + uint8_t uncoptr_rate : 2; + uint8_t not_used_01 : 1; + uint8_t odrchg_en : 1; + uint8_t not_used_02 : 1; + uint8_t fifo_compr_rt_en : 1; + uint8_t stop_on_wtm : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t stop_on_wtm : 1; + uint8_t fifo_compr_rt_en : 1; + uint8_t not_used_02 : 1; + uint8_t odrchg_en : 1; + uint8_t not_used_01 : 1; + uint8_t uncoptr_rate : 2; + uint8_t wtm : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fifo_ctrl2_t; + +#define LSM6DSO_FIFO_CTRL3 0x09U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bdr_xl : 4; + uint8_t bdr_gy : 4; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bdr_gy : 4; + uint8_t bdr_xl : 4; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fifo_ctrl3_t; + +#define LSM6DSO_FIFO_CTRL4 0x0AU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t fifo_mode : 3; + uint8_t not_used_01 : 1; + uint8_t odr_t_batch : 2; + uint8_t odr_ts_batch : 2; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t odr_ts_batch : 2; + uint8_t odr_t_batch : 2; + uint8_t not_used_01 : 1; + uint8_t fifo_mode : 3; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fifo_ctrl4_t; + +#define LSM6DSO_COUNTER_BDR_REG1 0x0BU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t cnt_bdr_th : 3; + uint8_t not_used_01 : 2; + uint8_t trig_counter_bdr : 1; + uint8_t rst_counter_bdr : 1; + uint8_t dataready_pulsed : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t dataready_pulsed : 1; + uint8_t rst_counter_bdr : 1; + uint8_t trig_counter_bdr : 1; + uint8_t not_used_01 : 2; + uint8_t cnt_bdr_th : 3; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_counter_bdr_reg1_t; + +#define LSM6DSO_COUNTER_BDR_REG2 0x0CU +typedef struct +{ + uint8_t cnt_bdr_th : 8; +} lsm6dso_counter_bdr_reg2_t; + +#define LSM6DSO_INT1_CTRL 0x0D +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t int1_drdy_xl : 1; + uint8_t int1_drdy_g : 1; + uint8_t int1_boot : 1; + uint8_t int1_fifo_th : 1; + uint8_t int1_fifo_ovr : 1; + uint8_t int1_fifo_full : 1; + uint8_t int1_cnt_bdr : 1; + uint8_t den_drdy_flag : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t den_drdy_flag : 1; + uint8_t int1_cnt_bdr : 1; + uint8_t int1_fifo_full : 1; + uint8_t int1_fifo_ovr : 1; + uint8_t int1_fifo_th : 1; + uint8_t int1_boot : 1; + uint8_t int1_drdy_g : 1; + uint8_t int1_drdy_xl : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_int1_ctrl_t; + +#define LSM6DSO_INT2_CTRL 0x0EU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t int2_drdy_xl : 1; + uint8_t int2_drdy_g : 1; + uint8_t int2_drdy_temp : 1; + uint8_t int2_fifo_th : 1; + uint8_t int2_fifo_ovr : 1; + uint8_t int2_fifo_full : 1; + uint8_t int2_cnt_bdr : 1; + uint8_t not_used_01 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_01 : 1; + uint8_t int2_cnt_bdr : 1; + uint8_t int2_fifo_full : 1; + uint8_t int2_fifo_ovr : 1; + uint8_t int2_fifo_th : 1; + uint8_t int2_drdy_temp : 1; + uint8_t int2_drdy_g : 1; + uint8_t int2_drdy_xl : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_int2_ctrl_t; + +#define LSM6DSO_WHO_AM_I 0x0FU +#define LSM6DSO_CTRL1_XL 0x10U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t not_used_01 : 1; + uint8_t lpf2_xl_en : 1; + uint8_t fs_xl : 2; + uint8_t odr_xl : 4; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t odr_xl : 4; + uint8_t fs_xl : 2; + uint8_t lpf2_xl_en : 1; + uint8_t not_used_01 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_ctrl1_xl_t; + +#define LSM6DSO_CTRL2_G 0x11U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t not_used_01 : 1; + uint8_t fs_g : 3; /* fs_125 + fs_g */ + uint8_t odr_g : 4; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t odr_g : 4; + uint8_t fs_g : 3; /* fs_125 + fs_g */ + uint8_t not_used_01 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_ctrl2_g_t; + +#define LSM6DSO_CTRL3_C 0x12U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t sw_reset : 1; + uint8_t not_used_01 : 1; + uint8_t if_inc : 1; + uint8_t sim : 1; + uint8_t pp_od : 1; + uint8_t h_lactive : 1; + uint8_t bdu : 1; + uint8_t boot : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t boot : 1; + uint8_t bdu : 1; + uint8_t h_lactive : 1; + uint8_t pp_od : 1; + uint8_t sim : 1; + uint8_t if_inc : 1; + uint8_t not_used_01 : 1; + uint8_t sw_reset : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_ctrl3_c_t; + +#define LSM6DSO_CTRL4_C 0x13U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t not_used_01 : 1; + uint8_t lpf1_sel_g : 1; + uint8_t i2c_disable : 1; + uint8_t drdy_mask : 1; + uint8_t not_used_02 : 1; + uint8_t int2_on_int1 : 1; + uint8_t sleep_g : 1; + uint8_t not_used_03 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_03 : 1; + uint8_t sleep_g : 1; + uint8_t int2_on_int1 : 1; + uint8_t not_used_02 : 1; + uint8_t drdy_mask : 1; + uint8_t i2c_disable : 1; + uint8_t lpf1_sel_g : 1; + uint8_t not_used_01 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_ctrl4_c_t; + +#define LSM6DSO_CTRL5_C 0x14U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t st_xl : 2; + uint8_t st_g : 2; + uint8_t not_used_01 : 1; + uint8_t rounding : 2; + uint8_t xl_ulp_en : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t xl_ulp_en : 1; + uint8_t rounding : 2; + uint8_t not_used_01 : 1; + uint8_t st_g : 2; + uint8_t st_xl : 2; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_ctrl5_c_t; + +#define LSM6DSO_CTRL6_C 0x15U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t ftype : 3; + uint8_t usr_off_w : 1; + uint8_t xl_hm_mode : 1; +uint8_t den_mode : + 3; /* trig_en + lvl1_en + lvl2_en */ +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN +uint8_t den_mode : + 3; /* trig_en + lvl1_en + lvl2_en */ + uint8_t xl_hm_mode : 1; + uint8_t usr_off_w : 1; + uint8_t ftype : 3; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_ctrl6_c_t; + +#define LSM6DSO_CTRL7_G 0x16U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t ois_on : 1; + uint8_t usr_off_on_out : 1; + uint8_t ois_on_en : 1; + uint8_t not_used_01 : 1; + uint8_t hpm_g : 2; + uint8_t hp_en_g : 1; + uint8_t g_hm_mode : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t g_hm_mode : 1; + uint8_t hp_en_g : 1; + uint8_t hpm_g : 2; + uint8_t not_used_01 : 1; + uint8_t ois_on_en : 1; + uint8_t usr_off_on_out : 1; + uint8_t ois_on : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_ctrl7_g_t; + +#define LSM6DSO_CTRL8_XL 0x17U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t low_pass_on_6d : 1; + uint8_t xl_fs_mode : 1; + uint8_t hp_slope_xl_en : 1; + uint8_t fastsettl_mode_xl : 1; + uint8_t hp_ref_mode_xl : 1; + uint8_t hpcf_xl : 3; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t hpcf_xl : 3; + uint8_t hp_ref_mode_xl : 1; + uint8_t fastsettl_mode_xl : 1; + uint8_t hp_slope_xl_en : 1; + uint8_t xl_fs_mode : 1; + uint8_t low_pass_on_6d : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_ctrl8_xl_t; + +#define LSM6DSO_CTRL9_XL 0x18U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t not_used_01 : 1; + uint8_t i3c_disable : 1; + uint8_t den_lh : 1; + uint8_t den_xl_g : 2; /* den_xl_en + den_xl_g */ + uint8_t den_z : 1; + uint8_t den_y : 1; + uint8_t den_x : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t den_x : 1; + uint8_t den_y : 1; + uint8_t den_z : 1; + uint8_t den_xl_g : 2; /* den_xl_en + den_xl_g */ + uint8_t den_lh : 1; + uint8_t i3c_disable : 1; + uint8_t not_used_01 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_ctrl9_xl_t; + +#define LSM6DSO_CTRL10_C 0x19U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t not_used_01 : 5; + uint8_t timestamp_en : 1; + uint8_t not_used_02 : 2; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_02 : 2; + uint8_t timestamp_en : 1; + uint8_t not_used_01 : 5; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_ctrl10_c_t; + +#define LSM6DSO_ALL_INT_SRC 0x1AU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t ff_ia : 1; + uint8_t wu_ia : 1; + uint8_t single_tap : 1; + uint8_t double_tap : 1; + uint8_t d6d_ia : 1; + uint8_t sleep_change_ia : 1; + uint8_t not_used_01 : 1; + uint8_t timestamp_endcount : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t timestamp_endcount : 1; + uint8_t not_used_01 : 1; + uint8_t sleep_change_ia : 1; + uint8_t d6d_ia : 1; + uint8_t double_tap : 1; + uint8_t single_tap : 1; + uint8_t wu_ia : 1; + uint8_t ff_ia : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_all_int_src_t; + +#define LSM6DSO_WAKE_UP_SRC 0x1BU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t z_wu : 1; + uint8_t y_wu : 1; + uint8_t x_wu : 1; + uint8_t wu_ia : 1; + uint8_t sleep_state : 1; + uint8_t ff_ia : 1; + uint8_t sleep_change_ia : 1; + uint8_t not_used_01 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_01 : 1; + uint8_t sleep_change_ia : 1; + uint8_t ff_ia : 1; + uint8_t sleep_state : 1; + uint8_t wu_ia : 1; + uint8_t x_wu : 1; + uint8_t y_wu : 1; + uint8_t z_wu : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_wake_up_src_t; + +#define LSM6DSO_TAP_SRC 0x1CU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t z_tap : 1; + uint8_t y_tap : 1; + uint8_t x_tap : 1; + uint8_t tap_sign : 1; + uint8_t double_tap : 1; + uint8_t single_tap : 1; + uint8_t tap_ia : 1; + uint8_t not_used_02 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_02 : 1; + uint8_t tap_ia : 1; + uint8_t single_tap : 1; + uint8_t double_tap : 1; + uint8_t tap_sign : 1; + uint8_t x_tap : 1; + uint8_t y_tap : 1; + uint8_t z_tap : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_tap_src_t; + +#define LSM6DSO_D6D_SRC 0x1DU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t xl : 1; + uint8_t xh : 1; + uint8_t yl : 1; + uint8_t yh : 1; + uint8_t zl : 1; + uint8_t zh : 1; + uint8_t d6d_ia : 1; + uint8_t den_drdy : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t den_drdy : 1; + uint8_t d6d_ia : 1; + uint8_t zh : 1; + uint8_t zl : 1; + uint8_t yh : 1; + uint8_t yl : 1; + uint8_t xh : 1; + uint8_t xl : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_d6d_src_t; + +#define LSM6DSO_STATUS_REG 0x1EU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t xlda : 1; + uint8_t gda : 1; + uint8_t tda : 1; + uint8_t not_used_01 : 5; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_01 : 5; + uint8_t tda : 1; + uint8_t gda : 1; + uint8_t xlda : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_status_reg_t; + +#define LSM6DSO_STATUS_SPIAUX 0x1EU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t xlda : 1; + uint8_t gda : 1; + uint8_t gyro_settling : 1; + uint8_t not_used_01 : 5; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_01 : 5; + uint8_t gyro_settling : 1; + uint8_t gda : 1; + uint8_t xlda : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_status_spiaux_t; + +#define LSM6DSO_OUT_TEMP_L 0x20U +#define LSM6DSO_OUT_TEMP_H 0x21U +#define LSM6DSO_OUTX_L_G 0x22U +#define LSM6DSO_OUTX_H_G 0x23U +#define LSM6DSO_OUTY_L_G 0x24U +#define LSM6DSO_OUTY_H_G 0x25U +#define LSM6DSO_OUTZ_L_G 0x26U +#define LSM6DSO_OUTZ_H_G 0x27U +#define LSM6DSO_OUTX_L_A 0x28U +#define LSM6DSO_OUTX_H_A 0x29U +#define LSM6DSO_OUTY_L_A 0x2AU +#define LSM6DSO_OUTY_H_A 0x2BU +#define LSM6DSO_OUTZ_L_A 0x2CU +#define LSM6DSO_OUTZ_H_A 0x2DU +#define LSM6DSO_EMB_FUNC_STATUS_MAINPAGE 0x35U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t not_used_01 : 3; + uint8_t is_step_det : 1; + uint8_t is_tilt : 1; + uint8_t is_sigmot : 1; + uint8_t not_used_02 : 1; + uint8_t is_fsm_lc : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t is_fsm_lc : 1; + uint8_t not_used_02 : 1; + uint8_t is_sigmot : 1; + uint8_t is_tilt : 1; + uint8_t is_step_det : 1; + uint8_t not_used_01 : 3; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_emb_func_status_mainpage_t; + +#define LSM6DSO_FSM_STATUS_A_MAINPAGE 0x36U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t is_fsm1 : 1; + uint8_t is_fsm2 : 1; + uint8_t is_fsm3 : 1; + uint8_t is_fsm4 : 1; + uint8_t is_fsm5 : 1; + uint8_t is_fsm6 : 1; + uint8_t is_fsm7 : 1; + uint8_t is_fsm8 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t is_fsm8 : 1; + uint8_t is_fsm7 : 1; + uint8_t is_fsm6 : 1; + uint8_t is_fsm5 : 1; + uint8_t is_fsm4 : 1; + uint8_t is_fsm3 : 1; + uint8_t is_fsm2 : 1; + uint8_t is_fsm1 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fsm_status_a_mainpage_t; + +#define LSM6DSO_FSM_STATUS_B_MAINPAGE 0x37U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t is_fsm9 : 1; + uint8_t is_fsm10 : 1; + uint8_t is_fsm11 : 1; + uint8_t is_fsm12 : 1; + uint8_t is_fsm13 : 1; + uint8_t is_fsm14 : 1; + uint8_t is_fsm15 : 1; + uint8_t is_fsm16 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t is_fsm16 : 1; + uint8_t is_fsm15 : 1; + uint8_t is_fsm14 : 1; + uint8_t is_fsm13 : 1; + uint8_t is_fsm12 : 1; + uint8_t is_fsm11 : 1; + uint8_t is_fsm10 : 1; + uint8_t is_fsm9 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fsm_status_b_mainpage_t; + +#define LSM6DSO_STATUS_MASTER_MAINPAGE 0x39U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t sens_hub_endop : 1; + uint8_t not_used_01 : 2; + uint8_t slave0_nack : 1; + uint8_t slave1_nack : 1; + uint8_t slave2_nack : 1; + uint8_t slave3_nack : 1; + uint8_t wr_once_done : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t wr_once_done : 1; + uint8_t slave3_nack : 1; + uint8_t slave2_nack : 1; + uint8_t slave1_nack : 1; + uint8_t slave0_nack : 1; + uint8_t not_used_01 : 2; + uint8_t sens_hub_endop : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_status_master_mainpage_t; + +#define LSM6DSO_FIFO_STATUS1 0x3AU +typedef struct +{ + uint8_t diff_fifo : 8; +} lsm6dso_fifo_status1_t; + +#define LSM6DSO_FIFO_STATUS2 0x3B +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t diff_fifo : 2; + uint8_t not_used_01 : 1; + uint8_t over_run_latched : 1; + uint8_t counter_bdr_ia : 1; + uint8_t fifo_full_ia : 1; + uint8_t fifo_ovr_ia : 1; + uint8_t fifo_wtm_ia : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t fifo_wtm_ia : 1; + uint8_t fifo_ovr_ia : 1; + uint8_t fifo_full_ia : 1; + uint8_t counter_bdr_ia : 1; + uint8_t over_run_latched : 1; + uint8_t not_used_01 : 1; + uint8_t diff_fifo : 2; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fifo_status2_t; + +#define LSM6DSO_TIMESTAMP0 0x40U +#define LSM6DSO_TIMESTAMP1 0x41U +#define LSM6DSO_TIMESTAMP2 0x42U +#define LSM6DSO_TIMESTAMP3 0x43U +#define LSM6DSO_TAP_CFG0 0x56U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t lir : 1; + uint8_t tap_z_en : 1; + uint8_t tap_y_en : 1; + uint8_t tap_x_en : 1; + uint8_t slope_fds : 1; + uint8_t sleep_status_on_int : 1; + uint8_t int_clr_on_read : 1; + uint8_t not_used_01 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_01 : 1; + uint8_t int_clr_on_read : 1; + uint8_t sleep_status_on_int : 1; + uint8_t slope_fds : 1; + uint8_t tap_x_en : 1; + uint8_t tap_y_en : 1; + uint8_t tap_z_en : 1; + uint8_t lir : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_tap_cfg0_t; + +#define LSM6DSO_TAP_CFG1 0x57U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t tap_ths_x : 5; + uint8_t tap_priority : 3; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t tap_priority : 3; + uint8_t tap_ths_x : 5; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_tap_cfg1_t; + +#define LSM6DSO_TAP_CFG2 0x58U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t tap_ths_y : 5; + uint8_t inact_en : 2; + uint8_t interrupts_enable : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t interrupts_enable : 1; + uint8_t inact_en : 2; + uint8_t tap_ths_y : 5; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_tap_cfg2_t; + +#define LSM6DSO_TAP_THS_6D 0x59U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t tap_ths_z : 5; + uint8_t sixd_ths : 2; + uint8_t d4d_en : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t d4d_en : 1; + uint8_t sixd_ths : 2; + uint8_t tap_ths_z : 5; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_tap_ths_6d_t; + +#define LSM6DSO_INT_DUR2 0x5AU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t shock : 2; + uint8_t quiet : 2; + uint8_t dur : 4; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t dur : 4; + uint8_t quiet : 2; + uint8_t shock : 2; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_int_dur2_t; + +#define LSM6DSO_WAKE_UP_THS 0x5BU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t wk_ths : 6; + uint8_t usr_off_on_wu : 1; + uint8_t single_double_tap : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t single_double_tap : 1; + uint8_t usr_off_on_wu : 1; + uint8_t wk_ths : 6; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_wake_up_ths_t; + +#define LSM6DSO_WAKE_UP_DUR 0x5CU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t sleep_dur : 4; + uint8_t wake_ths_w : 1; + uint8_t wake_dur : 2; + uint8_t ff_dur : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t ff_dur : 1; + uint8_t wake_dur : 2; + uint8_t wake_ths_w : 1; + uint8_t sleep_dur : 4; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_wake_up_dur_t; + +#define LSM6DSO_FREE_FALL 0x5DU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t ff_ths : 3; + uint8_t ff_dur : 5; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t ff_dur : 5; + uint8_t ff_ths : 3; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_free_fall_t; + +#define LSM6DSO_MD1_CFG 0x5EU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t int1_shub : 1; + uint8_t int1_emb_func : 1; + uint8_t int1_6d : 1; + uint8_t int1_double_tap : 1; + uint8_t int1_ff : 1; + uint8_t int1_wu : 1; + uint8_t int1_single_tap : 1; + uint8_t int1_sleep_change : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t int1_sleep_change : 1; + uint8_t int1_single_tap : 1; + uint8_t int1_wu : 1; + uint8_t int1_ff : 1; + uint8_t int1_double_tap : 1; + uint8_t int1_6d : 1; + uint8_t int1_emb_func : 1; + uint8_t int1_shub : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_md1_cfg_t; + +#define LSM6DSO_MD2_CFG 0x5FU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t int2_timestamp : 1; + uint8_t int2_emb_func : 1; + uint8_t int2_6d : 1; + uint8_t int2_double_tap : 1; + uint8_t int2_ff : 1; + uint8_t int2_wu : 1; + uint8_t int2_single_tap : 1; + uint8_t int2_sleep_change : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t int2_sleep_change : 1; + uint8_t int2_single_tap : 1; + uint8_t int2_wu : 1; + uint8_t int2_ff : 1; + uint8_t int2_double_tap : 1; + uint8_t int2_6d : 1; + uint8_t int2_emb_func : 1; + uint8_t int2_timestamp : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_md2_cfg_t; + +#define LSM6DSO_I3C_BUS_AVB 0x62U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t pd_dis_int1 : 1; + uint8_t not_used_01 : 2; + uint8_t i3c_bus_avb_sel : 2; + uint8_t not_used_02 : 3; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_02 : 3; + uint8_t i3c_bus_avb_sel : 2; + uint8_t not_used_01 : 2; + uint8_t pd_dis_int1 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_i3c_bus_avb_t; + +#define LSM6DSO_INTERNAL_FREQ_FINE 0x63U +typedef struct +{ + uint8_t freq_fine : 8; +} lsm6dso_internal_freq_fine_t; + +#define LSM6DSO_INT_OIS 0x6FU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t st_xl_ois : 2; + uint8_t not_used_01 : 3; + uint8_t den_lh_ois : 1; + uint8_t lvl2_ois : 1; + uint8_t int2_drdy_ois : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t int2_drdy_ois : 1; + uint8_t lvl2_ois : 1; + uint8_t den_lh_ois : 1; + uint8_t not_used_01 : 3; + uint8_t st_xl_ois : 2; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_int_ois_t; + +#define LSM6DSO_CTRL1_OIS 0x70U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t ois_en_spi2 : 1; + uint8_t fs_g_ois : 3; /* fs_125_ois + fs[1:0]_g_ois */ + uint8_t mode4_en : 1; + uint8_t sim_ois : 1; + uint8_t lvl1_ois : 1; + uint8_t not_used_01 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_01 : 1; + uint8_t lvl1_ois : 1; + uint8_t sim_ois : 1; + uint8_t mode4_en : 1; + uint8_t fs_g_ois : 3; /* fs_125_ois + fs[1:0]_g_ois */ + uint8_t ois_en_spi2 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_ctrl1_ois_t; + +#define LSM6DSO_CTRL2_OIS 0x71U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t hp_en_ois : 1; + uint8_t ftype_ois : 2; + uint8_t not_used_01 : 1; + uint8_t hpm_ois : 2; + uint8_t not_used_02 : 2; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_02 : 2; + uint8_t hpm_ois : 2; + uint8_t not_used_01 : 1; + uint8_t ftype_ois : 2; + uint8_t hp_en_ois : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_ctrl2_ois_t; + +#define LSM6DSO_CTRL3_OIS 0x72U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t st_ois_clampdis : 1; + uint8_t st_ois : 2; + uint8_t filter_xl_conf_ois : 3; + uint8_t fs_xl_ois : 2; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t fs_xl_ois : 2; + uint8_t filter_xl_conf_ois : 3; + uint8_t st_ois : 2; + uint8_t st_ois_clampdis : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_ctrl3_ois_t; + +#define LSM6DSO_X_OFS_USR 0x73U +#define LSM6DSO_Y_OFS_USR 0x74U +#define LSM6DSO_Z_OFS_USR 0x75U +#define LSM6DSO_FIFO_DATA_OUT_TAG 0x78U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t tag_parity : 1; + uint8_t tag_cnt : 2; + uint8_t tag_sensor : 5; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t tag_sensor : 5; + uint8_t tag_cnt : 2; + uint8_t tag_parity : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fifo_data_out_tag_t; + +#define LSM6DSO_FIFO_DATA_OUT_X_L 0x79U +#define LSM6DSO_FIFO_DATA_OUT_X_H 0x7AU +#define LSM6DSO_FIFO_DATA_OUT_Y_L 0x7BU +#define LSM6DSO_FIFO_DATA_OUT_Y_H 0x7CU +#define LSM6DSO_FIFO_DATA_OUT_Z_L 0x7DU +#define LSM6DSO_FIFO_DATA_OUT_Z_H 0x7EU +#define LSM6DSO_PAGE_SEL 0x02U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t not_used_01 : 4; + uint8_t page_sel : 4; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t page_sel : 4; + uint8_t not_used_01 : 4; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_page_sel_t; + +#define LSM6DSO_EMB_FUNC_EN_A 0x04U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t not_used_01 : 3; + uint8_t pedo_en : 1; + uint8_t tilt_en : 1; + uint8_t sign_motion_en : 1; + uint8_t not_used_02 : 2; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_02 : 2; + uint8_t sign_motion_en : 1; + uint8_t tilt_en : 1; + uint8_t pedo_en : 1; + uint8_t not_used_01 : 3; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_emb_func_en_a_t; + +#define LSM6DSO_EMB_FUNC_EN_B 0x05U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t fsm_en : 1; + uint8_t not_used_01 : 2; + uint8_t fifo_compr_en : 1; + uint8_t pedo_adv_en : 1; + uint8_t not_used_02 : 3; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_02 : 3; + uint8_t pedo_adv_en : 1; + uint8_t fifo_compr_en : 1; + uint8_t not_used_01 : 2; + uint8_t fsm_en : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_emb_func_en_b_t; + +#define LSM6DSO_PAGE_ADDRESS 0x08U +typedef struct +{ + uint8_t page_addr : 8; +} lsm6dso_page_address_t; + +#define LSM6DSO_PAGE_VALUE 0x09U +typedef struct +{ + uint8_t page_value : 8; +} lsm6dso_page_value_t; + +#define LSM6DSO_EMB_FUNC_INT1 0x0AU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t not_used_01 : 3; + uint8_t int1_step_detector : 1; + uint8_t int1_tilt : 1; + uint8_t int1_sig_mot : 1; + uint8_t not_used_02 : 1; + uint8_t int1_fsm_lc : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t int1_fsm_lc : 1; + uint8_t not_used_02 : 1; + uint8_t int1_sig_mot : 1; + uint8_t int1_tilt : 1; + uint8_t int1_step_detector : 1; + uint8_t not_used_01 : 3; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_emb_func_int1_t; + +#define LSM6DSO_FSM_INT1_A 0x0BU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t int1_fsm1 : 1; + uint8_t int1_fsm2 : 1; + uint8_t int1_fsm3 : 1; + uint8_t int1_fsm4 : 1; + uint8_t int1_fsm5 : 1; + uint8_t int1_fsm6 : 1; + uint8_t int1_fsm7 : 1; + uint8_t int1_fsm8 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t int1_fsm8 : 1; + uint8_t int1_fsm7 : 1; + uint8_t int1_fsm6 : 1; + uint8_t int1_fsm5 : 1; + uint8_t int1_fsm4 : 1; + uint8_t int1_fsm3 : 1; + uint8_t int1_fsm2 : 1; + uint8_t int1_fsm1 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fsm_int1_a_t; + +#define LSM6DSO_FSM_INT1_B 0x0CU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t int1_fsm9 : 1; + uint8_t int1_fsm10 : 1; + uint8_t int1_fsm11 : 1; + uint8_t int1_fsm12 : 1; + uint8_t int1_fsm13 : 1; + uint8_t int1_fsm14 : 1; + uint8_t int1_fsm15 : 1; + uint8_t int1_fsm16 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t int1_fsm16 : 1; + uint8_t int1_fsm15 : 1; + uint8_t int1_fsm14 : 1; + uint8_t int1_fsm13 : 1; + uint8_t int1_fsm12 : 1; + uint8_t int1_fsm11 : 1; + uint8_t int1_fsm10 : 1; + uint8_t int1_fsm9 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fsm_int1_b_t; + +#define LSM6DSO_EMB_FUNC_INT2 0x0EU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t not_used_01 : 3; + uint8_t int2_step_detector : 1; + uint8_t int2_tilt : 1; + uint8_t int2_sig_mot : 1; + uint8_t not_used_02 : 1; + uint8_t int2_fsm_lc : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t int2_fsm_lc : 1; + uint8_t not_used_02 : 1; + uint8_t int2_sig_mot : 1; + uint8_t int2_tilt : 1; + uint8_t int2_step_detector : 1; + uint8_t not_used_01 : 3; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_emb_func_int2_t; + +#define LSM6DSO_FSM_INT2_A 0x0FU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t int2_fsm1 : 1; + uint8_t int2_fsm2 : 1; + uint8_t int2_fsm3 : 1; + uint8_t int2_fsm4 : 1; + uint8_t int2_fsm5 : 1; + uint8_t int2_fsm6 : 1; + uint8_t int2_fsm7 : 1; + uint8_t int2_fsm8 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t int2_fsm8 : 1; + uint8_t int2_fsm7 : 1; + uint8_t int2_fsm6 : 1; + uint8_t int2_fsm5 : 1; + uint8_t int2_fsm4 : 1; + uint8_t int2_fsm3 : 1; + uint8_t int2_fsm2 : 1; + uint8_t int2_fsm1 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fsm_int2_a_t; + +#define LSM6DSO_FSM_INT2_B 0x10U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t int2_fsm9 : 1; + uint8_t int2_fsm10 : 1; + uint8_t int2_fsm11 : 1; + uint8_t int2_fsm12 : 1; + uint8_t int2_fsm13 : 1; + uint8_t int2_fsm14 : 1; + uint8_t int2_fsm15 : 1; + uint8_t int2_fsm16 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t int2_fsm16 : 1; + uint8_t int2_fsm15 : 1; + uint8_t int2_fsm14 : 1; + uint8_t int2_fsm13 : 1; + uint8_t int2_fsm12 : 1; + uint8_t int2_fsm11 : 1; + uint8_t int2_fsm10 : 1; + uint8_t int2_fsm9 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fsm_int2_b_t; + +#define LSM6DSO_EMB_FUNC_STATUS 0x12U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t not_used_01 : 3; + uint8_t is_step_det : 1; + uint8_t is_tilt : 1; + uint8_t is_sigmot : 1; + uint8_t not_used_02 : 1; + uint8_t is_fsm_lc : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t is_fsm_lc : 1; + uint8_t not_used_02 : 1; + uint8_t is_sigmot : 1; + uint8_t is_tilt : 1; + uint8_t is_step_det : 1; + uint8_t not_used_01 : 3; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_emb_func_status_t; + +#define LSM6DSO_FSM_STATUS_A 0x13U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t is_fsm1 : 1; + uint8_t is_fsm2 : 1; + uint8_t is_fsm3 : 1; + uint8_t is_fsm4 : 1; + uint8_t is_fsm5 : 1; + uint8_t is_fsm6 : 1; + uint8_t is_fsm7 : 1; + uint8_t is_fsm8 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t is_fsm8 : 1; + uint8_t is_fsm7 : 1; + uint8_t is_fsm6 : 1; + uint8_t is_fsm5 : 1; + uint8_t is_fsm4 : 1; + uint8_t is_fsm3 : 1; + uint8_t is_fsm2 : 1; + uint8_t is_fsm1 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fsm_status_a_t; + +#define LSM6DSO_FSM_STATUS_B 0x14U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t is_fsm9 : 1; + uint8_t is_fsm10 : 1; + uint8_t is_fsm11 : 1; + uint8_t is_fsm12 : 1; + uint8_t is_fsm13 : 1; + uint8_t is_fsm14 : 1; + uint8_t is_fsm15 : 1; + uint8_t is_fsm16 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t is_fsm16 : 1; + uint8_t is_fsm15 : 1; + uint8_t is_fsm14 : 1; + uint8_t is_fsm13 : 1; + uint8_t is_fsm12 : 1; + uint8_t is_fsm11 : 1; + uint8_t is_fsm10 : 1; + uint8_t is_fsm9 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fsm_status_b_t; + +#define LSM6DSO_PAGE_RW 0x17U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t not_used_01 : 5; + uint8_t page_rw : 2; /* page_write + page_read */ + uint8_t emb_func_lir : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t emb_func_lir : 1; + uint8_t page_rw : 2; /* page_write + page_read */ + uint8_t not_used_01 : 5; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_page_rw_t; + +#define LSM6DSO_EMB_FUNC_FIFO_CFG 0x44U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t not_used_00 : 6; + uint8_t pedo_fifo_en : 1; + uint8_t not_used_01 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_01 : 1; + uint8_t pedo_fifo_en : 1; + uint8_t not_used_00 : 6; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_emb_func_fifo_cfg_t; + +#define LSM6DSO_FSM_ENABLE_A 0x46U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t fsm1_en : 1; + uint8_t fsm2_en : 1; + uint8_t fsm3_en : 1; + uint8_t fsm4_en : 1; + uint8_t fsm5_en : 1; + uint8_t fsm6_en : 1; + uint8_t fsm7_en : 1; + uint8_t fsm8_en : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t fsm8_en : 1; + uint8_t fsm7_en : 1; + uint8_t fsm6_en : 1; + uint8_t fsm5_en : 1; + uint8_t fsm4_en : 1; + uint8_t fsm3_en : 1; + uint8_t fsm2_en : 1; + uint8_t fsm1_en : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fsm_enable_a_t; + +#define LSM6DSO_FSM_ENABLE_B 0x47U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t fsm9_en : 1; + uint8_t fsm10_en : 1; + uint8_t fsm11_en : 1; + uint8_t fsm12_en : 1; + uint8_t fsm13_en : 1; + uint8_t fsm14_en : 1; + uint8_t fsm15_en : 1; + uint8_t fsm16_en : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t fsm16_en : 1; + uint8_t fsm15_en : 1; + uint8_t fsm14_en : 1; + uint8_t fsm13_en : 1; + uint8_t fsm12_en : 1; + uint8_t fsm11_en : 1; + uint8_t fsm10_en : 1; + uint8_t fsm9_en : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fsm_enable_b_t; + +#define LSM6DSO_FSM_LONG_COUNTER_L 0x48U +#define LSM6DSO_FSM_LONG_COUNTER_H 0x49U +#define LSM6DSO_FSM_LONG_COUNTER_CLEAR 0x4AU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN +uint8_t fsm_lc_clr : + 2; /* fsm_lc_cleared + fsm_lc_clear */ + uint8_t not_used_01 : 6; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_01 : 6; +uint8_t fsm_lc_clr : + 2; /* fsm_lc_cleared + fsm_lc_clear */ +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fsm_long_counter_clear_t; + +#define LSM6DSO_FSM_OUTS1 0x4CU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t n_v : 1; + uint8_t p_v : 1; + uint8_t n_z : 1; + uint8_t p_z : 1; + uint8_t n_y : 1; + uint8_t p_y : 1; + uint8_t n_x : 1; + uint8_t p_x : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t p_x : 1; + uint8_t n_x : 1; + uint8_t p_y : 1; + uint8_t n_y : 1; + uint8_t p_z : 1; + uint8_t n_z : 1; + uint8_t p_v : 1; + uint8_t n_v : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fsm_outs1_t; + +#define LSM6DSO_FSM_OUTS2 0x4DU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t n_v : 1; + uint8_t p_v : 1; + uint8_t n_z : 1; + uint8_t p_z : 1; + uint8_t n_y : 1; + uint8_t p_y : 1; + uint8_t n_x : 1; + uint8_t p_x : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t p_x : 1; + uint8_t n_x : 1; + uint8_t p_y : 1; + uint8_t n_y : 1; + uint8_t p_z : 1; + uint8_t n_z : 1; + uint8_t p_v : 1; + uint8_t n_v : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fsm_outs2_t; + +#define LSM6DSO_FSM_OUTS3 0x4EU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t n_v : 1; + uint8_t p_v : 1; + uint8_t n_z : 1; + uint8_t p_z : 1; + uint8_t n_y : 1; + uint8_t p_y : 1; + uint8_t n_x : 1; + uint8_t p_x : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t p_x : 1; + uint8_t n_x : 1; + uint8_t p_y : 1; + uint8_t n_y : 1; + uint8_t p_z : 1; + uint8_t n_z : 1; + uint8_t p_v : 1; + uint8_t n_v : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fsm_outs3_t; + +#define LSM6DSO_FSM_OUTS4 0x4FU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t n_v : 1; + uint8_t p_v : 1; + uint8_t n_z : 1; + uint8_t p_z : 1; + uint8_t n_y : 1; + uint8_t p_y : 1; + uint8_t n_x : 1; + uint8_t p_x : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t p_x : 1; + uint8_t n_x : 1; + uint8_t p_y : 1; + uint8_t n_y : 1; + uint8_t p_z : 1; + uint8_t n_z : 1; + uint8_t p_v : 1; + uint8_t n_v : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fsm_outs4_t; + +#define LSM6DSO_FSM_OUTS5 0x50U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t n_v : 1; + uint8_t p_v : 1; + uint8_t n_z : 1; + uint8_t p_z : 1; + uint8_t n_y : 1; + uint8_t p_y : 1; + uint8_t n_x : 1; + uint8_t p_x : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t p_x : 1; + uint8_t n_x : 1; + uint8_t p_y : 1; + uint8_t n_y : 1; + uint8_t p_z : 1; + uint8_t n_z : 1; + uint8_t p_v : 1; + uint8_t n_v : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fsm_outs5_t; + +#define LSM6DSO_FSM_OUTS6 0x51U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t n_v : 1; + uint8_t p_v : 1; + uint8_t n_z : 1; + uint8_t p_z : 1; + uint8_t n_y : 1; + uint8_t p_y : 1; + uint8_t n_x : 1; + uint8_t p_x : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t p_x : 1; + uint8_t n_x : 1; + uint8_t p_y : 1; + uint8_t n_y : 1; + uint8_t p_z : 1; + uint8_t n_z : 1; + uint8_t p_v : 1; + uint8_t n_v : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fsm_outs6_t; + +#define LSM6DSO_FSM_OUTS7 0x52U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t n_v : 1; + uint8_t p_v : 1; + uint8_t n_z : 1; + uint8_t p_z : 1; + uint8_t n_y : 1; + uint8_t p_y : 1; + uint8_t n_x : 1; + uint8_t p_x : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t p_x : 1; + uint8_t n_x : 1; + uint8_t p_y : 1; + uint8_t n_y : 1; + uint8_t p_z : 1; + uint8_t n_z : 1; + uint8_t p_v : 1; + uint8_t n_v : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fsm_outs7_t; + +#define LSM6DSO_FSM_OUTS8 0x53U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t n_v : 1; + uint8_t p_v : 1; + uint8_t n_z : 1; + uint8_t p_z : 1; + uint8_t n_y : 1; + uint8_t p_y : 1; + uint8_t n_x : 1; + uint8_t p_x : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t p_x : 1; + uint8_t n_x : 1; + uint8_t p_y : 1; + uint8_t n_y : 1; + uint8_t p_z : 1; + uint8_t n_z : 1; + uint8_t p_v : 1; + uint8_t n_v : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fsm_outs8_t; + +#define LSM6DSO_FSM_OUTS9 0x54U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t n_v : 1; + uint8_t p_v : 1; + uint8_t n_z : 1; + uint8_t p_z : 1; + uint8_t n_y : 1; + uint8_t p_y : 1; + uint8_t n_x : 1; + uint8_t p_x : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t p_x : 1; + uint8_t n_x : 1; + uint8_t p_y : 1; + uint8_t n_y : 1; + uint8_t p_z : 1; + uint8_t n_z : 1; + uint8_t p_v : 1; + uint8_t n_v : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fsm_outs9_t; + +#define LSM6DSO_FSM_OUTS10 0x55U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t n_v : 1; + uint8_t p_v : 1; + uint8_t n_z : 1; + uint8_t p_z : 1; + uint8_t n_y : 1; + uint8_t p_y : 1; + uint8_t n_x : 1; + uint8_t p_x : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t p_x : 1; + uint8_t n_x : 1; + uint8_t p_y : 1; + uint8_t n_y : 1; + uint8_t p_z : 1; + uint8_t n_z : 1; + uint8_t p_v : 1; + uint8_t n_v : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fsm_outs10_t; + +#define LSM6DSO_FSM_OUTS11 0x56U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t n_v : 1; + uint8_t p_v : 1; + uint8_t n_z : 1; + uint8_t p_z : 1; + uint8_t n_y : 1; + uint8_t p_y : 1; + uint8_t n_x : 1; + uint8_t p_x : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t p_x : 1; + uint8_t n_x : 1; + uint8_t p_y : 1; + uint8_t n_y : 1; + uint8_t p_z : 1; + uint8_t n_z : 1; + uint8_t p_v : 1; + uint8_t n_v : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fsm_outs11_t; + +#define LSM6DSO_FSM_OUTS12 0x57U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t n_v : 1; + uint8_t p_v : 1; + uint8_t n_z : 1; + uint8_t p_z : 1; + uint8_t n_y : 1; + uint8_t p_y : 1; + uint8_t n_x : 1; + uint8_t p_x : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t p_x : 1; + uint8_t n_x : 1; + uint8_t p_y : 1; + uint8_t n_y : 1; + uint8_t p_z : 1; + uint8_t n_z : 1; + uint8_t p_v : 1; + uint8_t n_v : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fsm_outs12_t; + +#define LSM6DSO_FSM_OUTS13 0x58U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t n_v : 1; + uint8_t p_v : 1; + uint8_t n_z : 1; + uint8_t p_z : 1; + uint8_t n_y : 1; + uint8_t p_y : 1; + uint8_t n_x : 1; + uint8_t p_x : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t p_x : 1; + uint8_t n_x : 1; + uint8_t p_y : 1; + uint8_t n_y : 1; + uint8_t p_z : 1; + uint8_t n_z : 1; + uint8_t p_v : 1; + uint8_t n_v : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fsm_outs13_t; + +#define LSM6DSO_FSM_OUTS14 0x59U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t n_v : 1; + uint8_t p_v : 1; + uint8_t n_z : 1; + uint8_t p_z : 1; + uint8_t n_y : 1; + uint8_t p_y : 1; + uint8_t n_x : 1; + uint8_t p_x : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t p_x : 1; + uint8_t n_x : 1; + uint8_t p_y : 1; + uint8_t n_y : 1; + uint8_t p_z : 1; + uint8_t n_z : 1; + uint8_t p_v : 1; + uint8_t n_v : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fsm_outs14_t; + +#define LSM6DSO_FSM_OUTS15 0x5AU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t n_v : 1; + uint8_t p_v : 1; + uint8_t n_z : 1; + uint8_t p_z : 1; + uint8_t n_y : 1; + uint8_t p_y : 1; + uint8_t n_x : 1; + uint8_t p_x : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t p_x : 1; + uint8_t n_x : 1; + uint8_t p_y : 1; + uint8_t n_y : 1; + uint8_t p_z : 1; + uint8_t n_z : 1; + uint8_t p_v : 1; + uint8_t n_v : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fsm_outs15_t; + +#define LSM6DSO_FSM_OUTS16 0x5BU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t n_v : 1; + uint8_t p_v : 1; + uint8_t n_z : 1; + uint8_t p_z : 1; + uint8_t n_y : 1; + uint8_t p_y : 1; + uint8_t n_x : 1; + uint8_t p_x : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t p_x : 1; + uint8_t n_x : 1; + uint8_t p_y : 1; + uint8_t n_y : 1; + uint8_t p_z : 1; + uint8_t n_z : 1; + uint8_t p_v : 1; + uint8_t n_v : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_fsm_outs16_t; + +#define LSM6DSO_EMB_FUNC_ODR_CFG_B 0x5FU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t not_used_01 : 3; + uint8_t fsm_odr : 2; + uint8_t not_used_02 : 3; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_02 : 3; + uint8_t fsm_odr : 2; + uint8_t not_used_01 : 3; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_emb_func_odr_cfg_b_t; + +#define LSM6DSO_STEP_COUNTER_L 0x62U +#define LSM6DSO_STEP_COUNTER_H 0x63U +#define LSM6DSO_EMB_FUNC_SRC 0x64U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t not_used_01 : 2; + uint8_t stepcounter_bit_set : 1; + uint8_t step_overflow : 1; + uint8_t step_count_delta_ia : 1; + uint8_t step_detected : 1; + uint8_t not_used_02 : 1; + uint8_t pedo_rst_step : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t pedo_rst_step : 1; + uint8_t not_used_02 : 1; + uint8_t step_detected : 1; + uint8_t step_count_delta_ia : 1; + uint8_t step_overflow : 1; + uint8_t stepcounter_bit_set : 1; + uint8_t not_used_01 : 2; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_emb_func_src_t; + +#define LSM6DSO_EMB_FUNC_INIT_A 0x66U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t not_used_01 : 3; + uint8_t step_det_init : 1; + uint8_t tilt_init : 1; + uint8_t sig_mot_init : 1; + uint8_t not_used_02 : 2; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_02 : 2; + uint8_t sig_mot_init : 1; + uint8_t tilt_init : 1; + uint8_t step_det_init : 1; + uint8_t not_used_01 : 3; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_emb_func_init_a_t; + +#define LSM6DSO_EMB_FUNC_INIT_B 0x67U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t fsm_init : 1; + uint8_t not_used_01 : 2; + uint8_t fifo_compr_init : 1; + uint8_t not_used_02 : 4; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_02 : 4; + uint8_t fifo_compr_init : 1; + uint8_t not_used_01 : 2; + uint8_t fsm_init : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_emb_func_init_b_t; + +#define LSM6DSO_MAG_SENSITIVITY_L 0xBAU +#define LSM6DSO_MAG_SENSITIVITY_H 0xBBU +#define LSM6DSO_MAG_OFFX_L 0xC0U +#define LSM6DSO_MAG_OFFX_H 0xC1U +#define LSM6DSO_MAG_OFFY_L 0xC2U +#define LSM6DSO_MAG_OFFY_H 0xC3U +#define LSM6DSO_MAG_OFFZ_L 0xC4U +#define LSM6DSO_MAG_OFFZ_H 0xC5U +#define LSM6DSO_MAG_SI_XX_L 0xC6U +#define LSM6DSO_MAG_SI_XX_H 0xC7U +#define LSM6DSO_MAG_SI_XY_L 0xC8U +#define LSM6DSO_MAG_SI_XY_H 0xC9U +#define LSM6DSO_MAG_SI_XZ_L 0xCAU +#define LSM6DSO_MAG_SI_XZ_H 0xCBU +#define LSM6DSO_MAG_SI_YY_L 0xCCU +#define LSM6DSO_MAG_SI_YY_H 0xCDU +#define LSM6DSO_MAG_SI_YZ_L 0xCEU +#define LSM6DSO_MAG_SI_YZ_H 0xCFU +#define LSM6DSO_MAG_SI_ZZ_L 0xD0U +#define LSM6DSO_MAG_SI_ZZ_H 0xD1U +#define LSM6DSO_MAG_CFG_A 0xD4U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t mag_z_axis : 3; + uint8_t not_used_01 : 1; + uint8_t mag_y_axis : 3; + uint8_t not_used_02 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_02 : 1; + uint8_t mag_y_axis : 3; + uint8_t not_used_01 : 1; + uint8_t mag_z_axis : 3; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_mag_cfg_a_t; + +#define LSM6DSO_MAG_CFG_B 0xD5U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t mag_x_axis : 3; + uint8_t not_used_01 : 5; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_01 : 5; + uint8_t mag_x_axis : 3; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_mag_cfg_b_t; + +#define LSM6DSO_FSM_LC_TIMEOUT_L 0x17AU +#define LSM6DSO_FSM_LC_TIMEOUT_H 0x17BU +#define LSM6DSO_FSM_PROGRAMS 0x17CU +#define LSM6DSO_FSM_START_ADD_L 0x17EU +#define LSM6DSO_FSM_START_ADD_H 0x17FU +#define LSM6DSO_PEDO_CMD_REG 0x183U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t ad_det_en : 1; + uint8_t not_used_01 : 1; + uint8_t fp_rejection_en : 1; + uint8_t carry_count_en : 1; + uint8_t not_used_02 : 4; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_02 : 4; + uint8_t carry_count_en : 1; + uint8_t fp_rejection_en : 1; + uint8_t not_used_01 : 1; + uint8_t ad_det_en : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_pedo_cmd_reg_t; + +#define LSM6DSO_PEDO_DEB_STEPS_CONF 0x184U +#define LSM6DSO_PEDO_SC_DELTAT_L 0x1D0U +#define LSM6DSO_PEDO_SC_DELTAT_H 0x1D1U +#define LSM6DSO_SENSOR_HUB_1 0x02U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_sensor_hub_1_t; + +#define LSM6DSO_SENSOR_HUB_2 0x03U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_sensor_hub_2_t; + +#define LSM6DSO_SENSOR_HUB_3 0x04U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_sensor_hub_3_t; + +#define LSM6DSO_SENSOR_HUB_4 0x05U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_sensor_hub_4_t; + +#define LSM6DSO_SENSOR_HUB_5 0x06U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_sensor_hub_5_t; + +#define LSM6DSO_SENSOR_HUB_6 0x07U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_sensor_hub_6_t; + +#define LSM6DSO_SENSOR_HUB_7 0x08U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_sensor_hub_7_t; + +#define LSM6DSO_SENSOR_HUB_8 0x09U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_sensor_hub_8_t; + +#define LSM6DSO_SENSOR_HUB_9 0x0AU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_sensor_hub_9_t; + +#define LSM6DSO_SENSOR_HUB_10 0x0BU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_sensor_hub_10_t; + +#define LSM6DSO_SENSOR_HUB_11 0x0CU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_sensor_hub_11_t; + +#define LSM6DSO_SENSOR_HUB_12 0x0DU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_sensor_hub_12_t; + +#define LSM6DSO_SENSOR_HUB_13 0x0EU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_sensor_hub_13_t; + +#define LSM6DSO_SENSOR_HUB_14 0x0FU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_sensor_hub_14_t; + +#define LSM6DSO_SENSOR_HUB_15 0x10U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_sensor_hub_15_t; + +#define LSM6DSO_SENSOR_HUB_16 0x11U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_sensor_hub_16_t; + +#define LSM6DSO_SENSOR_HUB_17 0x12U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_sensor_hub_17_t; + +#define LSM6DSO_SENSOR_HUB_18 0x13U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t bit0 : 1; + uint8_t bit1 : 1; + uint8_t bit2 : 1; + uint8_t bit3 : 1; + uint8_t bit4 : 1; + uint8_t bit5 : 1; + uint8_t bit6 : 1; + uint8_t bit7 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_sensor_hub_18_t; + +#define LSM6DSO_MASTER_CONFIG 0x14U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t aux_sens_on : 2; + uint8_t master_on : 1; + uint8_t shub_pu_en : 1; + uint8_t pass_through_mode : 1; + uint8_t start_config : 1; + uint8_t write_once : 1; + uint8_t rst_master_regs : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t rst_master_regs : 1; + uint8_t write_once : 1; + uint8_t start_config : 1; + uint8_t pass_through_mode : 1; + uint8_t shub_pu_en : 1; + uint8_t master_on : 1; + uint8_t aux_sens_on : 2; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_master_config_t; + +#define LSM6DSO_SLV0_ADD 0x15U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t rw_0 : 1; + uint8_t slave0 : 7; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t slave0 : 7; + uint8_t rw_0 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_slv0_add_t; + +#define LSM6DSO_SLV0_SUBADD 0x16U +typedef struct +{ + uint8_t slave0_reg : 8; +} lsm6dso_slv0_subadd_t; + +#define LSM6DSO_SLV0_CONFIG 0x17U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t slave0_numop : 3; + uint8_t batch_ext_sens_0_en : 1; + uint8_t not_used_01 : 2; + uint8_t shub_odr : 2; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t shub_odr : 2; + uint8_t not_used_01 : 2; + uint8_t batch_ext_sens_0_en : 1; + uint8_t slave0_numop : 3; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_slv0_config_t; + +#define LSM6DSO_SLV1_ADD 0x18U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t r_1 : 1; + uint8_t slave1_add : 7; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t slave1_add : 7; + uint8_t r_1 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_slv1_add_t; + +#define LSM6DSO_SLV1_SUBADD 0x19U +typedef struct +{ + uint8_t slave1_reg : 8; +} lsm6dso_slv1_subadd_t; + +#define LSM6DSO_SLV1_CONFIG 0x1AU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t slave1_numop : 3; + uint8_t batch_ext_sens_1_en : 1; + uint8_t not_used_01 : 4; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_01 : 4; + uint8_t batch_ext_sens_1_en : 1; + uint8_t slave1_numop : 3; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_slv1_config_t; + +#define LSM6DSO_SLV2_ADD 0x1BU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t r_2 : 1; + uint8_t slave2_add : 7; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t slave2_add : 7; + uint8_t r_2 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_slv2_add_t; + +#define LSM6DSO_SLV2_SUBADD 0x1CU +typedef struct +{ + uint8_t slave2_reg : 8; +} lsm6dso_slv2_subadd_t; + +#define LSM6DSO_SLV2_CONFIG 0x1DU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t slave2_numop : 3; + uint8_t batch_ext_sens_2_en : 1; + uint8_t not_used_01 : 4; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_01 : 4; + uint8_t batch_ext_sens_2_en : 1; + uint8_t slave2_numop : 3; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_slv2_config_t; + +#define LSM6DSO_SLV3_ADD 0x1EU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t r_3 : 1; + uint8_t slave3_add : 7; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t slave3_add : 7; + uint8_t r_3 : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_slv3_add_t; + +#define LSM6DSO_SLV3_SUBADD 0x1FU +typedef struct +{ + uint8_t slave3_reg : 8; +} lsm6dso_slv3_subadd_t; + +#define LSM6DSO_SLV3_CONFIG 0x20U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t slave3_numop : 3; + uint8_t batch_ext_sens_3_en : 1; + uint8_t not_used_01 : 4; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_01 : 4; + uint8_t batch_ext_sens_3_en : 1; + uint8_t slave3_numop : 3; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_slv3_config_t; + +#define LSM6DSO_DATAWRITE_SLV0 0x21U +typedef struct +{ + uint8_t slave0_dataw : 8; +} lsm6dso_datawrite_src_mode_sub_slv0_t; + +#define LSM6DSO_STATUS_MASTER 0x22U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t sens_hub_endop : 1; + uint8_t not_used_01 : 2; + uint8_t slave0_nack : 1; + uint8_t slave1_nack : 1; + uint8_t slave2_nack : 1; + uint8_t slave3_nack : 1; + uint8_t wr_once_done : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t wr_once_done : 1; + uint8_t slave3_nack : 1; + uint8_t slave2_nack : 1; + uint8_t slave1_nack : 1; + uint8_t slave0_nack : 1; + uint8_t not_used_01 : 2; + uint8_t sens_hub_endop : 1; +#endif /* DRV_BYTE_ORDER */ +} lsm6dso_status_master_t; + +#define LSM6DSO_START_FSM_ADD 0x0400U + +/** + * @defgroup LSM6DSO_Register_Union + * @brief This union group all the registers having a bit-field + * description. + * This union is useful but it's not needed by the driver. + * + * REMOVING this union you are compliant with: + * MISRA-C 2012 [Rule 19.2] -> " Union are not allowed " + * + * @{ + * + */ +typedef union +{ + lsm6dso_func_cfg_access_t func_cfg_access; + lsm6dso_pin_ctrl_t pin_ctrl; + lsm6dso_fifo_ctrl1_t fifo_ctrl1; + lsm6dso_fifo_ctrl2_t fifo_ctrl2; + lsm6dso_fifo_ctrl3_t fifo_ctrl3; + lsm6dso_fifo_ctrl4_t fifo_ctrl4; + lsm6dso_counter_bdr_reg1_t counter_bdr_reg1; + lsm6dso_counter_bdr_reg2_t counter_bdr_reg2; + lsm6dso_int1_ctrl_t int1_ctrl; + lsm6dso_int2_ctrl_t int2_ctrl; + lsm6dso_ctrl1_xl_t ctrl1_xl; + lsm6dso_ctrl2_g_t ctrl2_g; + lsm6dso_ctrl3_c_t ctrl3_c; + lsm6dso_ctrl4_c_t ctrl4_c; + lsm6dso_ctrl5_c_t ctrl5_c; + lsm6dso_ctrl6_c_t ctrl6_c; + lsm6dso_ctrl7_g_t ctrl7_g; + lsm6dso_ctrl8_xl_t ctrl8_xl; + lsm6dso_ctrl9_xl_t ctrl9_xl; + lsm6dso_ctrl10_c_t ctrl10_c; + lsm6dso_all_int_src_t all_int_src; + lsm6dso_wake_up_src_t wake_up_src; + lsm6dso_tap_src_t tap_src; + lsm6dso_d6d_src_t d6d_src; + lsm6dso_status_reg_t status_reg; + lsm6dso_status_spiaux_t status_spiaux; + lsm6dso_fifo_status1_t fifo_status1; + lsm6dso_fifo_status2_t fifo_status2; + lsm6dso_tap_cfg0_t tap_cfg0; + lsm6dso_tap_cfg1_t tap_cfg1; + lsm6dso_tap_cfg2_t tap_cfg2; + lsm6dso_tap_ths_6d_t tap_ths_6d; + lsm6dso_int_dur2_t int_dur2; + lsm6dso_wake_up_ths_t wake_up_ths; + lsm6dso_wake_up_dur_t wake_up_dur; + lsm6dso_free_fall_t free_fall; + lsm6dso_md1_cfg_t md1_cfg; + lsm6dso_md2_cfg_t md2_cfg; + lsm6dso_i3c_bus_avb_t i3c_bus_avb; + lsm6dso_internal_freq_fine_t internal_freq_fine; + lsm6dso_int_ois_t int_ois; + lsm6dso_ctrl1_ois_t ctrl1_ois; + lsm6dso_ctrl2_ois_t ctrl2_ois; + lsm6dso_ctrl3_ois_t ctrl3_ois; + lsm6dso_fifo_data_out_tag_t fifo_data_out_tag; + lsm6dso_page_sel_t page_sel; + lsm6dso_emb_func_en_a_t emb_func_en_a; + lsm6dso_emb_func_en_b_t emb_func_en_b; + lsm6dso_page_address_t page_address; + lsm6dso_page_value_t page_value; + lsm6dso_emb_func_int1_t emb_func_int1; + lsm6dso_fsm_int1_a_t fsm_int1_a; + lsm6dso_fsm_int1_b_t fsm_int1_b; + lsm6dso_emb_func_int2_t emb_func_int2; + lsm6dso_fsm_int2_a_t fsm_int2_a; + lsm6dso_fsm_int2_b_t fsm_int2_b; + lsm6dso_emb_func_status_t emb_func_status; + lsm6dso_fsm_status_a_t fsm_status_a; + lsm6dso_fsm_status_b_t fsm_status_b; + lsm6dso_page_rw_t page_rw; + lsm6dso_emb_func_fifo_cfg_t emb_func_fifo_cfg; + lsm6dso_fsm_enable_a_t fsm_enable_a; + lsm6dso_fsm_enable_b_t fsm_enable_b; + lsm6dso_fsm_long_counter_clear_t fsm_long_counter_clear; + lsm6dso_fsm_outs1_t fsm_outs1; + lsm6dso_fsm_outs2_t fsm_outs2; + lsm6dso_fsm_outs3_t fsm_outs3; + lsm6dso_fsm_outs4_t fsm_outs4; + lsm6dso_fsm_outs5_t fsm_outs5; + lsm6dso_fsm_outs6_t fsm_outs6; + lsm6dso_fsm_outs7_t fsm_outs7; + lsm6dso_fsm_outs8_t fsm_outs8; + lsm6dso_fsm_outs9_t fsm_outs9; + lsm6dso_fsm_outs10_t fsm_outs10; + lsm6dso_fsm_outs11_t fsm_outs11; + lsm6dso_fsm_outs12_t fsm_outs12; + lsm6dso_fsm_outs13_t fsm_outs13; + lsm6dso_fsm_outs14_t fsm_outs14; + lsm6dso_fsm_outs15_t fsm_outs15; + lsm6dso_fsm_outs16_t fsm_outs16; + lsm6dso_emb_func_odr_cfg_b_t emb_func_odr_cfg_b; + lsm6dso_emb_func_src_t emb_func_src; + lsm6dso_emb_func_init_a_t emb_func_init_a; + lsm6dso_emb_func_init_b_t emb_func_init_b; + lsm6dso_mag_cfg_a_t mag_cfg_a; + lsm6dso_mag_cfg_b_t mag_cfg_b; + lsm6dso_pedo_cmd_reg_t pedo_cmd_reg; + lsm6dso_sensor_hub_1_t sensor_hub_1; + lsm6dso_sensor_hub_2_t sensor_hub_2; + lsm6dso_sensor_hub_3_t sensor_hub_3; + lsm6dso_sensor_hub_4_t sensor_hub_4; + lsm6dso_sensor_hub_5_t sensor_hub_5; + lsm6dso_sensor_hub_6_t sensor_hub_6; + lsm6dso_sensor_hub_7_t sensor_hub_7; + lsm6dso_sensor_hub_8_t sensor_hub_8; + lsm6dso_sensor_hub_9_t sensor_hub_9; + lsm6dso_sensor_hub_10_t sensor_hub_10; + lsm6dso_sensor_hub_11_t sensor_hub_11; + lsm6dso_sensor_hub_12_t sensor_hub_12; + lsm6dso_sensor_hub_13_t sensor_hub_13; + lsm6dso_sensor_hub_14_t sensor_hub_14; + lsm6dso_sensor_hub_15_t sensor_hub_15; + lsm6dso_sensor_hub_16_t sensor_hub_16; + lsm6dso_sensor_hub_17_t sensor_hub_17; + lsm6dso_sensor_hub_18_t sensor_hub_18; + lsm6dso_master_config_t master_config; + lsm6dso_slv0_add_t slv0_add; + lsm6dso_slv0_subadd_t slv0_subadd; + lsm6dso_slv0_config_t slv0_config; + lsm6dso_slv1_add_t slv1_add; + lsm6dso_slv1_subadd_t slv1_subadd; + lsm6dso_slv1_config_t slv1_config; + lsm6dso_slv2_add_t slv2_add; + lsm6dso_slv2_subadd_t slv2_subadd; + lsm6dso_slv2_config_t slv2_config; + lsm6dso_slv3_add_t slv3_add; + lsm6dso_slv3_subadd_t slv3_subadd; + lsm6dso_slv3_config_t slv3_config; + lsm6dso_datawrite_src_mode_sub_slv0_t datawrite_src_mode_sub_slv0; + lsm6dso_status_master_t status_master; + bitwise_t bitwise; + uint8_t byte; +} lsm6dso_reg_t; + +/** + * @} + * + */ + +float_t lsm6dso_from_fs2_to_mg(int16_t lsb); +float_t lsm6dso_from_fs4_to_mg(int16_t lsb); +float_t lsm6dso_from_fs8_to_mg(int16_t lsb); +float_t lsm6dso_from_fs16_to_mg(int16_t lsb); + +float_t lsm6dso_from_fs125_to_mdps(int16_t lsb); +float_t lsm6dso_from_fs500_to_mdps(int16_t lsb); +float_t lsm6dso_from_fs250_to_mdps(int16_t lsb); +float_t lsm6dso_from_fs1000_to_mdps(int16_t lsb); +float_t lsm6dso_from_fs2000_to_mdps(int16_t lsb); + +float_t lsm6dso_from_lsb_to_celsius(int16_t lsb); + +float_t lsm6dso_from_lsb_to_nsec(int16_t lsb); + +typedef enum +{ + LSM6DSO_2g = 0, + LSM6DSO_16g = 1, /* if XL_FS_MODE = '1' -> LSM6DSO_2g */ + LSM6DSO_4g = 2, + LSM6DSO_8g = 3, +} lsm6dso_fs_xl_t; +int32_t lsm6dso_xl_full_scale_set(stmdev_ctx_t *ctx, + lsm6dso_fs_xl_t val); +int32_t lsm6dso_xl_full_scale_get(stmdev_ctx_t *ctx, + lsm6dso_fs_xl_t *val); + +typedef enum +{ + LSM6DSO_XL_ODR_OFF = 0, + LSM6DSO_XL_ODR_12Hz5 = 1, + LSM6DSO_XL_ODR_26Hz = 2, + LSM6DSO_XL_ODR_52Hz = 3, + LSM6DSO_XL_ODR_104Hz = 4, + LSM6DSO_XL_ODR_208Hz = 5, + LSM6DSO_XL_ODR_417Hz = 6, + LSM6DSO_XL_ODR_833Hz = 7, + LSM6DSO_XL_ODR_1667Hz = 8, + LSM6DSO_XL_ODR_3333Hz = 9, + LSM6DSO_XL_ODR_6667Hz = 10, + LSM6DSO_XL_ODR_1Hz6 = 11, /* (low power only) */ +} lsm6dso_odr_xl_t; +int32_t lsm6dso_xl_data_rate_set(stmdev_ctx_t *ctx, + lsm6dso_odr_xl_t val); +int32_t lsm6dso_xl_data_rate_get(stmdev_ctx_t *ctx, + lsm6dso_odr_xl_t *val); + +typedef enum +{ + LSM6DSO_250dps = 0, + LSM6DSO_125dps = 1, + LSM6DSO_500dps = 2, + LSM6DSO_1000dps = 4, + LSM6DSO_2000dps = 6, +} lsm6dso_fs_g_t; +int32_t lsm6dso_gy_full_scale_set(stmdev_ctx_t *ctx, + lsm6dso_fs_g_t val); +int32_t lsm6dso_gy_full_scale_get(stmdev_ctx_t *ctx, + lsm6dso_fs_g_t *val); + +typedef enum +{ + LSM6DSO_GY_ODR_OFF = 0, + LSM6DSO_GY_ODR_12Hz5 = 1, + LSM6DSO_GY_ODR_26Hz = 2, + LSM6DSO_GY_ODR_52Hz = 3, + LSM6DSO_GY_ODR_104Hz = 4, + LSM6DSO_GY_ODR_208Hz = 5, + LSM6DSO_GY_ODR_417Hz = 6, + LSM6DSO_GY_ODR_833Hz = 7, + LSM6DSO_GY_ODR_1667Hz = 8, + LSM6DSO_GY_ODR_3333Hz = 9, + LSM6DSO_GY_ODR_6667Hz = 10, +} lsm6dso_odr_g_t; +int32_t lsm6dso_gy_data_rate_set(stmdev_ctx_t *ctx, + lsm6dso_odr_g_t val); +int32_t lsm6dso_gy_data_rate_get(stmdev_ctx_t *ctx, + lsm6dso_odr_g_t *val); + +int32_t lsm6dso_block_data_update_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_block_data_update_get(stmdev_ctx_t *ctx, + uint8_t *val); + +typedef enum +{ + LSM6DSO_LSb_1mg = 0, + LSM6DSO_LSb_16mg = 1, +} lsm6dso_usr_off_w_t; +int32_t lsm6dso_xl_offset_weight_set(stmdev_ctx_t *ctx, + lsm6dso_usr_off_w_t val); +int32_t lsm6dso_xl_offset_weight_get(stmdev_ctx_t *ctx, + lsm6dso_usr_off_w_t *val); + +typedef enum +{ + LSM6DSO_HIGH_PERFORMANCE_MD = 0, + LSM6DSO_LOW_NORMAL_POWER_MD = 1, + LSM6DSO_ULTRA_LOW_POWER_MD = 2, +} lsm6dso_xl_hm_mode_t; +int32_t lsm6dso_xl_power_mode_set(stmdev_ctx_t *ctx, + lsm6dso_xl_hm_mode_t val); +int32_t lsm6dso_xl_power_mode_get(stmdev_ctx_t *ctx, + lsm6dso_xl_hm_mode_t *val); + +typedef enum +{ + LSM6DSO_GY_HIGH_PERFORMANCE = 0, + LSM6DSO_GY_NORMAL = 1, +} lsm6dso_g_hm_mode_t; +int32_t lsm6dso_gy_power_mode_set(stmdev_ctx_t *ctx, + lsm6dso_g_hm_mode_t val); +int32_t lsm6dso_gy_power_mode_get(stmdev_ctx_t *ctx, + lsm6dso_g_hm_mode_t *val); + +int32_t lsm6dso_status_reg_get(stmdev_ctx_t *ctx, + lsm6dso_status_reg_t *val); + +int32_t lsm6dso_xl_flag_data_ready_get(stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6dso_gy_flag_data_ready_get(stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6dso_temp_flag_data_ready_get(stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6dso_xl_usr_offset_x_set(stmdev_ctx_t *ctx, uint8_t *buff); +int32_t lsm6dso_xl_usr_offset_x_get(stmdev_ctx_t *ctx, uint8_t *buff); + +int32_t lsm6dso_xl_usr_offset_y_set(stmdev_ctx_t *ctx, uint8_t *buff); +int32_t lsm6dso_xl_usr_offset_y_get(stmdev_ctx_t *ctx, uint8_t *buff); + +int32_t lsm6dso_xl_usr_offset_z_set(stmdev_ctx_t *ctx, uint8_t *buff); +int32_t lsm6dso_xl_usr_offset_z_get(stmdev_ctx_t *ctx, uint8_t *buff); + +int32_t lsm6dso_xl_usr_offset_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_xl_usr_offset_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6dso_timestamp_rst(stmdev_ctx_t *ctx); + +int32_t lsm6dso_timestamp_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_timestamp_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6dso_timestamp_raw_get(stmdev_ctx_t *ctx, uint32_t *val); + +typedef enum +{ + LSM6DSO_NO_ROUND = 0, + LSM6DSO_ROUND_XL = 1, + LSM6DSO_ROUND_GY = 2, + LSM6DSO_ROUND_GY_XL = 3, +} lsm6dso_rounding_t; +int32_t lsm6dso_rounding_mode_set(stmdev_ctx_t *ctx, + lsm6dso_rounding_t val); +int32_t lsm6dso_rounding_mode_get(stmdev_ctx_t *ctx, + lsm6dso_rounding_t *val); + +int32_t lsm6dso_temperature_raw_get(stmdev_ctx_t *ctx, int16_t *val); + +int32_t lsm6dso_angular_rate_raw_get(stmdev_ctx_t *ctx, + int16_t *val); + +int32_t lsm6dso_acceleration_raw_get(stmdev_ctx_t *ctx, + int16_t *val); + +int32_t lsm6dso_fifo_out_raw_get(stmdev_ctx_t *ctx, uint8_t *buff); + +int32_t lsm6dso_number_of_steps_get(stmdev_ctx_t *ctx, uint16_t *val); + +int32_t lsm6dso_steps_reset(stmdev_ctx_t *ctx); + +int32_t lsm6dso_odr_cal_reg_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_odr_cal_reg_get(stmdev_ctx_t *ctx, uint8_t *val); + +typedef enum +{ + LSM6DSO_USER_BANK = 0, + LSM6DSO_SENSOR_HUB_BANK = 1, + LSM6DSO_EMBEDDED_FUNC_BANK = 2, +} lsm6dso_reg_access_t; +int32_t lsm6dso_mem_bank_set(stmdev_ctx_t *ctx, + lsm6dso_reg_access_t val); +int32_t lsm6dso_mem_bank_get(stmdev_ctx_t *ctx, + lsm6dso_reg_access_t *val); + +int32_t lsm6dso_ln_pg_write_byte(stmdev_ctx_t *ctx, uint16_t address, + uint8_t *val); +int32_t lsm6dso_ln_pg_read_byte(stmdev_ctx_t *ctx, uint16_t address, + uint8_t *val); +int32_t lsm6dso_ln_pg_write(stmdev_ctx_t *ctx, uint16_t address, + uint8_t *buf, uint8_t len); +int32_t lsm6dso_ln_pg_read(stmdev_ctx_t *ctx, uint16_t address, + uint8_t *val); + +typedef enum +{ + LSM6DSO_DRDY_LATCHED = 0, + LSM6DSO_DRDY_PULSED = 1, +} lsm6dso_dataready_pulsed_t; +int32_t lsm6dso_data_ready_mode_set(stmdev_ctx_t *ctx, + lsm6dso_dataready_pulsed_t val); +int32_t lsm6dso_data_ready_mode_get(stmdev_ctx_t *ctx, + lsm6dso_dataready_pulsed_t *val); + +int32_t lsm6dso_device_id_get(stmdev_ctx_t *ctx, uint8_t *buff); + +int32_t lsm6dso_reset_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_reset_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6dso_auto_increment_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_auto_increment_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6dso_boot_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_boot_get(stmdev_ctx_t *ctx, uint8_t *val); + +typedef enum +{ + LSM6DSO_XL_ST_DISABLE = 0, + LSM6DSO_XL_ST_POSITIVE = 1, + LSM6DSO_XL_ST_NEGATIVE = 2, +} lsm6dso_st_xl_t; +int32_t lsm6dso_xl_self_test_set(stmdev_ctx_t *ctx, + lsm6dso_st_xl_t val); +int32_t lsm6dso_xl_self_test_get(stmdev_ctx_t *ctx, + lsm6dso_st_xl_t *val); + +typedef enum +{ + LSM6DSO_GY_ST_DISABLE = 0, + LSM6DSO_GY_ST_POSITIVE = 1, + LSM6DSO_GY_ST_NEGATIVE = 3, +} lsm6dso_st_g_t; +int32_t lsm6dso_gy_self_test_set(stmdev_ctx_t *ctx, + lsm6dso_st_g_t val); +int32_t lsm6dso_gy_self_test_get(stmdev_ctx_t *ctx, + lsm6dso_st_g_t *val); + +int32_t lsm6dso_xl_filter_lp2_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_xl_filter_lp2_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6dso_gy_filter_lp1_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_gy_filter_lp1_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6dso_filter_settling_mask_set(stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6dso_filter_settling_mask_get(stmdev_ctx_t *ctx, + uint8_t *val); + +typedef enum +{ + LSM6DSO_ULTRA_LIGHT = 0, + LSM6DSO_VERY_LIGHT = 1, + LSM6DSO_LIGHT = 2, + LSM6DSO_MEDIUM = 3, + LSM6DSO_STRONG = 4, /* not available for data rate > 1k670Hz */ + LSM6DSO_VERY_STRONG = 5, /* not available for data rate > 1k670Hz */ + LSM6DSO_AGGRESSIVE = 6, /* not available for data rate > 1k670Hz */ + LSM6DSO_XTREME = 7, /* not available for data rate > 1k670Hz */ +} lsm6dso_ftype_t; +int32_t lsm6dso_gy_lp1_bandwidth_set(stmdev_ctx_t *ctx, + lsm6dso_ftype_t val); +int32_t lsm6dso_gy_lp1_bandwidth_get(stmdev_ctx_t *ctx, + lsm6dso_ftype_t *val); + +int32_t lsm6dso_xl_lp2_on_6d_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_xl_lp2_on_6d_get(stmdev_ctx_t *ctx, uint8_t *val); + +typedef enum +{ + LSM6DSO_HP_PATH_DISABLE_ON_OUT = 0x00, + LSM6DSO_SLOPE_ODR_DIV_4 = 0x10, + LSM6DSO_HP_ODR_DIV_10 = 0x11, + LSM6DSO_HP_ODR_DIV_20 = 0x12, + LSM6DSO_HP_ODR_DIV_45 = 0x13, + LSM6DSO_HP_ODR_DIV_100 = 0x14, + LSM6DSO_HP_ODR_DIV_200 = 0x15, + LSM6DSO_HP_ODR_DIV_400 = 0x16, + LSM6DSO_HP_ODR_DIV_800 = 0x17, + LSM6DSO_HP_REF_MD_ODR_DIV_10 = 0x31, + LSM6DSO_HP_REF_MD_ODR_DIV_20 = 0x32, + LSM6DSO_HP_REF_MD_ODR_DIV_45 = 0x33, + LSM6DSO_HP_REF_MD_ODR_DIV_100 = 0x34, + LSM6DSO_HP_REF_MD_ODR_DIV_200 = 0x35, + LSM6DSO_HP_REF_MD_ODR_DIV_400 = 0x36, + LSM6DSO_HP_REF_MD_ODR_DIV_800 = 0x37, + LSM6DSO_LP_ODR_DIV_10 = 0x01, + LSM6DSO_LP_ODR_DIV_20 = 0x02, + LSM6DSO_LP_ODR_DIV_45 = 0x03, + LSM6DSO_LP_ODR_DIV_100 = 0x04, + LSM6DSO_LP_ODR_DIV_200 = 0x05, + LSM6DSO_LP_ODR_DIV_400 = 0x06, + LSM6DSO_LP_ODR_DIV_800 = 0x07, +} lsm6dso_hp_slope_xl_en_t; +int32_t lsm6dso_xl_hp_path_on_out_set(stmdev_ctx_t *ctx, + lsm6dso_hp_slope_xl_en_t val); +int32_t lsm6dso_xl_hp_path_on_out_get(stmdev_ctx_t *ctx, + lsm6dso_hp_slope_xl_en_t *val); + +int32_t lsm6dso_xl_fast_settling_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_xl_fast_settling_get(stmdev_ctx_t *ctx, uint8_t *val); + +typedef enum +{ + LSM6DSO_USE_SLOPE = 0, + LSM6DSO_USE_HPF = 1, +} lsm6dso_slope_fds_t; +int32_t lsm6dso_xl_hp_path_internal_set(stmdev_ctx_t *ctx, + lsm6dso_slope_fds_t val); +int32_t lsm6dso_xl_hp_path_internal_get(stmdev_ctx_t *ctx, + lsm6dso_slope_fds_t *val); + +typedef enum +{ + LSM6DSO_HP_FILTER_NONE = 0x00, + LSM6DSO_HP_FILTER_16mHz = 0x80, + LSM6DSO_HP_FILTER_65mHz = 0x81, + LSM6DSO_HP_FILTER_260mHz = 0x82, + LSM6DSO_HP_FILTER_1Hz04 = 0x83, +} lsm6dso_hpm_g_t; +int32_t lsm6dso_gy_hp_path_internal_set(stmdev_ctx_t *ctx, + lsm6dso_hpm_g_t val); +int32_t lsm6dso_gy_hp_path_internal_get(stmdev_ctx_t *ctx, + lsm6dso_hpm_g_t *val); + +typedef enum +{ + LSM6DSO_AUX_PULL_UP_DISC = 0, + LSM6DSO_AUX_PULL_UP_CONNECT = 1, +} lsm6dso_ois_pu_dis_t; +int32_t lsm6dso_aux_sdo_ocs_mode_set(stmdev_ctx_t *ctx, + lsm6dso_ois_pu_dis_t val); +int32_t lsm6dso_aux_sdo_ocs_mode_get(stmdev_ctx_t *ctx, + lsm6dso_ois_pu_dis_t *val); + +typedef enum +{ + LSM6DSO_AUX_ON = 1, + LSM6DSO_AUX_ON_BY_AUX_INTERFACE = 0, +} lsm6dso_ois_on_t; +int32_t lsm6dso_aux_pw_on_ctrl_set(stmdev_ctx_t *ctx, + lsm6dso_ois_on_t val); +int32_t lsm6dso_aux_pw_on_ctrl_get(stmdev_ctx_t *ctx, + lsm6dso_ois_on_t *val); + +typedef enum +{ + LSM6DSO_USE_SAME_XL_FS = 0, + LSM6DSO_USE_DIFFERENT_XL_FS = 1, +} lsm6dso_xl_fs_mode_t; +int32_t lsm6dso_aux_xl_fs_mode_set(stmdev_ctx_t *ctx, + lsm6dso_xl_fs_mode_t val); +int32_t lsm6dso_aux_xl_fs_mode_get(stmdev_ctx_t *ctx, + lsm6dso_xl_fs_mode_t *val); + +int32_t lsm6dso_aux_status_reg_get(stmdev_ctx_t *ctx, + lsm6dso_status_spiaux_t *val); + +int32_t lsm6dso_aux_xl_flag_data_ready_get(stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6dso_aux_gy_flag_data_ready_get(stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6dso_aux_gy_flag_settling_get(stmdev_ctx_t *ctx, + uint8_t *val); + +typedef enum +{ + LSM6DSO_AUX_XL_DISABLE = 0, + LSM6DSO_AUX_XL_POS = 1, + LSM6DSO_AUX_XL_NEG = 2, +} lsm6dso_st_xl_ois_t; +int32_t lsm6dso_aux_xl_self_test_set(stmdev_ctx_t *ctx, + lsm6dso_st_xl_ois_t val); +int32_t lsm6dso_aux_xl_self_test_get(stmdev_ctx_t *ctx, + lsm6dso_st_xl_ois_t *val); + +typedef enum +{ + LSM6DSO_AUX_DEN_ACTIVE_LOW = 0, + LSM6DSO_AUX_DEN_ACTIVE_HIGH = 1, +} lsm6dso_den_lh_ois_t; +int32_t lsm6dso_aux_den_polarity_set(stmdev_ctx_t *ctx, + lsm6dso_den_lh_ois_t val); +int32_t lsm6dso_aux_den_polarity_get(stmdev_ctx_t *ctx, + lsm6dso_den_lh_ois_t *val); + +typedef enum +{ + LSM6DSO_AUX_DEN_DISABLE = 0, + LSM6DSO_AUX_DEN_LEVEL_LATCH = 3, + LSM6DSO_AUX_DEN_LEVEL_TRIG = 2, +} lsm6dso_lvl2_ois_t; +int32_t lsm6dso_aux_den_mode_set(stmdev_ctx_t *ctx, + lsm6dso_lvl2_ois_t val); +int32_t lsm6dso_aux_den_mode_get(stmdev_ctx_t *ctx, + lsm6dso_lvl2_ois_t *val); + +int32_t lsm6dso_aux_drdy_on_int2_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_aux_drdy_on_int2_get(stmdev_ctx_t *ctx, uint8_t *val); + +typedef enum +{ + LSM6DSO_AUX_DISABLE = 0, + LSM6DSO_MODE_3_GY = 1, + LSM6DSO_MODE_4_GY_XL = 3, +} lsm6dso_ois_en_spi2_t; +int32_t lsm6dso_aux_mode_set(stmdev_ctx_t *ctx, + lsm6dso_ois_en_spi2_t val); +int32_t lsm6dso_aux_mode_get(stmdev_ctx_t *ctx, + lsm6dso_ois_en_spi2_t *val); + +typedef enum +{ + LSM6DSO_250dps_AUX = 0, + LSM6DSO_125dps_AUX = 1, + LSM6DSO_500dps_AUX = 2, + LSM6DSO_1000dps_AUX = 4, + LSM6DSO_2000dps_AUX = 6, +} lsm6dso_fs_g_ois_t; +int32_t lsm6dso_aux_gy_full_scale_set(stmdev_ctx_t *ctx, + lsm6dso_fs_g_ois_t val); +int32_t lsm6dso_aux_gy_full_scale_get(stmdev_ctx_t *ctx, + lsm6dso_fs_g_ois_t *val); + +typedef enum +{ + LSM6DSO_AUX_SPI_4_WIRE = 0, + LSM6DSO_AUX_SPI_3_WIRE = 1, +} lsm6dso_sim_ois_t; +int32_t lsm6dso_aux_spi_mode_set(stmdev_ctx_t *ctx, + lsm6dso_sim_ois_t val); +int32_t lsm6dso_aux_spi_mode_get(stmdev_ctx_t *ctx, + lsm6dso_sim_ois_t *val); + +typedef enum +{ + LSM6DSO_351Hz39 = 0, + LSM6DSO_236Hz63 = 1, + LSM6DSO_172Hz70 = 2, + LSM6DSO_937Hz91 = 3, +} lsm6dso_ftype_ois_t; +int32_t lsm6dso_aux_gy_lp1_bandwidth_set(stmdev_ctx_t *ctx, + lsm6dso_ftype_ois_t val); +int32_t lsm6dso_aux_gy_lp1_bandwidth_get(stmdev_ctx_t *ctx, + lsm6dso_ftype_ois_t *val); + +typedef enum +{ + LSM6DSO_AUX_HP_DISABLE = 0x00, + LSM6DSO_AUX_HP_Hz016 = 0x10, + LSM6DSO_AUX_HP_Hz065 = 0x11, + LSM6DSO_AUX_HP_Hz260 = 0x12, + LSM6DSO_AUX_HP_1Hz040 = 0x13, +} lsm6dso_hpm_ois_t; +int32_t lsm6dso_aux_gy_hp_bandwidth_set(stmdev_ctx_t *ctx, + lsm6dso_hpm_ois_t val); +int32_t lsm6dso_aux_gy_hp_bandwidth_get(stmdev_ctx_t *ctx, + lsm6dso_hpm_ois_t *val); + +typedef enum +{ + LSM6DSO_ENABLE_CLAMP = 0, + LSM6DSO_DISABLE_CLAMP = 1, +} lsm6dso_st_ois_clampdis_t; +int32_t lsm6dso_aux_gy_clamp_set(stmdev_ctx_t *ctx, + lsm6dso_st_ois_clampdis_t val); +int32_t lsm6dso_aux_gy_clamp_get(stmdev_ctx_t *ctx, + lsm6dso_st_ois_clampdis_t *val); + +typedef enum +{ + LSM6DSO_AUX_GY_DISABLE = 0, + LSM6DSO_AUX_GY_POS = 1, + LSM6DSO_AUX_GY_NEG = 3, +} lsm6dso_st_ois_t; +int32_t lsm6dso_aux_gy_self_test_set(stmdev_ctx_t *ctx, + lsm6dso_st_ois_t val); +int32_t lsm6dso_aux_gy_self_test_get(stmdev_ctx_t *ctx, + lsm6dso_st_ois_t *val); + +typedef enum +{ + LSM6DSO_289Hz = 0, + LSM6DSO_258Hz = 1, + LSM6DSO_120Hz = 2, + LSM6DSO_65Hz2 = 3, + LSM6DSO_33Hz2 = 4, + LSM6DSO_16Hz6 = 5, + LSM6DSO_8Hz30 = 6, + LSM6DSO_4Hz15 = 7, +} lsm6dso_filter_xl_conf_ois_t; +int32_t lsm6dso_aux_xl_bandwidth_set(stmdev_ctx_t *ctx, + lsm6dso_filter_xl_conf_ois_t val); +int32_t lsm6dso_aux_xl_bandwidth_get(stmdev_ctx_t *ctx, + lsm6dso_filter_xl_conf_ois_t *val); + +typedef enum +{ + LSM6DSO_AUX_2g = 0, + LSM6DSO_AUX_16g = 1, + LSM6DSO_AUX_4g = 2, + LSM6DSO_AUX_8g = 3, +} lsm6dso_fs_xl_ois_t; +int32_t lsm6dso_aux_xl_full_scale_set(stmdev_ctx_t *ctx, + lsm6dso_fs_xl_ois_t val); +int32_t lsm6dso_aux_xl_full_scale_get(stmdev_ctx_t *ctx, + lsm6dso_fs_xl_ois_t *val); + +typedef enum +{ + LSM6DSO_PULL_UP_DISC = 0, + LSM6DSO_PULL_UP_CONNECT = 1, +} lsm6dso_sdo_pu_en_t; +int32_t lsm6dso_sdo_sa0_mode_set(stmdev_ctx_t *ctx, + lsm6dso_sdo_pu_en_t val); +int32_t lsm6dso_sdo_sa0_mode_get(stmdev_ctx_t *ctx, + lsm6dso_sdo_pu_en_t *val); + +typedef enum +{ + LSM6DSO_SPI_4_WIRE = 0, + LSM6DSO_SPI_3_WIRE = 1, +} lsm6dso_sim_t; +int32_t lsm6dso_spi_mode_set(stmdev_ctx_t *ctx, lsm6dso_sim_t val); +int32_t lsm6dso_spi_mode_get(stmdev_ctx_t *ctx, lsm6dso_sim_t *val); + +typedef enum +{ + LSM6DSO_I2C_ENABLE = 0, + LSM6DSO_I2C_DISABLE = 1, +} lsm6dso_i2c_disable_t; +int32_t lsm6dso_i2c_interface_set(stmdev_ctx_t *ctx, + lsm6dso_i2c_disable_t val); +int32_t lsm6dso_i2c_interface_get(stmdev_ctx_t *ctx, + lsm6dso_i2c_disable_t *val); + +typedef enum +{ + LSM6DSO_I3C_DISABLE = 0x80, + LSM6DSO_I3C_ENABLE_T_50us = 0x00, + LSM6DSO_I3C_ENABLE_T_2us = 0x01, + LSM6DSO_I3C_ENABLE_T_1ms = 0x02, + LSM6DSO_I3C_ENABLE_T_25ms = 0x03, +} lsm6dso_i3c_disable_t; +int32_t lsm6dso_i3c_disable_set(stmdev_ctx_t *ctx, + lsm6dso_i3c_disable_t val); +int32_t lsm6dso_i3c_disable_get(stmdev_ctx_t *ctx, + lsm6dso_i3c_disable_t *val); + +typedef enum +{ + LSM6DSO_PULL_DOWN_DISC = 0, + LSM6DSO_PULL_DOWN_CONNECT = 1, +} lsm6dso_int1_pd_en_t; +int32_t lsm6dso_int1_mode_set(stmdev_ctx_t *ctx, + lsm6dso_int1_pd_en_t val); +int32_t lsm6dso_int1_mode_get(stmdev_ctx_t *ctx, + lsm6dso_int1_pd_en_t *val); + +typedef enum +{ + LSM6DSO_PUSH_PULL = 0, + LSM6DSO_OPEN_DRAIN = 1, +} lsm6dso_pp_od_t; +int32_t lsm6dso_pin_mode_set(stmdev_ctx_t *ctx, lsm6dso_pp_od_t val); +int32_t lsm6dso_pin_mode_get(stmdev_ctx_t *ctx, lsm6dso_pp_od_t *val); + +typedef enum +{ + LSM6DSO_ACTIVE_HIGH = 0, + LSM6DSO_ACTIVE_LOW = 1, +} lsm6dso_h_lactive_t; +int32_t lsm6dso_pin_polarity_set(stmdev_ctx_t *ctx, + lsm6dso_h_lactive_t val); +int32_t lsm6dso_pin_polarity_get(stmdev_ctx_t *ctx, + lsm6dso_h_lactive_t *val); + +int32_t lsm6dso_all_on_int1_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_all_on_int1_get(stmdev_ctx_t *ctx, uint8_t *val); + +typedef enum +{ + LSM6DSO_ALL_INT_PULSED = 0, + LSM6DSO_BASE_LATCHED_EMB_PULSED = 1, + LSM6DSO_BASE_PULSED_EMB_LATCHED = 2, + LSM6DSO_ALL_INT_LATCHED = 3, +} lsm6dso_lir_t; +int32_t lsm6dso_int_notification_set(stmdev_ctx_t *ctx, + lsm6dso_lir_t val); +int32_t lsm6dso_int_notification_get(stmdev_ctx_t *ctx, + lsm6dso_lir_t *val); + +typedef enum +{ + LSM6DSO_LSb_FS_DIV_64 = 0, + LSM6DSO_LSb_FS_DIV_256 = 1, +} lsm6dso_wake_ths_w_t; +int32_t lsm6dso_wkup_ths_weight_set(stmdev_ctx_t *ctx, + lsm6dso_wake_ths_w_t val); +int32_t lsm6dso_wkup_ths_weight_get(stmdev_ctx_t *ctx, + lsm6dso_wake_ths_w_t *val); + +int32_t lsm6dso_wkup_threshold_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_wkup_threshold_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6dso_xl_usr_offset_on_wkup_set(stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6dso_xl_usr_offset_on_wkup_get(stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6dso_wkup_dur_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_wkup_dur_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6dso_gy_sleep_mode_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_gy_sleep_mode_get(stmdev_ctx_t *ctx, uint8_t *val); + +typedef enum +{ + LSM6DSO_DRIVE_SLEEP_CHG_EVENT = 0, + LSM6DSO_DRIVE_SLEEP_STATUS = 1, +} lsm6dso_sleep_status_on_int_t; +int32_t lsm6dso_act_pin_notification_set(stmdev_ctx_t *ctx, + lsm6dso_sleep_status_on_int_t val); +int32_t lsm6dso_act_pin_notification_get(stmdev_ctx_t *ctx, + lsm6dso_sleep_status_on_int_t *val); + +typedef enum +{ + LSM6DSO_XL_AND_GY_NOT_AFFECTED = 0, + LSM6DSO_XL_12Hz5_GY_NOT_AFFECTED = 1, + LSM6DSO_XL_12Hz5_GY_SLEEP = 2, + LSM6DSO_XL_12Hz5_GY_PD = 3, +} lsm6dso_inact_en_t; +int32_t lsm6dso_act_mode_set(stmdev_ctx_t *ctx, + lsm6dso_inact_en_t val); +int32_t lsm6dso_act_mode_get(stmdev_ctx_t *ctx, + lsm6dso_inact_en_t *val); + +int32_t lsm6dso_act_sleep_dur_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_act_sleep_dur_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6dso_tap_detection_on_z_set(stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6dso_tap_detection_on_z_get(stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6dso_tap_detection_on_y_set(stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6dso_tap_detection_on_y_get(stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6dso_tap_detection_on_x_set(stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6dso_tap_detection_on_x_get(stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6dso_tap_threshold_x_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_tap_threshold_x_get(stmdev_ctx_t *ctx, uint8_t *val); + +typedef enum +{ + LSM6DSO_XYZ = 0, + LSM6DSO_YXZ = 1, + LSM6DSO_XZY = 2, + LSM6DSO_ZYX = 3, + LSM6DSO_YZX = 5, + LSM6DSO_ZXY = 6, +} lsm6dso_tap_priority_t; +int32_t lsm6dso_tap_axis_priority_set(stmdev_ctx_t *ctx, + lsm6dso_tap_priority_t val); +int32_t lsm6dso_tap_axis_priority_get(stmdev_ctx_t *ctx, + lsm6dso_tap_priority_t *val); + +int32_t lsm6dso_tap_threshold_y_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_tap_threshold_y_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6dso_tap_threshold_z_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_tap_threshold_z_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6dso_tap_shock_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_tap_shock_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6dso_tap_quiet_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_tap_quiet_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6dso_tap_dur_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_tap_dur_get(stmdev_ctx_t *ctx, uint8_t *val); + +typedef enum +{ + LSM6DSO_ONLY_SINGLE = 0, + LSM6DSO_BOTH_SINGLE_DOUBLE = 1, +} lsm6dso_single_double_tap_t; +int32_t lsm6dso_tap_mode_set(stmdev_ctx_t *ctx, + lsm6dso_single_double_tap_t val); +int32_t lsm6dso_tap_mode_get(stmdev_ctx_t *ctx, + lsm6dso_single_double_tap_t *val); + +typedef enum +{ + LSM6DSO_DEG_80 = 0, + LSM6DSO_DEG_70 = 1, + LSM6DSO_DEG_60 = 2, + LSM6DSO_DEG_50 = 3, +} lsm6dso_sixd_ths_t; +int32_t lsm6dso_6d_threshold_set(stmdev_ctx_t *ctx, + lsm6dso_sixd_ths_t val); +int32_t lsm6dso_6d_threshold_get(stmdev_ctx_t *ctx, + lsm6dso_sixd_ths_t *val); + +int32_t lsm6dso_4d_mode_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_4d_mode_get(stmdev_ctx_t *ctx, uint8_t *val); + +typedef enum +{ + LSM6DSO_FF_TSH_156mg = 0, + LSM6DSO_FF_TSH_219mg = 1, + LSM6DSO_FF_TSH_250mg = 2, + LSM6DSO_FF_TSH_312mg = 3, + LSM6DSO_FF_TSH_344mg = 4, + LSM6DSO_FF_TSH_406mg = 5, + LSM6DSO_FF_TSH_469mg = 6, + LSM6DSO_FF_TSH_500mg = 7, +} lsm6dso_ff_ths_t; +int32_t lsm6dso_ff_threshold_set(stmdev_ctx_t *ctx, + lsm6dso_ff_ths_t val); +int32_t lsm6dso_ff_threshold_get(stmdev_ctx_t *ctx, + lsm6dso_ff_ths_t *val); + +int32_t lsm6dso_ff_dur_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_ff_dur_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6dso_fifo_watermark_set(stmdev_ctx_t *ctx, uint16_t val); +int32_t lsm6dso_fifo_watermark_get(stmdev_ctx_t *ctx, uint16_t *val); + +int32_t lsm6dso_compression_algo_init_set(stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6dso_compression_algo_init_get(stmdev_ctx_t *ctx, + uint8_t *val); + +typedef enum +{ + LSM6DSO_CMP_DISABLE = 0x00, + LSM6DSO_CMP_ALWAYS = 0x04, + LSM6DSO_CMP_8_TO_1 = 0x05, + LSM6DSO_CMP_16_TO_1 = 0x06, + LSM6DSO_CMP_32_TO_1 = 0x07, +} lsm6dso_uncoptr_rate_t; +int32_t lsm6dso_compression_algo_set(stmdev_ctx_t *ctx, + lsm6dso_uncoptr_rate_t val); +int32_t lsm6dso_compression_algo_get(stmdev_ctx_t *ctx, + lsm6dso_uncoptr_rate_t *val); + +int32_t lsm6dso_fifo_virtual_sens_odr_chg_set(stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6dso_fifo_virtual_sens_odr_chg_get(stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6dso_compression_algo_real_time_set(stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6dso_compression_algo_real_time_get(stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6dso_fifo_stop_on_wtm_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_fifo_stop_on_wtm_get(stmdev_ctx_t *ctx, uint8_t *val); + +typedef enum +{ + LSM6DSO_XL_NOT_BATCHED = 0, + LSM6DSO_XL_BATCHED_AT_12Hz5 = 1, + LSM6DSO_XL_BATCHED_AT_26Hz = 2, + LSM6DSO_XL_BATCHED_AT_52Hz = 3, + LSM6DSO_XL_BATCHED_AT_104Hz = 4, + LSM6DSO_XL_BATCHED_AT_208Hz = 5, + LSM6DSO_XL_BATCHED_AT_417Hz = 6, + LSM6DSO_XL_BATCHED_AT_833Hz = 7, + LSM6DSO_XL_BATCHED_AT_1667Hz = 8, + LSM6DSO_XL_BATCHED_AT_3333Hz = 9, + LSM6DSO_XL_BATCHED_AT_6667Hz = 10, + LSM6DSO_XL_BATCHED_AT_6Hz5 = 11, +} lsm6dso_bdr_xl_t; +int32_t lsm6dso_fifo_xl_batch_set(stmdev_ctx_t *ctx, + lsm6dso_bdr_xl_t val); +int32_t lsm6dso_fifo_xl_batch_get(stmdev_ctx_t *ctx, + lsm6dso_bdr_xl_t *val); + +typedef enum +{ + LSM6DSO_GY_NOT_BATCHED = 0, + LSM6DSO_GY_BATCHED_AT_12Hz5 = 1, + LSM6DSO_GY_BATCHED_AT_26Hz = 2, + LSM6DSO_GY_BATCHED_AT_52Hz = 3, + LSM6DSO_GY_BATCHED_AT_104Hz = 4, + LSM6DSO_GY_BATCHED_AT_208Hz = 5, + LSM6DSO_GY_BATCHED_AT_417Hz = 6, + LSM6DSO_GY_BATCHED_AT_833Hz = 7, + LSM6DSO_GY_BATCHED_AT_1667Hz = 8, + LSM6DSO_GY_BATCHED_AT_3333Hz = 9, + LSM6DSO_GY_BATCHED_AT_6667Hz = 10, + LSM6DSO_GY_BATCHED_AT_6Hz5 = 11, +} lsm6dso_bdr_gy_t; +int32_t lsm6dso_fifo_gy_batch_set(stmdev_ctx_t *ctx, + lsm6dso_bdr_gy_t val); +int32_t lsm6dso_fifo_gy_batch_get(stmdev_ctx_t *ctx, + lsm6dso_bdr_gy_t *val); + +typedef enum +{ + LSM6DSO_BYPASS_MODE = 0, + LSM6DSO_FIFO_MODE = 1, + LSM6DSO_STREAM_TO_FIFO_MODE = 3, + LSM6DSO_BYPASS_TO_STREAM_MODE = 4, + LSM6DSO_STREAM_MODE = 6, + LSM6DSO_BYPASS_TO_FIFO_MODE = 7, +} lsm6dso_fifo_mode_t; +int32_t lsm6dso_fifo_mode_set(stmdev_ctx_t *ctx, + lsm6dso_fifo_mode_t val); +int32_t lsm6dso_fifo_mode_get(stmdev_ctx_t *ctx, + lsm6dso_fifo_mode_t *val); + +typedef enum +{ + LSM6DSO_TEMP_NOT_BATCHED = 0, + LSM6DSO_TEMP_BATCHED_AT_1Hz6 = 1, + LSM6DSO_TEMP_BATCHED_AT_12Hz5 = 2, + LSM6DSO_TEMP_BATCHED_AT_52Hz = 3, +} lsm6dso_odr_t_batch_t; +int32_t lsm6dso_fifo_temp_batch_set(stmdev_ctx_t *ctx, + lsm6dso_odr_t_batch_t val); +int32_t lsm6dso_fifo_temp_batch_get(stmdev_ctx_t *ctx, + lsm6dso_odr_t_batch_t *val); + +typedef enum +{ + LSM6DSO_NO_DECIMATION = 0, + LSM6DSO_DEC_1 = 1, + LSM6DSO_DEC_8 = 2, + LSM6DSO_DEC_32 = 3, +} lsm6dso_odr_ts_batch_t; +int32_t lsm6dso_fifo_timestamp_decimation_set(stmdev_ctx_t *ctx, + lsm6dso_odr_ts_batch_t val); +int32_t lsm6dso_fifo_timestamp_decimation_get(stmdev_ctx_t *ctx, + lsm6dso_odr_ts_batch_t *val); + +typedef enum +{ + LSM6DSO_XL_BATCH_EVENT = 0, + LSM6DSO_GYRO_BATCH_EVENT = 1, +} lsm6dso_trig_counter_bdr_t; + +typedef enum +{ + LSM6DSO_GYRO_NC_TAG = 1, + LSM6DSO_XL_NC_TAG, + LSM6DSO_TEMPERATURE_TAG, + LSM6DSO_TIMESTAMP_TAG, + LSM6DSO_CFG_CHANGE_TAG, + LSM6DSO_XL_NC_T_2_TAG, + LSM6DSO_XL_NC_T_1_TAG, + LSM6DSO_XL_2XC_TAG, + LSM6DSO_XL_3XC_TAG, + LSM6DSO_GYRO_NC_T_2_TAG, + LSM6DSO_GYRO_NC_T_1_TAG, + LSM6DSO_GYRO_2XC_TAG, + LSM6DSO_GYRO_3XC_TAG, + LSM6DSO_SENSORHUB_SLAVE0_TAG, + LSM6DSO_SENSORHUB_SLAVE1_TAG, + LSM6DSO_SENSORHUB_SLAVE2_TAG, + LSM6DSO_SENSORHUB_SLAVE3_TAG, + LSM6DSO_STEP_CPUNTER_TAG, + LSM6DSO_GAME_ROTATION_TAG, + LSM6DSO_GEOMAG_ROTATION_TAG, + LSM6DSO_ROTATION_TAG, + LSM6DSO_SENSORHUB_NACK_TAG = 0x19, +} lsm6dso_fifo_tag_t; +int32_t lsm6dso_fifo_cnt_event_batch_set(stmdev_ctx_t *ctx, + lsm6dso_trig_counter_bdr_t val); +int32_t lsm6dso_fifo_cnt_event_batch_get(stmdev_ctx_t *ctx, + lsm6dso_trig_counter_bdr_t *val); + +int32_t lsm6dso_rst_batch_counter_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_rst_batch_counter_get(stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6dso_batch_counter_threshold_set(stmdev_ctx_t *ctx, + uint16_t val); +int32_t lsm6dso_batch_counter_threshold_get(stmdev_ctx_t *ctx, + uint16_t *val); + +int32_t lsm6dso_fifo_data_level_get(stmdev_ctx_t *ctx, uint16_t *val); + +int32_t lsm6dso_fifo_status_get(stmdev_ctx_t *ctx, + lsm6dso_fifo_status2_t *val); + +int32_t lsm6dso_fifo_full_flag_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6dso_fifo_ovr_flag_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6dso_fifo_wtm_flag_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6dso_fifo_sensor_tag_get(stmdev_ctx_t *ctx, + lsm6dso_fifo_tag_t *val); + +int32_t lsm6dso_fifo_pedo_batch_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_fifo_pedo_batch_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6dso_sh_batch_slave_0_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_sh_batch_slave_0_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6dso_sh_batch_slave_1_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_sh_batch_slave_1_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6dso_sh_batch_slave_2_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_sh_batch_slave_2_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6dso_sh_batch_slave_3_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_sh_batch_slave_3_get(stmdev_ctx_t *ctx, uint8_t *val); + +typedef enum +{ + LSM6DSO_DEN_DISABLE = 0, + LSM6DSO_LEVEL_FIFO = 6, + LSM6DSO_LEVEL_LETCHED = 3, + LSM6DSO_LEVEL_TRIGGER = 2, + LSM6DSO_EDGE_TRIGGER = 4, +} lsm6dso_den_mode_t; +int32_t lsm6dso_den_mode_set(stmdev_ctx_t *ctx, + lsm6dso_den_mode_t val); +int32_t lsm6dso_den_mode_get(stmdev_ctx_t *ctx, + lsm6dso_den_mode_t *val); + +typedef enum +{ + LSM6DSO_DEN_ACT_LOW = 0, + LSM6DSO_DEN_ACT_HIGH = 1, +} lsm6dso_den_lh_t; +int32_t lsm6dso_den_polarity_set(stmdev_ctx_t *ctx, + lsm6dso_den_lh_t val); +int32_t lsm6dso_den_polarity_get(stmdev_ctx_t *ctx, + lsm6dso_den_lh_t *val); + +typedef enum +{ + LSM6DSO_STAMP_IN_GY_DATA = 0, + LSM6DSO_STAMP_IN_XL_DATA = 1, + LSM6DSO_STAMP_IN_GY_XL_DATA = 2, +} lsm6dso_den_xl_g_t; +int32_t lsm6dso_den_enable_set(stmdev_ctx_t *ctx, + lsm6dso_den_xl_g_t val); +int32_t lsm6dso_den_enable_get(stmdev_ctx_t *ctx, + lsm6dso_den_xl_g_t *val); + +int32_t lsm6dso_den_mark_axis_x_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_den_mark_axis_x_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6dso_den_mark_axis_y_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_den_mark_axis_y_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6dso_den_mark_axis_z_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_den_mark_axis_z_get(stmdev_ctx_t *ctx, uint8_t *val); + +typedef enum +{ + LSM6DSO_PEDO_BASE_MODE = 0x00, + LSM6DSO_FALSE_STEP_REJ = 0x10, + LSM6DSO_FALSE_STEP_REJ_ADV_MODE = 0x30, +} lsm6dso_pedo_md_t; +int32_t lsm6dso_pedo_sens_set(stmdev_ctx_t *ctx, + lsm6dso_pedo_md_t val); +int32_t lsm6dso_pedo_sens_get(stmdev_ctx_t *ctx, + lsm6dso_pedo_md_t *val); + +int32_t lsm6dso_pedo_step_detect_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6dso_pedo_debounce_steps_set(stmdev_ctx_t *ctx, + uint8_t *buff); +int32_t lsm6dso_pedo_debounce_steps_get(stmdev_ctx_t *ctx, + uint8_t *buff); + +int32_t lsm6dso_pedo_steps_period_set(stmdev_ctx_t *ctx, + uint16_t val); +int32_t lsm6dso_pedo_steps_period_get(stmdev_ctx_t *ctx, + uint16_t *val); + +typedef enum +{ + LSM6DSO_EVERY_STEP = 0, + LSM6DSO_COUNT_OVERFLOW = 1, +} lsm6dso_carry_count_en_t; +int32_t lsm6dso_pedo_int_mode_set(stmdev_ctx_t *ctx, + lsm6dso_carry_count_en_t val); +int32_t lsm6dso_pedo_int_mode_get(stmdev_ctx_t *ctx, + lsm6dso_carry_count_en_t *val); + +int32_t lsm6dso_motion_flag_data_ready_get(stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6dso_tilt_flag_data_ready_get(stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6dso_mag_sensitivity_set(stmdev_ctx_t *ctx, uint16_t val); +int32_t lsm6dso_mag_sensitivity_get(stmdev_ctx_t *ctx, uint16_t *val); + +int32_t lsm6dso_mag_offset_set(stmdev_ctx_t *ctx, int16_t *val); +int32_t lsm6dso_mag_offset_get(stmdev_ctx_t *ctx, int16_t *val); + +int32_t lsm6dso_mag_soft_iron_set(stmdev_ctx_t *ctx, int16_t *val); +int32_t lsm6dso_mag_soft_iron_get(stmdev_ctx_t *ctx, int16_t *val); + +typedef enum +{ + LSM6DSO_Z_EQ_Y = 0, + LSM6DSO_Z_EQ_MIN_Y = 1, + LSM6DSO_Z_EQ_X = 2, + LSM6DSO_Z_EQ_MIN_X = 3, + LSM6DSO_Z_EQ_MIN_Z = 4, + LSM6DSO_Z_EQ_Z = 5, +} lsm6dso_mag_z_axis_t; +int32_t lsm6dso_mag_z_orient_set(stmdev_ctx_t *ctx, + lsm6dso_mag_z_axis_t val); +int32_t lsm6dso_mag_z_orient_get(stmdev_ctx_t *ctx, + lsm6dso_mag_z_axis_t *val); + +typedef enum +{ + LSM6DSO_Y_EQ_Y = 0, + LSM6DSO_Y_EQ_MIN_Y = 1, + LSM6DSO_Y_EQ_X = 2, + LSM6DSO_Y_EQ_MIN_X = 3, + LSM6DSO_Y_EQ_MIN_Z = 4, + LSM6DSO_Y_EQ_Z = 5, +} lsm6dso_mag_y_axis_t; +int32_t lsm6dso_mag_y_orient_set(stmdev_ctx_t *ctx, + lsm6dso_mag_y_axis_t val); +int32_t lsm6dso_mag_y_orient_get(stmdev_ctx_t *ctx, + lsm6dso_mag_y_axis_t *val); + +typedef enum +{ + LSM6DSO_X_EQ_Y = 0, + LSM6DSO_X_EQ_MIN_Y = 1, + LSM6DSO_X_EQ_X = 2, + LSM6DSO_X_EQ_MIN_X = 3, + LSM6DSO_X_EQ_MIN_Z = 4, + LSM6DSO_X_EQ_Z = 5, +} lsm6dso_mag_x_axis_t; +int32_t lsm6dso_mag_x_orient_set(stmdev_ctx_t *ctx, + lsm6dso_mag_x_axis_t val); +int32_t lsm6dso_mag_x_orient_get(stmdev_ctx_t *ctx, + lsm6dso_mag_x_axis_t *val); + +int32_t lsm6dso_long_cnt_flag_data_ready_get(stmdev_ctx_t *ctx, + uint8_t *val); + +typedef struct +{ + lsm6dso_fsm_enable_a_t fsm_enable_a; + lsm6dso_fsm_enable_b_t fsm_enable_b; +} lsm6dso_emb_fsm_enable_t; +int32_t lsm6dso_fsm_enable_set(stmdev_ctx_t *ctx, + lsm6dso_emb_fsm_enable_t *val); +int32_t lsm6dso_fsm_enable_get(stmdev_ctx_t *ctx, + lsm6dso_emb_fsm_enable_t *val); + +int32_t lsm6dso_long_cnt_set(stmdev_ctx_t *ctx, uint16_t val); +int32_t lsm6dso_long_cnt_get(stmdev_ctx_t *ctx, uint16_t *val); + +typedef enum +{ + LSM6DSO_LC_NORMAL = 0, + LSM6DSO_LC_CLEAR = 1, + LSM6DSO_LC_CLEAR_DONE = 2, +} lsm6dso_fsm_lc_clr_t; +int32_t lsm6dso_long_clr_set(stmdev_ctx_t *ctx, + lsm6dso_fsm_lc_clr_t val); +int32_t lsm6dso_long_clr_get(stmdev_ctx_t *ctx, + lsm6dso_fsm_lc_clr_t *val); + +typedef struct +{ + lsm6dso_fsm_outs1_t fsm_outs1; + lsm6dso_fsm_outs2_t fsm_outs2; + lsm6dso_fsm_outs3_t fsm_outs3; + lsm6dso_fsm_outs4_t fsm_outs4; + lsm6dso_fsm_outs5_t fsm_outs5; + lsm6dso_fsm_outs6_t fsm_outs6; + lsm6dso_fsm_outs7_t fsm_outs7; + lsm6dso_fsm_outs8_t fsm_outs8; + lsm6dso_fsm_outs9_t fsm_outs9; + lsm6dso_fsm_outs10_t fsm_outs10; + lsm6dso_fsm_outs11_t fsm_outs11; + lsm6dso_fsm_outs12_t fsm_outs12; + lsm6dso_fsm_outs13_t fsm_outs13; + lsm6dso_fsm_outs14_t fsm_outs14; + lsm6dso_fsm_outs15_t fsm_outs15; + lsm6dso_fsm_outs16_t fsm_outs16; +} lsm6dso_fsm_out_t; +int32_t lsm6dso_fsm_out_get(stmdev_ctx_t *ctx, + lsm6dso_fsm_out_t *val); + +typedef enum +{ + LSM6DSO_ODR_FSM_12Hz5 = 0, + LSM6DSO_ODR_FSM_26Hz = 1, + LSM6DSO_ODR_FSM_52Hz = 2, + LSM6DSO_ODR_FSM_104Hz = 3, +} lsm6dso_fsm_odr_t; +int32_t lsm6dso_fsm_data_rate_set(stmdev_ctx_t *ctx, + lsm6dso_fsm_odr_t val); +int32_t lsm6dso_fsm_data_rate_get(stmdev_ctx_t *ctx, + lsm6dso_fsm_odr_t *val); + +int32_t lsm6dso_fsm_init_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_fsm_init_get(stmdev_ctx_t *ctx, uint8_t *val); + +int32_t lsm6dso_long_cnt_int_value_set(stmdev_ctx_t *ctx, + uint16_t val); +int32_t lsm6dso_long_cnt_int_value_get(stmdev_ctx_t *ctx, + uint16_t *val); + +int32_t lsm6dso_fsm_number_of_programs_set(stmdev_ctx_t *ctx, + uint8_t val); +int32_t lsm6dso_fsm_number_of_programs_get(stmdev_ctx_t *ctx, + uint8_t *val); + +int32_t lsm6dso_fsm_start_address_set(stmdev_ctx_t *ctx, + uint16_t val); +int32_t lsm6dso_fsm_start_address_get(stmdev_ctx_t *ctx, + uint16_t *val); + +int32_t lsm6dso_sh_read_data_raw_get(stmdev_ctx_t *ctx, uint8_t *val, + uint8_t len); + +typedef enum +{ + LSM6DSO_SLV_0 = 0, + LSM6DSO_SLV_0_1 = 1, + LSM6DSO_SLV_0_1_2 = 2, + LSM6DSO_SLV_0_1_2_3 = 3, +} lsm6dso_aux_sens_on_t; +int32_t lsm6dso_sh_slave_connected_set(stmdev_ctx_t *ctx, + lsm6dso_aux_sens_on_t val); +int32_t lsm6dso_sh_slave_connected_get(stmdev_ctx_t *ctx, + lsm6dso_aux_sens_on_t *val); + +int32_t lsm6dso_sh_master_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_sh_master_get(stmdev_ctx_t *ctx, uint8_t *val); + +typedef enum +{ + LSM6DSO_EXT_PULL_UP = 0, + LSM6DSO_INTERNAL_PULL_UP = 1, +} lsm6dso_shub_pu_en_t; +int32_t lsm6dso_sh_pin_mode_set(stmdev_ctx_t *ctx, + lsm6dso_shub_pu_en_t val); +int32_t lsm6dso_sh_pin_mode_get(stmdev_ctx_t *ctx, + lsm6dso_shub_pu_en_t *val); + +int32_t lsm6dso_sh_pass_through_set(stmdev_ctx_t *ctx, uint8_t val); +int32_t lsm6dso_sh_pass_through_get(stmdev_ctx_t *ctx, uint8_t *val); + +typedef enum +{ + LSM6DSO_EXT_ON_INT2_PIN = 1, + LSM6DSO_XL_GY_DRDY = 0, +} lsm6dso_start_config_t; +int32_t lsm6dso_sh_syncro_mode_set(stmdev_ctx_t *ctx, + lsm6dso_start_config_t val); +int32_t lsm6dso_sh_syncro_mode_get(stmdev_ctx_t *ctx, + lsm6dso_start_config_t *val); + +typedef enum +{ + LSM6DSO_EACH_SH_CYCLE = 0, + LSM6DSO_ONLY_FIRST_CYCLE = 1, +} lsm6dso_write_once_t; +int32_t lsm6dso_sh_write_mode_set(stmdev_ctx_t *ctx, + lsm6dso_write_once_t val); +int32_t lsm6dso_sh_write_mode_get(stmdev_ctx_t *ctx, + lsm6dso_write_once_t *val); + +int32_t lsm6dso_sh_reset_set(stmdev_ctx_t *ctx); +int32_t lsm6dso_sh_reset_get(stmdev_ctx_t *ctx, uint8_t *val); + +typedef enum +{ + LSM6DSO_SH_ODR_104Hz = 0, + LSM6DSO_SH_ODR_52Hz = 1, + LSM6DSO_SH_ODR_26Hz = 2, + LSM6DSO_SH_ODR_13Hz = 3, +} lsm6dso_shub_odr_t; +int32_t lsm6dso_sh_data_rate_set(stmdev_ctx_t *ctx, + lsm6dso_shub_odr_t val); +int32_t lsm6dso_sh_data_rate_get(stmdev_ctx_t *ctx, + lsm6dso_shub_odr_t *val); + +typedef struct +{ + uint8_t slv0_add; + uint8_t slv0_subadd; + uint8_t slv0_data; +} lsm6dso_sh_cfg_write_t; +int32_t lsm6dso_sh_cfg_write(stmdev_ctx_t *ctx, + lsm6dso_sh_cfg_write_t *val); + +typedef struct +{ + uint8_t slv_add; + uint8_t slv_subadd; + uint8_t slv_len; +} lsm6dso_sh_cfg_read_t; +int32_t lsm6dso_sh_slv0_cfg_read(stmdev_ctx_t *ctx, + lsm6dso_sh_cfg_read_t *val); +int32_t lsm6dso_sh_slv1_cfg_read(stmdev_ctx_t *ctx, + lsm6dso_sh_cfg_read_t *val); +int32_t lsm6dso_sh_slv2_cfg_read(stmdev_ctx_t *ctx, + lsm6dso_sh_cfg_read_t *val); +int32_t lsm6dso_sh_slv3_cfg_read(stmdev_ctx_t *ctx, + lsm6dso_sh_cfg_read_t *val); + +int32_t lsm6dso_sh_status_get(stmdev_ctx_t *ctx, + lsm6dso_status_master_t *val); + + +typedef struct +{ + uint8_t ui; + uint8_t aux; +} lsm6dso_id_t; +int32_t lsm6dso_id_get(stmdev_ctx_t *ctx, stmdev_ctx_t *aux_ctx, + lsm6dso_id_t *val); + +typedef enum +{ + LSM6DSO_SEL_BY_HW = 0x00, /* bus mode select by HW (SPI 3W disable) */ + LSM6DSO_SPI_4W = 0x06, /* Only SPI: SDO / SDI separated pins */ + LSM6DSO_SPI_3W = 0x07, /* Only SPI: SDO / SDI share the same pin */ + LSM6DSO_I2C = 0x04, /* Only I2C */ + LSM6DSO_I3C_T_50us = 0x02, /* I3C: available time equal to 50 us */ + LSM6DSO_I3C_T_2us = 0x12, /* I3C: available time equal to 2 us */ + LSM6DSO_I3C_T_1ms = 0x22, /* I3C: available time equal to 1 ms */ + LSM6DSO_I3C_T_25ms = 0x32, /* I3C: available time equal to 25 ms */ +} lsm6dso_ui_bus_md_t; + +typedef enum +{ + LSM6DSO_SPI_4W_AUX = 0x00, + LSM6DSO_SPI_3W_AUX = 0x01, +} lsm6dso_aux_bus_md_t; + +typedef struct +{ + lsm6dso_ui_bus_md_t ui_bus_md; + lsm6dso_aux_bus_md_t aux_bus_md; +} lsm6dso_bus_mode_t; +int32_t lsm6dso_bus_mode_set(stmdev_ctx_t *ctx, stmdev_ctx_t *aux_ctx, + lsm6dso_bus_mode_t val); +int32_t lsm6dso_bus_mode_get(stmdev_ctx_t *ctx, stmdev_ctx_t *aux_ctx, + lsm6dso_bus_mode_t *val); + +typedef enum +{ + LSM6DSO_DRV_RDY = 0x00, /* Initialize the device for driver usage */ + LSM6DSO_BOOT = 0x01, /* Restore calib. param. ( it takes 10ms ) */ + LSM6DSO_RESET = 0x02, /* Reset configuration registers */ + LSM6DSO_FIFO_COMP = 0x04, /* FIFO compression initialization request. */ + LSM6DSO_FSM = 0x08, /* Finite State Machine initialization request */ + LSM6DSO_PEDO = 0x20, /* Pedometer algo initialization request. */ + LSM6DSO_TILT = 0x40, /* Tilt algo initialization request */ + LSM6DSO_SMOTION = 0x80, /* Significant Motion initialization request */ +} lsm6dso_init_t; +int32_t lsm6dso_init_set(stmdev_ctx_t *ctx, lsm6dso_init_t val); + +typedef struct +{ +uint8_t sw_reset : + 1; /* Restoring configuration registers */ + uint8_t boot : 1; /* Restoring calibration parameters */ + uint8_t drdy_xl : 1; /* Accelerometer data ready */ + uint8_t drdy_g : 1; /* Gyroscope data ready */ + uint8_t drdy_temp : 1; /* Temperature data ready */ + uint8_t ois_drdy_xl : 1; /* Accelerometer data ready on OIS */ + uint8_t ois_drdy_g : 1; /* Gyroscope data ready on OIS */ +uint8_t ois_gyro_settling : + 1; /* Gyroscope is in the settling phase */ +} lsm6dso_status_t; +int32_t lsm6dso_status_get(stmdev_ctx_t *ctx, stmdev_ctx_t *aux_ctx, + lsm6dso_status_t *val); + +typedef struct +{ + uint8_t sdo_sa0_pull_up : 1; /* 1 = pull-up on SDO/SA0 pin */ +uint8_t aux_sdo_ocs_pull_up : + 1; /* 1 = pull-up on OCS_Aux/SDO_Aux pins */ + uint8_t int1_int2_push_pull : 1; /* 1 = push-pull / 0 = open-drain*/ +uint8_t int1_pull_down : + 1; /* 1 = pull-down always disabled (0=auto) */ +} lsm6dso_pin_conf_t; +int32_t lsm6dso_pin_conf_set(stmdev_ctx_t *ctx, + lsm6dso_pin_conf_t val); +int32_t lsm6dso_pin_conf_get(stmdev_ctx_t *ctx, + lsm6dso_pin_conf_t *val); + +typedef struct +{ + uint8_t active_low : 1; /* 1 = active low / 0 = active high */ +uint8_t base_latched : + 1; /* base functions are: FF, WU, 6D, Tap, Act/Inac */ +uint8_t emb_latched : + 1; /* emb functions are: Pedo, Tilt, SMot, Timestamp */ +} lsm6dso_int_mode_t; +int32_t lsm6dso_interrupt_mode_set(stmdev_ctx_t *ctx, + lsm6dso_int_mode_t val); +int32_t lsm6dso_interrupt_mode_get(stmdev_ctx_t *ctx, + lsm6dso_int_mode_t *val); + +typedef struct +{ + uint8_t drdy_xl : 1; /* Accelerometer data ready */ + uint8_t drdy_g : 1; /* Gyroscope data ready */ +uint8_t drdy_temp : + 1; /* Temperature data ready (1 = int2 pin disable) */ + uint8_t boot : 1; /* Restoring calibration parameters */ + uint8_t fifo_th : 1; /* FIFO threshold reached */ + uint8_t fifo_ovr : 1; /* FIFO overrun */ + uint8_t fifo_full : 1; /* FIFO full */ + uint8_t fifo_bdr : 1; /* FIFO Batch counter threshold reached */ +uint8_t den_flag : + 1; /* external trigger level recognition (DEN) */ + uint8_t sh_endop : 1; /* sensor hub end operation */ +uint8_t timestamp : + 1; /* timestamp overflow (1 = int2 pin disable) */ + uint8_t six_d : 1; /* orientation change (6D/4D detection) */ + uint8_t double_tap : 1; /* double-tap event */ + uint8_t free_fall : 1; /* free fall event */ + uint8_t wake_up : 1; /* wake up event */ + uint8_t single_tap : 1; /* single-tap event */ +uint8_t sleep_change : + 1; /* Act/Inact (or Vice-versa) status changed */ + uint8_t step_detector : 1; /* Step detected */ + uint8_t tilt : 1; /* Relative tilt event detected */ + uint8_t sig_mot : 1; /* "significant motion" event detected */ +uint8_t fsm_lc : + 1; /* fsm long counter timeout interrupt event */ + uint8_t fsm1 : 1; /* fsm 1 interrupt event */ + uint8_t fsm2 : 1; /* fsm 2 interrupt event */ + uint8_t fsm3 : 1; /* fsm 3 interrupt event */ + uint8_t fsm4 : 1; /* fsm 4 interrupt event */ + uint8_t fsm5 : 1; /* fsm 5 interrupt event */ + uint8_t fsm6 : 1; /* fsm 6 interrupt event */ + uint8_t fsm7 : 1; /* fsm 7 interrupt event */ + uint8_t fsm8 : 1; /* fsm 8 interrupt event */ + uint8_t fsm9 : 1; /* fsm 9 interrupt event */ + uint8_t fsm10 : 1; /* fsm 10 interrupt event */ + uint8_t fsm11 : 1; /* fsm 11 interrupt event */ + uint8_t fsm12 : 1; /* fsm 12 interrupt event */ + uint8_t fsm13 : 1; /* fsm 13 interrupt event */ + uint8_t fsm14 : 1; /* fsm 14 interrupt event */ + uint8_t fsm15 : 1; /* fsm 15 interrupt event */ + uint8_t fsm16 : 1; /* fsm 16 interrupt event */ + uint8_t mlc1 : 1; /* mlc 1 interrupt event */ + uint8_t mlc2 : 1; /* mlc 2 interrupt event */ + uint8_t mlc3 : 1; /* mlc 3 interrupt event */ + uint8_t mlc4 : 1; /* mlc 4 interrupt event */ + uint8_t mlc5 : 1; /* mlc 5 interrupt event */ + uint8_t mlc6 : 1; /* mlc 6 interrupt event */ + uint8_t mlc7 : 1; /* mlc 7 interrupt event */ + uint8_t mlc8 : 1; /* mlc 8 interrupt event */ +} lsm6dso_pin_int1_route_t; + +int32_t lsm6dso_pin_int1_route_set(stmdev_ctx_t *ctx, + lsm6dso_pin_int1_route_t val); +int32_t lsm6dso_pin_int1_route_get(stmdev_ctx_t *ctx, + lsm6dso_pin_int1_route_t *val); + +typedef struct +{ + uint8_t drdy_ois : 1; /* OIS chain data ready */ + uint8_t drdy_xl : 1; /* Accelerometer data ready */ + uint8_t drdy_g : 1; /* Gyroscope data ready */ + uint8_t drdy_temp : 1; /* Temperature data ready */ + uint8_t fifo_th : 1; /* FIFO threshold reached */ + uint8_t fifo_ovr : 1; /* FIFO overrun */ + uint8_t fifo_full : 1; /* FIFO full */ + uint8_t fifo_bdr : 1; /* FIFO Batch counter threshold reached */ + uint8_t timestamp : 1; /* timestamp overflow */ + uint8_t six_d : 1; /* orientation change (6D/4D detection) */ + uint8_t double_tap : 1; /* double-tap event */ + uint8_t free_fall : 1; /* free fall event */ + uint8_t wake_up : 1; /* wake up event */ + uint8_t single_tap : 1; /* single-tap event */ +uint8_t sleep_change : + 1; /* Act/Inact (or Vice-versa) status changed */ + uint8_t step_detector : 1; /* Step detected */ + uint8_t tilt : 1; /* Relative tilt event detected */ + uint8_t sig_mot : 1; /* "significant motion" event detected */ +uint8_t fsm_lc : + 1; /* fsm long counter timeout interrupt event */ + uint8_t fsm1 : 1; /* fsm 1 interrupt event */ + uint8_t fsm2 : 1; /* fsm 2 interrupt event */ + uint8_t fsm3 : 1; /* fsm 3 interrupt event */ + uint8_t fsm4 : 1; /* fsm 4 interrupt event */ + uint8_t fsm5 : 1; /* fsm 5 interrupt event */ + uint8_t fsm6 : 1; /* fsm 6 interrupt event */ + uint8_t fsm7 : 1; /* fsm 7 interrupt event */ + uint8_t fsm8 : 1; /* fsm 8 interrupt event */ + uint8_t fsm9 : 1; /* fsm 9 interrupt event */ + uint8_t fsm10 : 1; /* fsm 10 interrupt event */ + uint8_t fsm11 : 1; /* fsm 11 interrupt event */ + uint8_t fsm12 : 1; /* fsm 12 interrupt event */ + uint8_t fsm13 : 1; /* fsm 13 interrupt event */ + uint8_t fsm14 : 1; /* fsm 14 interrupt event */ + uint8_t fsm15 : 1; /* fsm 15 interrupt event */ + uint8_t fsm16 : 1; /* fsm 16 interrupt event */ + uint8_t mlc1 : 1; /* mlc 1 interrupt event */ + uint8_t mlc2 : 1; /* mlc 2 interrupt event */ + uint8_t mlc3 : 1; /* mlc 3 interrupt event */ + uint8_t mlc4 : 1; /* mlc 4 interrupt event */ + uint8_t mlc5 : 1; /* mlc 5 interrupt event */ + uint8_t mlc6 : 1; /* mlc 6 interrupt event */ + uint8_t mlc7 : 1; /* mlc 7 interrupt event */ + uint8_t mlc8 : 1; /* mlc 8 interrupt event */ +} lsm6dso_pin_int2_route_t; + +int32_t lsm6dso_pin_int2_route_set(stmdev_ctx_t *ctx, + stmdev_ctx_t *aux_ctx, + lsm6dso_pin_int2_route_t val); +int32_t lsm6dso_pin_int2_route_get(stmdev_ctx_t *ctx, + stmdev_ctx_t *aux_ctx, + lsm6dso_pin_int2_route_t *val); + +typedef struct +{ + uint8_t drdy_xl : 1; /* Accelerometer data ready */ + uint8_t drdy_g : 1; /* Gyroscope data ready */ + uint8_t drdy_temp : 1; /* Temperature data ready */ +uint8_t den_flag : + 1; /* external trigger level recognition (DEN) */ +uint8_t timestamp : + 1; /* timestamp overflow (1 = int2 pin disable) */ + uint8_t free_fall : 1; /* free fall event */ + uint8_t wake_up : 1; /* wake up event */ + uint8_t wake_up_z : 1; /* wake up on Z axis event */ + uint8_t wake_up_y : 1; /* wake up on Y axis event */ + uint8_t wake_up_x : 1; /* wake up on X axis event */ + uint8_t single_tap : 1; /* single-tap event */ + uint8_t double_tap : 1; /* double-tap event */ + uint8_t tap_z : 1; /* single-tap on Z axis event */ + uint8_t tap_y : 1; /* single-tap on Y axis event */ + uint8_t tap_x : 1; /* single-tap on X axis event */ + uint8_t tap_sign : 1; /* sign of tap event (0-pos / 1-neg) */ +uint8_t six_d : + 1; /* orientation change (6D/4D detection) */ +uint8_t six_d_xl : + 1; /* X-axis low 6D/4D event (under threshold) */ +uint8_t six_d_xh : + 1; /* X-axis high 6D/4D event (over threshold) */ +uint8_t six_d_yl : + 1; /* Y-axis low 6D/4D event (under threshold) */ +uint8_t six_d_yh : + 1; /* Y-axis high 6D/4D event (over threshold) */ +uint8_t six_d_zl : + 1; /* Z-axis low 6D/4D event (under threshold) */ +uint8_t six_d_zh : + 1; /* Z-axis high 6D/4D event (over threshold) */ +uint8_t sleep_change : + 1; /* Act/Inact (or Vice-versa) status changed */ +uint8_t sleep_state : + 1; /* Act/Inact status flag (0-Act / 1-Inact) */ + uint8_t step_detector : 1; /* Step detected */ + uint8_t tilt : 1; /* Relative tilt event detected */ +uint8_t sig_mot : + 1; /* "significant motion" event detected */ +uint8_t fsm_lc : + 1; /* fsm long counter timeout interrupt event */ + uint8_t fsm1 : 1; /* fsm 1 interrupt event */ + uint8_t fsm2 : 1; /* fsm 2 interrupt event */ + uint8_t fsm3 : 1; /* fsm 3 interrupt event */ + uint8_t fsm4 : 1; /* fsm 4 interrupt event */ + uint8_t fsm5 : 1; /* fsm 5 interrupt event */ + uint8_t fsm6 : 1; /* fsm 6 interrupt event */ + uint8_t fsm7 : 1; /* fsm 7 interrupt event */ + uint8_t fsm8 : 1; /* fsm 8 interrupt event */ + uint8_t fsm9 : 1; /* fsm 9 interrupt event */ + uint8_t fsm10 : 1; /* fsm 10 interrupt event */ + uint8_t fsm11 : 1; /* fsm 11 interrupt event */ + uint8_t fsm12 : 1; /* fsm 12 interrupt event */ + uint8_t fsm13 : 1; /* fsm 13 interrupt event */ + uint8_t fsm14 : 1; /* fsm 14 interrupt event */ + uint8_t fsm15 : 1; /* fsm 15 interrupt event */ + uint8_t fsm16 : 1; /* fsm 16 interrupt event */ + uint8_t mlc1 : 1; /* mlc 1 interrupt event */ + uint8_t mlc2 : 1; /* mlc 2 interrupt event */ + uint8_t mlc3 : 1; /* mlc 3 interrupt event */ + uint8_t mlc4 : 1; /* mlc 4 interrupt event */ + uint8_t mlc5 : 1; /* mlc 5 interrupt event */ + uint8_t mlc6 : 1; /* mlc 6 interrupt event */ + uint8_t mlc7 : 1; /* mlc 7 interrupt event */ + uint8_t mlc8 : 1; /* mlc 8 interrupt event */ + uint8_t sh_endop : 1; /* sensor hub end operation */ +uint8_t sh_slave0_nack : + 1; /* Not acknowledge on sensor hub slave 0 */ +uint8_t sh_slave1_nack : + 1; /* Not acknowledge on sensor hub slave 1 */ +uint8_t sh_slave2_nack : + 1; /* Not acknowledge on sensor hub slave 2 */ +uint8_t sh_slave3_nack : + 1; /* Not acknowledge on sensor hub slave 3 */ +uint8_t sh_wr_once : + 1; /* "WRITE_ONCE" end on sensor hub slave 0 */ +uint16_t fifo_diff : + 10; /* Number of unread sensor data in FIFO*/ + uint8_t fifo_ovr_latched : 1; /* Latched FIFO overrun status */ +uint8_t fifo_bdr : + 1; /* FIFO Batch counter threshold reached */ + uint8_t fifo_full : 1; /* FIFO full */ + uint8_t fifo_ovr : 1; /* FIFO overrun */ + uint8_t fifo_th : 1; /* FIFO threshold reached */ +} lsm6dso_all_sources_t; +int32_t lsm6dso_all_sources_get(stmdev_ctx_t *ctx, + lsm6dso_all_sources_t *val); + +typedef struct +{ + uint8_t odr_fine_tune; +} dev_cal_t; +int32_t lsm6dso_calibration_get(stmdev_ctx_t *ctx, dev_cal_t *val); + +typedef enum +{ + LSM6DSO_XL_UI_OFF = 0x00, /* in power down */ + LSM6DSO_XL_UI_1Hz6_LP = 0x1B, /* @1Hz6 (low power) */ + LSM6DSO_XL_UI_1Hz6_ULP = 0x2B, /* @1Hz6 (ultra low/Gy, OIS imu off) */ + LSM6DSO_XL_UI_12Hz5_HP = 0x01, /* @12Hz5 (high performance) */ + LSM6DSO_XL_UI_12Hz5_LP = 0x11, /* @12Hz5 (low power) */ + LSM6DSO_XL_UI_12Hz5_ULP = 0x21, /* @12Hz5 (ultra low/Gy, OIS imu off) */ + LSM6DSO_XL_UI_26Hz_HP = 0x02, /* @26Hz (high performance) */ + LSM6DSO_XL_UI_26Hz_LP = 0x12, /* @26Hz (low power) */ + LSM6DSO_XL_UI_26Hz_ULP = 0x22, /* @26Hz (ultra low/Gy, OIS imu off) */ + LSM6DSO_XL_UI_52Hz_HP = 0x03, /* @52Hz (high performance) */ + LSM6DSO_XL_UI_52Hz_LP = 0x13, /* @52Hz (low power) */ + LSM6DSO_XL_UI_52Hz_ULP = 0x23, /* @52Hz (ultra low/Gy, OIS imu off) */ + LSM6DSO_XL_UI_104Hz_HP = 0x04, /* @104Hz (high performance) */ + LSM6DSO_XL_UI_104Hz_NM = 0x14, /* @104Hz (normal mode) */ + LSM6DSO_XL_UI_104Hz_ULP = 0x24, /* @104Hz (ultra low/Gy, OIS imu off) */ + LSM6DSO_XL_UI_208Hz_HP = 0x05, /* @208Hz (high performance) */ + LSM6DSO_XL_UI_208Hz_NM = 0x15, /* @208Hz (normal mode) */ + LSM6DSO_XL_UI_208Hz_ULP = 0x25, /* @208Hz (ultra low/Gy, OIS imu off) */ + LSM6DSO_XL_UI_416Hz_HP = 0x06, /* @416Hz (high performance) */ + LSM6DSO_XL_UI_833Hz_HP = 0x07, /* @833Hz (high performance) */ + LSM6DSO_XL_UI_1667Hz_HP = 0x08, /* @1kHz66 (high performance) */ + LSM6DSO_XL_UI_3333Hz_HP = 0x09, /* @3kHz33 (high performance) */ + LSM6DSO_XL_UI_6667Hz_HP = 0x0A, /* @6kHz66 (high performance) */ +} lsm6dso_odr_xl_ui_t; + +typedef enum +{ + LSM6DSO_XL_UI_2g = 0, + LSM6DSO_XL_UI_4g = 2, + LSM6DSO_XL_UI_8g = 3, + LSM6DSO_XL_UI_16g = 1, /* OIS full scale is also forced to be 16g */ +} lsm6dso_fs_xl_ui_t; + +typedef enum +{ + LSM6DSO_GY_UI_OFF = 0x00, /* gy in power down */ + LSM6DSO_GY_UI_12Hz5_LP = 0x11, /* gy @12Hz5 (low power) */ + LSM6DSO_GY_UI_12Hz5_HP = 0x01, /* gy @12Hz5 (high performance) */ + LSM6DSO_GY_UI_26Hz_LP = 0x12, /* gy @26Hz (low power) */ + LSM6DSO_GY_UI_26Hz_HP = 0x02, /* gy @26Hz (high performance) */ + LSM6DSO_GY_UI_52Hz_LP = 0x13, /* gy @52Hz (low power) */ + LSM6DSO_GY_UI_52Hz_HP = 0x03, /* gy @52Hz (high performance) */ + LSM6DSO_GY_UI_104Hz_NM = 0x14, /* gy @104Hz (low power) */ + LSM6DSO_GY_UI_104Hz_HP = 0x04, /* gy @104Hz (high performance) */ + LSM6DSO_GY_UI_208Hz_NM = 0x15, /* gy @208Hz (low power) */ + LSM6DSO_GY_UI_208Hz_HP = 0x05, /* gy @208Hz (high performance) */ + LSM6DSO_GY_UI_416Hz_HP = 0x06, /* gy @416Hz (high performance) */ + LSM6DSO_GY_UI_833Hz_HP = 0x07, /* gy @833Hz (high performance) */ + LSM6DSO_GY_UI_1667Hz_HP = 0x08, /* gy @1kHz66 (high performance) */ + LSM6DSO_GY_UI_3333Hz_HP = 0x09, /* gy @3kHz33 (high performance) */ + LSM6DSO_GY_UI_6667Hz_HP = 0x0A, /* gy @6kHz66 (high performance) */ +} lsm6dso_odr_g_ui_t; + +typedef enum +{ + LSM6DSO_GY_UI_250dps = 0, + LSM6DSO_GY_UI_125dps = 1, + LSM6DSO_GY_UI_500dps = 2, + LSM6DSO_GY_UI_1000dps = 4, + LSM6DSO_GY_UI_2000dps = 6, +} lsm6dso_fs_g_ui_t; + +typedef enum +{ + LSM6DSO_OIS_ONLY_AUX = 0x00, /* Auxiliary SPI full control */ + LSM6DSO_OIS_MIXED = 0x01, /* Enabling by UI / read-config by AUX */ +} lsm6dso_ctrl_md_t; + +typedef enum +{ + LSM6DSO_XL_OIS_OFF = 0x00, /* in power down */ + LSM6DSO_XL_OIS_6667Hz_HP = 0x01, /* @6kHz OIS imu active/NO ULP on UI */ +} lsm6dso_odr_xl_ois_noaux_t; + +typedef enum +{ + LSM6DSO_XL_OIS_2g = 0, + LSM6DSO_XL_OIS_4g = 2, + LSM6DSO_XL_OIS_8g = 3, + LSM6DSO_XL_OIS_16g = 1, /* UI full scale is also forced to be 16g */ +} lsm6dso_fs_xl_ois_noaux_t; + +typedef enum +{ + LSM6DSO_GY_OIS_OFF = 0x00, /* in power down */ + LSM6DSO_GY_OIS_6667Hz_HP = 0x01, /* @6kHz No Ultra Low Power*/ +} lsm6dso_odr_g_ois_noaux_t; + +typedef enum +{ + LSM6DSO_GY_OIS_250dps = 0, + LSM6DSO_GY_OIS_125dps = 1, + LSM6DSO_GY_OIS_500dps = 2, + LSM6DSO_GY_OIS_1000dps = 4, + LSM6DSO_GY_OIS_2000dps = 6, +} lsm6dso_fs_g_ois_noaux_t; + +typedef enum +{ + LSM6DSO_FSM_DISABLE = 0x00, + LSM6DSO_FSM_XL = 0x01, + LSM6DSO_FSM_GY = 0x02, + LSM6DSO_FSM_XL_GY = 0x03, +} lsm6dso_sens_fsm_t; + +typedef enum +{ + LSM6DSO_FSM_12Hz5 = 0x00, + LSM6DSO_FSM_26Hz = 0x01, + LSM6DSO_FSM_52Hz = 0x02, + LSM6DSO_FSM_104Hz = 0x03, +} lsm6dso_odr_fsm_t; + +typedef struct +{ + struct + { + struct + { + lsm6dso_odr_xl_ui_t odr; + lsm6dso_fs_xl_ui_t fs; + } xl; + struct + { + lsm6dso_odr_g_ui_t odr; + lsm6dso_fs_g_ui_t fs; + } gy; + } ui; + struct + { + lsm6dso_ctrl_md_t ctrl_md; + struct + { + lsm6dso_odr_xl_ois_noaux_t odr; + lsm6dso_fs_xl_ois_noaux_t fs; + } xl; + struct + { + lsm6dso_odr_g_ois_noaux_t odr; + lsm6dso_fs_g_ois_noaux_t fs; + } gy; + } ois; + struct + { + lsm6dso_sens_fsm_t sens; + lsm6dso_odr_fsm_t odr; + } fsm; +} lsm6dso_md_t; +int32_t lsm6dso_mode_set(stmdev_ctx_t *ctx, stmdev_ctx_t *aux_ctx, + lsm6dso_md_t *val); +int32_t lsm6dso_mode_get(stmdev_ctx_t *ctx, stmdev_ctx_t *aux_ctx, + lsm6dso_md_t *val); +typedef struct +{ + struct + { + struct + { + float_t mg[3]; + int16_t raw[3]; + } xl; + struct + { + float_t mdps[3]; + int16_t raw[3]; + } gy; + struct + { + float_t deg_c; + int16_t raw; + } heat; + } ui; + struct + { + struct + { + float_t mg[3]; + int16_t raw[3]; + } xl; + struct + { + float_t mdps[3]; + int16_t raw[3]; + } gy; + } ois; +} lsm6dso_data_t; +int32_t lsm6dso_data_get(stmdev_ctx_t *ctx, stmdev_ctx_t *aux_ctx, + lsm6dso_md_t *md, lsm6dso_data_t *data); + +typedef struct +{ + uint8_t sig_mot : 1; /* significant motion */ + uint8_t tilt : 1; /* tilt detection */ + uint8_t step : 1; /* step counter/detector */ + uint8_t step_adv : 1; /* step counter advanced mode */ + uint8_t fsm : 1; /* finite state machine */ + uint8_t fifo_compr : 1; /* FIFO compression */ +} lsm6dso_emb_sens_t; +int32_t lsm6dso_embedded_sens_set(stmdev_ctx_t *ctx, + lsm6dso_emb_sens_t *emb_sens); +int32_t lsm6dso_embedded_sens_get(stmdev_ctx_t *ctx, + lsm6dso_emb_sens_t *emb_sens); +int32_t lsm6dso_embedded_sens_off(stmdev_ctx_t *ctx); + +/** + * @} + * + */ + +#ifdef __cplusplus +} +#endif + +#endif /*LSM6DSO_DRIVER_H */ diff --git a/airmouse/tracking/imu/bmi160.c b/airmouse/tracking/imu/bmi160.c index 968dddd4def..9491b6bbc8b 100644 --- a/airmouse/tracking/imu/bmi160.c +++ b/airmouse/tracking/imu/bmi160.c @@ -1,5988 +1,86 @@ -/** -* Copyright (c) 2021 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 bmi160.c -* @date 2021-10-05 -* @version v3.9.2 -* -*/ +#include "imu.h" +#include "../../lib/bmi160-api/bmi160.h" -#include "bmi160.h" +#define BMI160_TAG "BMI160" +#define BMI160_DEV_ADDR (0x69 << 1) -/* Below look up table follows the enum bmi160_int_types. - * Hence any change should match to the enum bmi160_int_types - */ -const uint8_t int_mask_lookup_table[13] = { - BMI160_INT1_SLOPE_MASK, - BMI160_INT1_SLOPE_MASK, - BMI160_INT2_LOW_STEP_DETECT_MASK, - BMI160_INT1_DOUBLE_TAP_MASK, - BMI160_INT1_SINGLE_TAP_MASK, - BMI160_INT1_ORIENT_MASK, - BMI160_INT1_FLAT_MASK, - BMI160_INT1_HIGH_G_MASK, - BMI160_INT1_LOW_G_MASK, - BMI160_INT1_NO_MOTION_MASK, - BMI160_INT2_DATA_READY_MASK, - BMI160_INT2_FIFO_FULL_MASK, - BMI160_INT2_FIFO_WM_MASK}; +struct bmi160_dev bmi160dev; +struct bmi160_sensor_data bmi160_accel; +struct bmi160_sensor_data bmi160_gyro; -/*********************************************************************/ -/* Static function declarations */ - -/*! - * @brief This API configures the pins to fire the - * interrupt signal when it occurs - * - * @param[in] int_config : Structure instance of bmi160_int_settg. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error. - */ -static int8_t - set_intr_pin_config(const struct bmi160_int_settg* int_config, const struct bmi160_dev* dev); - -/*! - * @brief This API sets the any-motion interrupt of the sensor. - * This interrupt occurs when accel values exceeds preset threshold - * for a certain period of time. - * - * @param[in] int_config : Structure instance of bmi160_int_settg. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error. - */ -static int8_t - set_accel_any_motion_int(struct bmi160_int_settg* int_config, struct bmi160_dev* dev); - -/*! - * @brief This API sets tap interrupts.Interrupt is fired when - * tap movements happen. - * - * @param[in] int_config : Structure instance of bmi160_int_settg. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error. - */ -static int8_t set_accel_tap_int(struct bmi160_int_settg* int_config, const struct bmi160_dev* dev); - -/*! - * @brief This API sets the data ready interrupt for both accel and gyro. - * This interrupt occurs when new accel and gyro data come. - * - * @param[in] int_config : Structure instance of bmi160_int_settg. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error. - */ -static int8_t set_accel_gyro_data_ready_int( - const struct bmi160_int_settg* int_config, - const struct bmi160_dev* dev); - -/*! - * @brief This API sets the significant motion interrupt of the sensor.This - * interrupt occurs when there is change in user location. - * - * @param[in] int_config : Structure instance of bmi160_int_settg. - * @param[in] dev : Structure instance of bmi160_dev. - * - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error. - */ -static int8_t - set_accel_sig_motion_int(struct bmi160_int_settg* int_config, struct bmi160_dev* dev); - -/*! - * @brief This API sets the no motion/slow motion interrupt of the sensor. - * Slow motion is similar to any motion interrupt.No motion interrupt - * occurs when slope bet. two accel values falls below preset threshold - * for preset duration. - * - * @param[in] int_config : Structure instance of bmi160_int_settg. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error. - */ -static int8_t - set_accel_no_motion_int(struct bmi160_int_settg* int_config, const struct bmi160_dev* dev); - -/*! - * @brief This API sets the step detection interrupt.This interrupt - * occurs when the single step causes accel values to go above - * preset threshold. - * - * @param[in] int_config : Structure instance of bmi160_int_settg. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error. - */ -static int8_t - set_accel_step_detect_int(struct bmi160_int_settg* int_config, const struct bmi160_dev* dev); - -/*! - * @brief This API sets the orientation interrupt of the sensor.This - * interrupt occurs when there is orientation change in the sensor - * with respect to gravitational field vector g. - * - * @param[in] int_config : Structure instance of bmi160_int_settg. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error. - */ -static int8_t - set_accel_orientation_int(struct bmi160_int_settg* int_config, const struct bmi160_dev* dev); - -/*! - * @brief This API sets the flat interrupt of the sensor.This interrupt - * occurs in case of flat orientation - * - * @param[in] int_config : Structure instance of bmi160_int_settg. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error. - */ -static int8_t - set_accel_flat_detect_int(struct bmi160_int_settg* int_config, const struct bmi160_dev* dev); - -/*! - * @brief This API sets the low-g interrupt of the sensor.This interrupt - * occurs during free-fall. - * - * @param[in] int_config : Structure instance of bmi160_int_settg. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error. - */ -static int8_t - set_accel_low_g_int(struct bmi160_int_settg* int_config, const struct bmi160_dev* dev); - -/*! - * @brief This API sets the high-g interrupt of the sensor.The interrupt - * occurs if the absolute value of acceleration data of any enabled axis - * exceeds the programmed threshold and the sign of the value does not - * change for a preset duration. - * - * @param[in] int_config : Structure instance of bmi160_int_settg. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error. - */ -static int8_t - set_accel_high_g_int(struct bmi160_int_settg* int_config, const struct bmi160_dev* dev); - -/*! - * @brief This API sets the default configuration parameters of accel & gyro. - * Also maintain the previous state of configurations. - * - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error. - */ -static void default_param_settg(struct bmi160_dev* dev); - -/*! - * @brief This API is used to validate the device structure pointer for - * null conditions. - * - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error. - */ -static int8_t null_ptr_check(const struct bmi160_dev* dev); - -/*! - * @brief This API set the accel configuration. - * - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error. - */ -static int8_t set_accel_conf(struct bmi160_dev* dev); - -/*! - * @brief This API gets the accel configuration. - * - * @param[out] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error. - */ -static int8_t get_accel_conf(struct bmi160_dev* dev); - -/*! - * @brief This API check the accel configuration. - * - * @param[in] data : Pointer to store the updated accel config. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error. - */ -static int8_t check_accel_config(uint8_t* data, const struct bmi160_dev* dev); - -/*! - * @brief This API process the accel odr. - * - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error. - */ -static int8_t process_accel_odr(uint8_t* data, const struct bmi160_dev* dev); - -/*! - * @brief This API process the accel bandwidth. - * - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error. - */ -static int8_t process_accel_bw(uint8_t* data, const struct bmi160_dev* dev); - -/*! - * @brief This API process the accel range. - * - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error. - */ -static int8_t process_accel_range(uint8_t* data, const struct bmi160_dev* dev); - -/*! - * @brief This API checks the invalid settings for ODR & Bw for Accel and Gyro. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error. - */ -static int8_t check_invalid_settg(const struct bmi160_dev* dev); - -/*! - * @brief This API set the gyro configuration. - * - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error. - */ -static int8_t set_gyro_conf(struct bmi160_dev* dev); - -/*! - * @brief This API get the gyro configuration. - * - * @param[out] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error. - */ -static int8_t get_gyro_conf(struct bmi160_dev* dev); - -/*! - * @brief This API check the gyro configuration. - * - * @param[in] data : Pointer to store the updated gyro config. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error. - */ -static int8_t check_gyro_config(uint8_t* data, const struct bmi160_dev* dev); - -/*! - * @brief This API process the gyro odr. - * - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error. - */ -static int8_t process_gyro_odr(uint8_t* data, const struct bmi160_dev* dev); - -/*! - * @brief This API process the gyro bandwidth. - * - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error. - */ -static int8_t process_gyro_bw(uint8_t* data, const struct bmi160_dev* dev); - -/*! - * @brief This API process the gyro range. - * - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error. - */ -static int8_t process_gyro_range(uint8_t* data, const struct bmi160_dev* dev); - -/*! - * @brief This API sets the accel power mode. - * - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error. - */ -static int8_t set_accel_pwr(struct bmi160_dev* dev); - -/*! - * @brief This API process the undersampling setting of Accel. - * - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error. - */ -static int8_t process_under_sampling(uint8_t* data, const struct bmi160_dev* dev); - -/*! - * @brief This API sets the gyro power mode. - * - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error. - */ -static int8_t set_gyro_pwr(struct bmi160_dev* dev); - -/*! - * @brief This API reads accel data along with sensor time if time is requested - * by user. Kindly refer the user guide(README.md) for more info. - * - * @param[in] len : len to read no of bytes - * @param[out] accel : Structure pointer to store accel data - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t - get_accel_data(uint8_t len, struct bmi160_sensor_data* accel, const struct bmi160_dev* dev); - -/*! - * @brief This API reads accel data along with sensor time if time is requested - * by user. Kindly refer the user guide(README.md) for more info. - * - * @param[in] len : len to read no of bytes - * @param[out] gyro : Structure pointer to store accel data - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t - get_gyro_data(uint8_t len, struct bmi160_sensor_data* gyro, const struct bmi160_dev* dev); - -/*! - * @brief This API reads accel and gyro data along with sensor time - * if time is requested by user. - * Kindly refer the user guide(README.md) for more info. - * - * @param[in] len : len to read no of bytes - * @param[out] accel : Structure pointer to store accel data - * @param[out] gyro : Structure pointer to store accel data - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t get_accel_gyro_data( - uint8_t len, - struct bmi160_sensor_data* accel, - struct bmi160_sensor_data* gyro, - const struct bmi160_dev* dev); - -/*! - * @brief This API enables the any-motion interrupt for accel. - * - * @param[in] any_motion_int_cfg : Structure instance of - * bmi160_acc_any_mot_int_cfg. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t enable_accel_any_motion_int( - const struct bmi160_acc_any_mot_int_cfg* any_motion_int_cfg, - struct bmi160_dev* dev); - -/*! - * @brief This API disable the sig-motion interrupt. - * - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t disable_sig_motion_int(const struct bmi160_dev* dev); - -/*! - * @brief This API configure the source of data(filter & pre-filter) - * for any-motion interrupt. - * - * @param[in] any_motion_int_cfg : Structure instance of - * bmi160_acc_any_mot_int_cfg. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t config_any_motion_src( - const struct bmi160_acc_any_mot_int_cfg* any_motion_int_cfg, - const struct bmi160_dev* dev); - -/*! - * @brief This API configure the duration and threshold of - * any-motion interrupt. - * - * @param[in] any_motion_int_cfg : Structure instance of - * bmi160_acc_any_mot_int_cfg. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t config_any_dur_threshold( - const struct bmi160_acc_any_mot_int_cfg* any_motion_int_cfg, - const struct bmi160_dev* dev); - -/*! - * @brief This API configure necessary setting of any-motion interrupt. - * - * @param[in] int_config : Structure instance of bmi160_int_settg. - * @param[in] any_motion_int_cfg : Structure instance of - * bmi160_acc_any_mot_int_cfg. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t config_any_motion_int_settg( - const struct bmi160_int_settg* int_config, - const struct bmi160_acc_any_mot_int_cfg* any_motion_int_cfg, - const struct bmi160_dev* dev); - -/*! - * @brief This API enable the data ready interrupt. - * - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t enable_data_ready_int(const struct bmi160_dev* dev); - -/*! - * @brief This API enables the no motion/slow motion interrupt. - * - * @param[in] no_mot_int_cfg : Structure instance of - * bmi160_acc_no_motion_int_cfg. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t enable_no_motion_int( - const struct bmi160_acc_no_motion_int_cfg* no_mot_int_cfg, - const struct bmi160_dev* dev); - -/*! - * @brief This API configure the interrupt PIN setting for - * no motion/slow motion interrupt. - * - * @param[in] int_config : structure instance of bmi160_int_settg. - * @param[in] no_mot_int_cfg : Structure instance of - * bmi160_acc_no_motion_int_cfg. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t config_no_motion_int_settg( - const struct bmi160_int_settg* int_config, - const struct bmi160_acc_no_motion_int_cfg* no_mot_int_cfg, - const struct bmi160_dev* dev); - -/*! - * @brief This API configure the source of interrupt for no motion. - * - * @param[in] no_mot_int_cfg : Structure instance of - * bmi160_acc_no_motion_int_cfg. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t config_no_motion_data_src( - const struct bmi160_acc_no_motion_int_cfg* no_mot_int_cfg, - const struct bmi160_dev* dev); - -/*! - * @brief This API configure the duration and threshold of - * no motion/slow motion interrupt along with selection of no/slow motion. - * - * @param[in] no_mot_int_cfg : Structure instance of - * bmi160_acc_no_motion_int_cfg. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t config_no_motion_dur_thr( - const struct bmi160_acc_no_motion_int_cfg* no_mot_int_cfg, - const struct bmi160_dev* dev); - -/*! - * @brief This API enables the sig-motion motion interrupt. - * - * @param[in] sig_mot_int_cfg : Structure instance of - * bmi160_acc_sig_mot_int_cfg. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t enable_sig_motion_int( - const struct bmi160_acc_sig_mot_int_cfg* sig_mot_int_cfg, - struct bmi160_dev* dev); - -/*! - * @brief This API configure the interrupt PIN setting for - * significant motion interrupt. - * - * @param[in] int_config : Structure instance of bmi160_int_settg. - * @param[in] sig_mot_int_cfg : Structure instance of - * bmi160_acc_sig_mot_int_cfg. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t config_sig_motion_int_settg( - const struct bmi160_int_settg* int_config, - const struct bmi160_acc_sig_mot_int_cfg* sig_mot_int_cfg, - const struct bmi160_dev* dev); - -/*! - * @brief This API configure the source of data(filter & pre-filter) - * for sig motion interrupt. - * - * @param[in] sig_mot_int_cfg : Structure instance of - * bmi160_acc_sig_mot_int_cfg. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t config_sig_motion_data_src( - const struct bmi160_acc_sig_mot_int_cfg* sig_mot_int_cfg, - const struct bmi160_dev* dev); - -/*! - * @brief This API configure the threshold, skip and proof time of - * sig motion interrupt. - * - * @param[in] sig_mot_int_cfg : Structure instance of - * bmi160_acc_sig_mot_int_cfg. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t config_sig_dur_threshold( - const struct bmi160_acc_sig_mot_int_cfg* sig_mot_int_cfg, - const struct bmi160_dev* dev); - -/*! - * @brief This API enables the step detector interrupt. - * - * @param[in] step_detect_int_cfg : Structure instance of - * bmi160_acc_step_detect_int_cfg. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t enable_step_detect_int( - const struct bmi160_acc_step_detect_int_cfg* step_detect_int_cfg, - const struct bmi160_dev* dev); - -/*! - * @brief This API configure the step detector parameter. - * - * @param[in] step_detect_int_cfg : Structure instance of - * bmi160_acc_step_detect_int_cfg. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t config_step_detect( - const struct bmi160_acc_step_detect_int_cfg* step_detect_int_cfg, - const struct bmi160_dev* dev); - -/*! - * @brief This API enables the single/double tap interrupt. - * - * @param[in] int_config : Structure instance of bmi160_int_settg. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t enable_tap_int( - const struct bmi160_int_settg* int_config, - const struct bmi160_acc_tap_int_cfg* tap_int_cfg, - const struct bmi160_dev* dev); - -/*! - * @brief This API configure the interrupt PIN setting for - * tap interrupt. - * - * @param[in] int_config : Structure instance of bmi160_int_settg. - * @param[in] tap_int_cfg : Structure instance of bmi160_acc_tap_int_cfg. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t config_tap_int_settg( - const struct bmi160_int_settg* int_config, - const struct bmi160_acc_tap_int_cfg* tap_int_cfg, - const struct bmi160_dev* dev); - -/*! - * @brief This API configure the source of data(filter & pre-filter) - * for tap interrupt. - * - * @param[in] tap_int_cfg : Structure instance of bmi160_acc_tap_int_cfg. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t config_tap_data_src( - const struct bmi160_acc_tap_int_cfg* tap_int_cfg, - const struct bmi160_dev* dev); - -/*! - * @brief This API configure the parameters of tap interrupt. - * Threshold, quite, shock, and duration. - * - * @param[in] int_config : Structure instance of bmi160_int_settg. - * @param[in] tap_int_cfg : Structure instance of bmi160_acc_tap_int_cfg. - * @param[in] dev : structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t config_tap_param( - const struct bmi160_int_settg* int_config, - const struct bmi160_acc_tap_int_cfg* tap_int_cfg, - const struct bmi160_dev* dev); - -/*! - * @brief This API enable the external mode configuration. - * - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t config_sec_if(const struct bmi160_dev* dev); - -/*! - * @brief This API configure the ODR of the auxiliary sensor. - * - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t config_aux_odr(const struct bmi160_dev* dev); - -/*! - * @brief This API maps the actual burst read length set by user. - * - * @param[in] len : Pointer to store the read length. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t map_read_len(uint16_t* len, const struct bmi160_dev* dev); - -/*! - * @brief This API configure the settings of auxiliary sensor. - * - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t config_aux_settg(const struct bmi160_dev* dev); - -/*! - * @brief This API extract the read data from auxiliary sensor. - * - * @param[in] map_len : burst read value. - * @param[in] reg_addr : Address of register to read. - * @param[in] aux_data : Pointer to store the read data. - * @param[in] len : length to read the data. - * @param[in] dev : Structure instance of bmi160_dev. - * @note : Refer user guide for detailed info. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t extract_aux_read( - uint16_t map_len, - uint8_t reg_addr, - uint8_t* aux_data, - uint16_t len, - const struct bmi160_dev* dev); - -/*! - * @brief This API enables the orient interrupt. - * - * @param[in] orient_int_cfg : Structure instance of bmi160_acc_orient_int_cfg. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t enable_orient_int( - const struct bmi160_acc_orient_int_cfg* orient_int_cfg, - const struct bmi160_dev* dev); - -/*! - * @brief This API configure the necessary setting of orientation interrupt. - * - * @param[in] orient_int_cfg : Structure instance of bmi160_acc_orient_int_cfg. - * @param[in] dev : structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t config_orient_int_settg( - const struct bmi160_acc_orient_int_cfg* orient_int_cfg, - const struct bmi160_dev* dev); - -/*! - * @brief This API enables the flat interrupt. - * - * @param[in] flat_int : Structure instance of bmi160_acc_flat_detect_int_cfg. - * @param[in] dev : structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t enable_flat_int( - const struct bmi160_acc_flat_detect_int_cfg* flat_int, - const struct bmi160_dev* dev); - -/*! - * @brief This API configure the necessary setting of flat interrupt. - * - * @param[in] flat_int : Structure instance of bmi160_acc_flat_detect_int_cfg. - * @param[in] dev : structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t config_flat_int_settg( - const struct bmi160_acc_flat_detect_int_cfg* flat_int, - const struct bmi160_dev* dev); - -/*! - * @brief This API enables the Low-g interrupt. - * - * @param[in] low_g_int : Structure instance of bmi160_acc_low_g_int_cfg. - * @param[in] dev : structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t enable_low_g_int( - const struct bmi160_acc_low_g_int_cfg* low_g_int, - const struct bmi160_dev* dev); - -/*! - * @brief This API configure the source of data(filter & pre-filter) for low-g interrupt. - * - * @param[in] low_g_int : Structure instance of bmi160_acc_low_g_int_cfg. - * @param[in] dev : structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t config_low_g_data_src( - const struct bmi160_acc_low_g_int_cfg* low_g_int, - const struct bmi160_dev* dev); - -/*! - * @brief This API configure the necessary setting of low-g interrupt. - * - * @param[in] low_g_int : Structure instance of bmi160_acc_low_g_int_cfg. - * @param[in] dev : structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t config_low_g_int_settg( - const struct bmi160_acc_low_g_int_cfg* low_g_int, - const struct bmi160_dev* dev); - -/*! - * @brief This API enables the high-g interrupt. - * - * @param[in] high_g_int_cfg : Structure instance of bmi160_acc_high_g_int_cfg. - * @param[in] dev : structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t enable_high_g_int( - const struct bmi160_acc_high_g_int_cfg* high_g_int_cfg, - const struct bmi160_dev* dev); - -/*! - * @brief This API configure the source of data(filter & pre-filter) - * for high-g interrupt. - * - * @param[in] high_g_int_cfg : Structure instance of bmi160_acc_high_g_int_cfg. - * @param[in] dev : structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t config_high_g_data_src( - const struct bmi160_acc_high_g_int_cfg* high_g_int_cfg, - const struct bmi160_dev* dev); - -/*! - * @brief This API configure the necessary setting of high-g interrupt. - * - * @param[in] high_g_int_cfg : Structure instance of bmi160_acc_high_g_int_cfg. - * @param[in] dev : structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t config_high_g_int_settg( - const struct bmi160_acc_high_g_int_cfg* high_g_int_cfg, - const struct bmi160_dev* dev); - -/*! - * @brief This API configure the behavioural setting of interrupt pin. - * - * @param[in] int_config : Structure instance of bmi160_int_settg. - * @param[in] dev : structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t - config_int_out_ctrl(const struct bmi160_int_settg* int_config, const struct bmi160_dev* dev); - -/*! - * @brief This API configure the mode(input enable, latch or non-latch) of interrupt pin. - * - * @param[in] int_config : Structure instance of bmi160_int_settg. - * @param[in] dev : structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t - config_int_latch(const struct bmi160_int_settg* int_config, const struct bmi160_dev* dev); - -/*! - * @brief This API performs the self test for accelerometer of BMI160 - * - * @param[in] dev : structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t perform_accel_self_test(struct bmi160_dev* dev); - -/*! - * @brief This API enables to perform the accel self test by setting proper - * configurations to facilitate accel self test - * - * @param[in] dev : structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t enable_accel_self_test(struct bmi160_dev* dev); - -/*! - * @brief This API performs accel self test with positive excitation - * - * @param[in] accel_pos : Structure pointer to store accel data - * for positive excitation - * @param[in] dev : structure instance of bmi160_dev - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t accel_self_test_positive_excitation( - struct bmi160_sensor_data* accel_pos, - const struct bmi160_dev* dev); - -/*! - * @brief This API performs accel self test with negative excitation - * - * @param[in] accel_neg : Structure pointer to store accel data - * for negative excitation - * @param[in] dev : structure instance of bmi160_dev - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t accel_self_test_negative_excitation( - struct bmi160_sensor_data* accel_neg, - const struct bmi160_dev* dev); - -/*! - * @brief This API validates the accel self test results - * - * @param[in] accel_pos : Structure pointer to store accel data - * for positive excitation - * @param[in] accel_neg : Structure pointer to store accel data - * for negative excitation - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error / +ve value -> Self test fail - */ -static int8_t validate_accel_self_test( - const struct bmi160_sensor_data* accel_pos, - const struct bmi160_sensor_data* accel_neg); - -/*! - * @brief This API performs the self test for gyroscope of BMI160 - * - * @param[in] dev : structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t perform_gyro_self_test(const struct bmi160_dev* dev); - -/*! - * @brief This API enables the self test bit to trigger self test for gyro - * - * @param[in] dev : structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t enable_gyro_self_test(const struct bmi160_dev* dev); - -/*! - * @brief This API validates the self test results of gyro - * - * @param[in] dev : structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t validate_gyro_self_test(const struct bmi160_dev* dev); - -/*! - * @brief This API sets FIFO full interrupt of the sensor.This interrupt - * occurs when the FIFO is full and the next full data sample would cause - * a FIFO overflow, which may delete the old samples. - * - * @param[in] int_config : Structure instance of bmi160_int_settg. - * @param[in] dev : structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t - set_fifo_full_int(const struct bmi160_int_settg* int_config, const struct bmi160_dev* dev); - -/*! - * @brief This enable the FIFO full interrupt engine. - * - * @param[in] int_config : Structure instance of bmi160_int_settg. - * @param[in] dev : structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t - enable_fifo_full_int(const struct bmi160_int_settg* int_config, const struct bmi160_dev* dev); - -/*! - * @brief This API sets FIFO watermark interrupt of the sensor.The FIFO - * watermark interrupt is fired, when the FIFO fill level is above a fifo - * watermark. - * - * @param[in] int_config : Structure instance of bmi160_int_settg. - * @param[in] dev : structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t - set_fifo_watermark_int(const struct bmi160_int_settg* int_config, const struct bmi160_dev* dev); - -/*! - * @brief This enable the FIFO watermark interrupt engine. - * - * @param[in] int_config : Structure instance of bmi160_int_settg. - * @param[in] dev : structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t - enable_fifo_wtm_int(const struct bmi160_int_settg* int_config, const struct bmi160_dev* dev); - -/*! - * @brief This API is used to reset the FIFO related configurations - * in the fifo_frame structure. - * - * @param[in] dev : structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static void reset_fifo_data_structure(const struct bmi160_dev* dev); - -/*! - * @brief This API is used to read number of bytes filled - * currently in FIFO buffer. - * - * @param[in] bytes_to_read : Number of bytes available in FIFO at the - * instant which is obtained from FIFO counter. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error. - * @retval Any non zero value -> Fail - * - */ -static int8_t get_fifo_byte_counter(uint16_t* bytes_to_read, struct bmi160_dev const* dev); - -/*! - * @brief This API is used to compute the number of bytes of accel FIFO data - * which is to be parsed in header-less mode - * - * @param[out] data_index : The start index for parsing data - * @param[out] data_read_length : Number of bytes to be parsed - * @param[in] acc_frame_count : Number of accelerometer frames to be read - * @param[in] dev : Structure instance of bmi160_dev. - * - */ -static void get_accel_len_to_parse( - uint16_t* data_index, - uint16_t* data_read_length, - const uint8_t* acc_frame_count, - const struct bmi160_dev* dev); - -/*! - * @brief This API is used to parse the accelerometer data from the - * FIFO data in both header mode and header-less mode. - * It updates the idx value which is used to store the index of - * the current data byte which is parsed. - * - * @param[in,out] acc : structure instance of sensor data - * @param[in,out] idx : Index value of number of bytes parsed - * @param[in,out] acc_idx : Index value of accelerometer data - * (x,y,z axes) frames parsed - * @param[in] frame_info : It consists of either fifo_data_enable - * parameter in header-less mode or - * frame header data in header mode - * @param[in] dev : structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static void unpack_accel_frame( - struct bmi160_sensor_data* acc, - uint16_t* idx, - uint8_t* acc_idx, - uint8_t frame_info, - const struct bmi160_dev* dev); - -/*! - * @brief This API is used to parse the accelerometer data from the - * FIFO data and store it in the instance of the structure bmi160_sensor_data. - * - * @param[in,out] accel_data : structure instance of sensor data - * @param[in,out] data_start_index : Index value of number of bytes parsed - * @param[in] dev : structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static void unpack_accel_data( - struct bmi160_sensor_data* accel_data, - uint16_t data_start_index, - const struct bmi160_dev* dev); - -/*! - * @brief This API is used to parse the accelerometer data from the - * FIFO data in header mode. - * - * @param[in,out] accel_data : Structure instance of sensor data - * @param[in,out] accel_length : Number of accelerometer frames - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static void extract_accel_header_mode( - struct bmi160_sensor_data* accel_data, - uint8_t* accel_length, - const struct bmi160_dev* dev); - -/*! - * @brief This API computes the number of bytes of gyro FIFO data - * which is to be parsed in header-less mode - * - * @param[out] data_index : The start index for parsing data - * @param[out] data_read_length : No of bytes to be parsed from FIFO buffer - * @param[in] gyro_frame_count : Number of Gyro data frames to be read - * @param[in] dev : Structure instance of bmi160_dev. - */ -static void get_gyro_len_to_parse( - uint16_t* data_index, - uint16_t* data_read_length, - const uint8_t* gyro_frame_count, - const struct bmi160_dev* dev); - -/*! - * @brief This API is used to parse the gyroscope's data from the - * FIFO data in both header mode and header-less mode. - * It updates the idx value which is used to store the index of - * the current data byte which is parsed. - * - * @param[in,out] gyro : structure instance of sensor data - * @param[in,out] idx : Index value of number of bytes parsed - * @param[in,out] gyro_idx : Index value of gyro data - * (x,y,z axes) frames parsed - * @param[in] frame_info : It consists of either fifo_data_enable - * parameter in header-less mode or - * frame header data in header mode - * @param[in] dev : structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static void unpack_gyro_frame( - struct bmi160_sensor_data* gyro, - uint16_t* idx, - uint8_t* gyro_idx, - uint8_t frame_info, - const struct bmi160_dev* dev); - -/*! - * @brief This API is used to parse the gyro data from the - * FIFO data and store it in the instance of the structure bmi160_sensor_data. - * - * @param[in,out] gyro_data : structure instance of sensor data - * @param[in,out] data_start_index : Index value of number of bytes parsed - * @param[in] dev : structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static void unpack_gyro_data( - struct bmi160_sensor_data* gyro_data, - uint16_t data_start_index, - const struct bmi160_dev* dev); - -/*! - * @brief This API is used to parse the gyro data from the - * FIFO data in header mode. - * - * @param[in,out] gyro_data : Structure instance of sensor data - * @param[in,out] gyro_length : Number of gyro frames - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static void extract_gyro_header_mode( - struct bmi160_sensor_data* gyro_data, - uint8_t* gyro_length, - const struct bmi160_dev* dev); - -/*! - * @brief This API computes the number of bytes of aux FIFO data - * which is to be parsed in header-less mode - * - * @param[out] data_index : The start index for parsing data - * @param[out] data_read_length : No of bytes to be parsed from FIFO buffer - * @param[in] aux_frame_count : Number of Aux data frames to be read - * @param[in] dev : Structure instance of bmi160_dev. - */ -static void get_aux_len_to_parse( - uint16_t* data_index, - uint16_t* data_read_length, - const uint8_t* aux_frame_count, - const struct bmi160_dev* dev); - -/*! - * @brief This API is used to parse the aux's data from the - * FIFO data in both header mode and header-less mode. - * It updates the idx value which is used to store the index of - * the current data byte which is parsed - * - * @param[in,out] aux_data : structure instance of sensor data - * @param[in,out] idx : Index value of number of bytes parsed - * @param[in,out] aux_index : Index value of gyro data - * (x,y,z axes) frames parsed - * @param[in] frame_info : It consists of either fifo_data_enable - * parameter in header-less mode or - * frame header data in header mode - * @param[in] dev : structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static void unpack_aux_frame( - struct bmi160_aux_data* aux_data, - uint16_t* idx, - uint8_t* aux_index, - uint8_t frame_info, - const struct bmi160_dev* dev); - -/*! - * @brief This API is used to parse the aux data from the - * FIFO data and store it in the instance of the structure bmi160_aux_data. - * - * @param[in,out] aux_data : structure instance of sensor data - * @param[in,out] data_start_index : Index value of number of bytes parsed - * @param[in] dev : structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static void unpack_aux_data( - struct bmi160_aux_data* aux_data, - uint16_t data_start_index, - const struct bmi160_dev* dev); - -/*! - * @brief This API is used to parse the aux data from the - * FIFO data in header mode. - * - * @param[in,out] aux_data : Structure instance of sensor data - * @param[in,out] aux_length : Number of aux frames - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static void extract_aux_header_mode( - struct bmi160_aux_data* aux_data, - uint8_t* aux_length, - const struct bmi160_dev* dev); - -/*! - * @brief This API checks the presence of non-valid frames in the read fifo data. - * - * @param[in,out] data_index : The index of the current data to - * be parsed from fifo data - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static void check_frame_validity(uint16_t* data_index, const struct bmi160_dev* dev); - -/*! - * @brief This API is used to move the data index ahead of the - * current_frame_length parameter when unnecessary FIFO data appears while - * extracting the user specified data. - * - * @param[in,out] data_index : Index of the FIFO data which - * is to be moved ahead of the - * current_frame_length - * @param[in] current_frame_length : Number of bytes in a particular frame - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static void move_next_frame( - uint16_t* data_index, - uint8_t current_frame_length, - const struct bmi160_dev* dev); - -/*! - * @brief This API is used to parse and store the sensor time from the - * FIFO data in the structure instance dev. - * - * @param[in,out] data_index : Index of the FIFO data which - * has the sensor time. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static void unpack_sensortime_frame(uint16_t* data_index, const struct bmi160_dev* dev); - -/*! - * @brief This API is used to parse and store the skipped_frame_count from - * the FIFO data in the structure instance dev. - * - * @param[in,out] data_index : Index of the FIFO data which - * has the skipped frame count. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static void unpack_skipped_frame(uint16_t* data_index, const struct bmi160_dev* dev); - -/*! - * @brief This API is used to get the FOC status from the sensor - * - * @param[in,out] foc_status : Result of FOC status. - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t get_foc_status(uint8_t* foc_status, struct bmi160_dev const* dev); - -/*! - * @brief This API is used to configure the offset enable bits in the sensor - * - * @param[in,out] foc_conf : Structure instance of bmi160_foc_conf which - * has the FOC and offset configurations - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t - configure_offset_enable(const struct bmi160_foc_conf* foc_conf, struct bmi160_dev const* dev); - -/*! - * @brief This API is used to trigger the FOC in the sensor - * - * @param[in,out] offset : Structure instance of bmi160_offsets which - * reads and stores the offset values after FOC - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t trigger_foc(struct bmi160_offsets* offset, struct bmi160_dev const* dev); - -/*! - * @brief This API is used to map/unmap the Dataready(Accel & Gyro), FIFO full - * and FIFO watermark interrupt - * - * @param[in] int_config : Structure instance of bmi160_int_settg which - * stores the interrupt type and interrupt channel - * configurations to map/unmap the interrupt pins - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t - map_hardware_interrupt(const struct bmi160_int_settg* int_config, const struct bmi160_dev* dev); - -/*! - * @brief This API is used to map/unmap the Any/Sig motion, Step det/Low-g, - * Double tap, Single tap, Orientation, Flat, High-G, Nomotion interrupt pins. - * - * @param[in] int_config : Structure instance of bmi160_int_settg which - * stores the interrupt type and interrupt channel - * configurations to map/unmap the interrupt pins - * @param[in] dev : Structure instance of bmi160_dev. - * - * @return Result of API execution status - * @retval zero -> Success / -ve value -> Error - */ -static int8_t - map_feature_interrupt(const struct bmi160_int_settg* int_config, const struct bmi160_dev* dev); - -/*********************** User function definitions ****************************/ - -/*! - * @brief This API reads the data from the given register address - * of sensor. - */ -int8_t - bmi160_get_regs(uint8_t reg_addr, uint8_t* data, uint16_t len, const struct bmi160_dev* dev) { - int8_t rslt = BMI160_OK; - - /* Null-pointer check */ - if((dev == NULL) || (dev->read == NULL)) { - rslt = BMI160_E_NULL_PTR; - } else if(len == 0) { - rslt = BMI160_E_READ_WRITE_LENGTH_INVALID; - } else { - /* Configuring reg_addr for SPI Interface */ - if(dev->intf == BMI160_SPI_INTF) { - reg_addr = (reg_addr | BMI160_SPI_RD_MASK); - } - - rslt = dev->read(dev->id, reg_addr, data, len); - } - - return rslt; -} - -/*! - * @brief This API writes the given data to the register address - * of sensor. - */ -int8_t - bmi160_set_regs(uint8_t reg_addr, uint8_t* data, uint16_t len, const struct bmi160_dev* dev) { - int8_t rslt = BMI160_OK; - uint8_t count = 0; - - /* Null-pointer check */ - if((dev == NULL) || (dev->write == NULL)) { - rslt = BMI160_E_NULL_PTR; - } else if(len == 0) { - rslt = BMI160_E_READ_WRITE_LENGTH_INVALID; - } else { - /* Configuring reg_addr for SPI Interface */ - if(dev->intf == BMI160_SPI_INTF) { - reg_addr = (reg_addr & BMI160_SPI_WR_MASK); - } - - if((dev->prev_accel_cfg.power == BMI160_ACCEL_NORMAL_MODE) || - (dev->prev_gyro_cfg.power == BMI160_GYRO_NORMAL_MODE)) { - rslt = dev->write(dev->id, reg_addr, data, len); - - /* Kindly refer bmi160 data sheet section 3.2.4 */ - dev->delay_ms(1); - - } else { - /*Burst write is not allowed in - * suspend & low power mode */ - for(; count < len; count++) { - rslt = dev->write(dev->id, reg_addr, &data[count], 1); - reg_addr++; - - /* Kindly refer bmi160 data sheet section 3.2.4 */ - dev->delay_ms(1); - } - } - - if(rslt != BMI160_OK) { - rslt = BMI160_E_COM_FAIL; - } - } - - return rslt; -} - -/*! - * @brief This API is the entry point for sensor.It performs - * the selection of I2C/SPI read mechanism according to the - * selected interface and reads the chip-id of bmi160 sensor. - */ -int8_t bmi160_init(struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data; - uint8_t try = 3; - - /* Null-pointer check */ - rslt = null_ptr_check(dev); - - /* Dummy read of 0x7F register to enable SPI Interface - * if SPI is used */ - if((rslt == BMI160_OK) && (dev->intf == BMI160_SPI_INTF)) { - rslt = bmi160_get_regs(BMI160_SPI_COMM_TEST_ADDR, &data, 1, dev); - } - - if(rslt == BMI160_OK) { - /* Assign chip id as zero */ - dev->chip_id = 0; - - while((try--) && (dev->chip_id != BMI160_CHIP_ID)) { - /* Read chip_id */ - rslt = bmi160_get_regs(BMI160_CHIP_ID_ADDR, &dev->chip_id, 1, dev); - } - - if((rslt == BMI160_OK) && (dev->chip_id == BMI160_CHIP_ID)) { - dev->any_sig_sel = BMI160_BOTH_ANY_SIG_MOTION_DISABLED; - - /* Soft reset */ - rslt = bmi160_soft_reset(dev); - } else { - rslt = BMI160_E_DEV_NOT_FOUND; - } - } - - return rslt; -} - -/*! - * @brief This API resets and restarts the device. - * All register values are overwritten with default parameters. - */ -int8_t bmi160_soft_reset(struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data = BMI160_SOFT_RESET_CMD; - - /* Null-pointer check */ - if((dev == NULL) || (dev->delay_ms == NULL)) { - rslt = BMI160_E_NULL_PTR; - } else { - /* Reset the device */ - rslt = bmi160_set_regs(BMI160_COMMAND_REG_ADDR, &data, 1, dev); - dev->delay_ms(BMI160_SOFT_RESET_DELAY_MS); - if((rslt == BMI160_OK) && (dev->intf == BMI160_SPI_INTF)) { - /* Dummy read of 0x7F register to enable SPI Interface - * if SPI is used */ - rslt = bmi160_get_regs(BMI160_SPI_COMM_TEST_ADDR, &data, 1, dev); - } - - if(rslt == BMI160_OK) { - /* Update the default parameters */ - default_param_settg(dev); - } - } - - return rslt; -} - -/*! - * @brief This API configures the power mode, range and bandwidth - * of sensor. - */ -int8_t bmi160_set_sens_conf(struct bmi160_dev* dev) { - int8_t rslt = BMI160_OK; - - /* Null-pointer check */ - if((dev == NULL) || (dev->delay_ms == NULL)) { - rslt = BMI160_E_NULL_PTR; - } else { - rslt = set_accel_conf(dev); - if(rslt == BMI160_OK) { - rslt = set_gyro_conf(dev); - if(rslt == BMI160_OK) { - /* write power mode for accel and gyro */ - rslt = bmi160_set_power_mode(dev); - if(rslt == BMI160_OK) { - rslt = check_invalid_settg(dev); - } - } - } - } - - return rslt; -} - -/*! - * @brief This API gets accel and gyro configurations. - */ -int8_t bmi160_get_sens_conf(struct bmi160_dev* dev) { - int8_t rslt = BMI160_OK; - - /* Null-pointer check */ - if((dev == NULL) || (dev->delay_ms == NULL)) { - rslt = BMI160_E_NULL_PTR; - } else { - rslt = get_accel_conf(dev); - if(rslt == BMI160_OK) { - rslt = get_gyro_conf(dev); - } - } - - return rslt; -} - -/*! - * @brief This API sets the power mode of the sensor. - */ -int8_t bmi160_set_power_mode(struct bmi160_dev* dev) { - int8_t rslt = 0; - - /* Null-pointer check */ - if((dev == NULL) || (dev->delay_ms == NULL)) { - rslt = BMI160_E_NULL_PTR; - } else { - rslt = set_accel_pwr(dev); - if(rslt == BMI160_OK) { - rslt = set_gyro_pwr(dev); - } - } - - return rslt; -} - -/*! - * @brief This API gets the power mode of the sensor. - */ -int8_t bmi160_get_power_mode(struct bmi160_dev* dev) { - int8_t rslt = 0; - uint8_t power_mode = 0; - - /* Null-pointer check */ - if((dev == NULL) || (dev->delay_ms == NULL)) { - rslt = BMI160_E_NULL_PTR; - } else { - rslt = bmi160_get_regs(BMI160_PMU_STATUS_ADDR, &power_mode, 1, dev); - if(rslt == BMI160_OK) { - /* Power mode of the accel, gyro sensor is obtained */ - dev->gyro_cfg.power = BMI160_GET_BITS(power_mode, BMI160_GYRO_POWER_MODE); - dev->accel_cfg.power = BMI160_GET_BITS(power_mode, BMI160_ACCEL_POWER_MODE); - } - } - - return rslt; -} - -/*! - * @brief This API reads sensor data, stores it in - * the bmi160_sensor_data structure pointer passed by the user. - */ -int8_t bmi160_get_sensor_data( - uint8_t select_sensor, - struct bmi160_sensor_data* accel, - struct bmi160_sensor_data* gyro, - const struct bmi160_dev* dev) { - int8_t rslt = BMI160_OK; - uint8_t time_sel; - uint8_t sen_sel; - uint8_t len = 0; - - /*Extract the sensor and time select information*/ - sen_sel = select_sensor & BMI160_SEN_SEL_MASK; - time_sel = ((sen_sel & BMI160_TIME_SEL) >> 2); - sen_sel = sen_sel & (BMI160_ACCEL_SEL | BMI160_GYRO_SEL); - if(time_sel == 1) { - len = 3; - } - - /* Null-pointer check */ - if(dev != NULL) { - switch(sen_sel) { - case BMI160_ACCEL_ONLY: - - /* Null-pointer check */ - if(accel == NULL) { - rslt = BMI160_E_NULL_PTR; - } else { - rslt = get_accel_data(len, accel, dev); - } - - break; - case BMI160_GYRO_ONLY: - - /* Null-pointer check */ - if(gyro == NULL) { - rslt = BMI160_E_NULL_PTR; - } else { - rslt = get_gyro_data(len, gyro, dev); - } - - break; - case BMI160_BOTH_ACCEL_AND_GYRO: - - /* Null-pointer check */ - if((gyro == NULL) || (accel == NULL)) { - rslt = BMI160_E_NULL_PTR; - } else { - rslt = get_accel_gyro_data(len, accel, gyro, dev); - } - - break; - default: - rslt = BMI160_E_INVALID_INPUT; - break; - } - } else { - rslt = BMI160_E_NULL_PTR; - } - - return rslt; -} - -/*! - * @brief This API configures the necessary interrupt based on - * the user settings in the bmi160_int_settg structure instance. - */ -int8_t bmi160_set_int_config(struct bmi160_int_settg* int_config, struct bmi160_dev* dev) { - int8_t rslt = BMI160_OK; - - switch(int_config->int_type) { - case BMI160_ACC_ANY_MOTION_INT: - - /*Any-motion interrupt*/ - rslt = set_accel_any_motion_int(int_config, dev); - break; - case BMI160_ACC_SIG_MOTION_INT: - - /* Significant motion interrupt */ - rslt = set_accel_sig_motion_int(int_config, dev); - break; - case BMI160_ACC_SLOW_NO_MOTION_INT: - - /* Slow or no motion interrupt */ - rslt = set_accel_no_motion_int(int_config, dev); - break; - case BMI160_ACC_DOUBLE_TAP_INT: - case BMI160_ACC_SINGLE_TAP_INT: - - /* Double tap and single tap Interrupt */ - rslt = set_accel_tap_int(int_config, dev); - break; - case BMI160_STEP_DETECT_INT: - - /* Step detector interrupt */ - rslt = set_accel_step_detect_int(int_config, dev); - break; - case BMI160_ACC_ORIENT_INT: - - /* Orientation interrupt */ - rslt = set_accel_orientation_int(int_config, dev); - break; - case BMI160_ACC_FLAT_INT: - - /* Flat detection interrupt */ - rslt = set_accel_flat_detect_int(int_config, dev); - break; - case BMI160_ACC_LOW_G_INT: - - /* Low-g interrupt */ - rslt = set_accel_low_g_int(int_config, dev); - break; - case BMI160_ACC_HIGH_G_INT: - - /* High-g interrupt */ - rslt = set_accel_high_g_int(int_config, dev); - break; - case BMI160_ACC_GYRO_DATA_RDY_INT: - - /* Data ready interrupt */ - rslt = set_accel_gyro_data_ready_int(int_config, dev); - break; - case BMI160_ACC_GYRO_FIFO_FULL_INT: - - /* Fifo full interrupt */ - rslt = set_fifo_full_int(int_config, dev); - break; - case BMI160_ACC_GYRO_FIFO_WATERMARK_INT: - - /* Fifo water-mark interrupt */ - rslt = set_fifo_watermark_int(int_config, dev); - break; - case BMI160_FIFO_TAG_INT_PIN: - - /* Fifo tagging feature support */ - /* Configure Interrupt pins */ - rslt = set_intr_pin_config(int_config, dev); - break; - default: - break; - } - - return rslt; -} - -/*! - * @brief This API enables or disable the step counter feature. - * 1 - enable step counter (0 - disable) - */ -int8_t bmi160_set_step_counter(uint8_t step_cnt_enable, const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data = 0; - - /* Null-pointer check */ - rslt = null_ptr_check(dev); - if(rslt != BMI160_OK) { - rslt = BMI160_E_NULL_PTR; - } else { - rslt = bmi160_get_regs(BMI160_INT_STEP_CONFIG_1_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - if(step_cnt_enable == BMI160_ENABLE) { - data |= (uint8_t)(step_cnt_enable << 3); - } else { - data &= ~BMI160_STEP_COUNT_EN_BIT_MASK; - } - - rslt = bmi160_set_regs(BMI160_INT_STEP_CONFIG_1_ADDR, &data, 1, dev); - } - } - - return rslt; -} - -/*! - * @brief This API reads the step counter value. - */ -int8_t bmi160_read_step_counter(uint16_t* step_val, const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data[2] = {0, 0}; - uint16_t msb = 0; - uint8_t lsb = 0; - - /* Null-pointer check */ - rslt = null_ptr_check(dev); - if(rslt != BMI160_OK) { - rslt = BMI160_E_NULL_PTR; - } else { - rslt = bmi160_get_regs(BMI160_INT_STEP_CNT_0_ADDR, data, 2, dev); - if(rslt == BMI160_OK) { - lsb = data[0]; - msb = data[1] << 8; - *step_val = msb | lsb; - } - } - - return rslt; -} - -/*! - * @brief This API reads the mention no of byte of data from the given - * register address of auxiliary sensor. - */ -int8_t bmi160_aux_read( - uint8_t reg_addr, - uint8_t* aux_data, - uint16_t len, - const struct bmi160_dev* dev) { - int8_t rslt = BMI160_OK; - uint16_t map_len = 0; - - /* Null-pointer check */ - if((dev == NULL) || (dev->read == NULL)) { - rslt = BMI160_E_NULL_PTR; - } else { - if(dev->aux_cfg.aux_sensor_enable == BMI160_ENABLE) { - rslt = map_read_len(&map_len, dev); - if(rslt == BMI160_OK) { - rslt = extract_aux_read(map_len, reg_addr, aux_data, len, dev); - } - } else { - rslt = BMI160_E_INVALID_INPUT; - } - } - - return rslt; -} - -/*! - * @brief This API writes the mention no of byte of data to the given - * register address of auxiliary sensor. - */ -int8_t bmi160_aux_write( - uint8_t reg_addr, - uint8_t* aux_data, - uint16_t len, - const struct bmi160_dev* dev) { - int8_t rslt = BMI160_OK; - uint8_t count = 0; - - /* Null-pointer check */ - if((dev == NULL) || (dev->write == NULL)) { - rslt = BMI160_E_NULL_PTR; - } else { - for(; count < len; count++) { - /* set data to write */ - rslt = bmi160_set_regs(BMI160_AUX_IF_4_ADDR, aux_data, 1, dev); - dev->delay_ms(BMI160_AUX_COM_DELAY); - if(rslt == BMI160_OK) { - /* set address to write */ - rslt = bmi160_set_regs(BMI160_AUX_IF_3_ADDR, ®_addr, 1, dev); - dev->delay_ms(BMI160_AUX_COM_DELAY); - if(rslt == BMI160_OK && (count < len - 1)) { - aux_data++; - reg_addr++; - } - } - } - } - - return rslt; -} - -/*! - * @brief This API initialize the auxiliary sensor - * in order to access it. - */ -int8_t bmi160_aux_init(const struct bmi160_dev* dev) { - int8_t rslt; - - /* Null-pointer check */ - rslt = null_ptr_check(dev); - if(rslt != BMI160_OK) { - rslt = BMI160_E_NULL_PTR; - } else { - if(dev->aux_cfg.aux_sensor_enable == BMI160_ENABLE) { - /* Configures the auxiliary sensor interface settings */ - rslt = config_aux_settg(dev); - } else { - rslt = BMI160_E_INVALID_INPUT; - } - } - - return rslt; -} - -/*! - * @brief This API is used to setup the auxiliary sensor of bmi160 in auto mode - * Thus enabling the auto update of 8 bytes of data from auxiliary sensor - * to BMI160 register address 0x04 to 0x0B - */ -int8_t bmi160_set_aux_auto_mode(uint8_t* data_addr, struct bmi160_dev* dev) { - int8_t rslt; - - /* Null-pointer check */ - rslt = null_ptr_check(dev); - if(rslt != BMI160_OK) { - rslt = BMI160_E_NULL_PTR; - } else { - if(dev->aux_cfg.aux_sensor_enable == BMI160_ENABLE) { - /* Write the aux. address to read in 0x4D of BMI160*/ - rslt = bmi160_set_regs(BMI160_AUX_IF_2_ADDR, data_addr, 1, dev); - dev->delay_ms(BMI160_AUX_COM_DELAY); - if(rslt == BMI160_OK) { - /* Configure the polling ODR for - * auxiliary sensor */ - rslt = config_aux_odr(dev); - if(rslt == BMI160_OK) { - /* Disable the aux. manual mode, i.e aux. - * sensor is in auto-mode (data-mode) */ - dev->aux_cfg.manual_enable = BMI160_DISABLE; - rslt = bmi160_config_aux_mode(dev); - - /* Auxiliary sensor data is obtained - * in auto mode from this point */ - } - } - } else { - rslt = BMI160_E_INVALID_INPUT; - } - } - - return rslt; -} - -/*! - * @brief This API configures the 0x4C register and settings like - * Auxiliary sensor manual enable/ disable and aux burst read length. - */ -int8_t bmi160_config_aux_mode(const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t aux_if[2] = {(uint8_t)(dev->aux_cfg.aux_i2c_addr * 2), 0}; - - rslt = bmi160_get_regs(BMI160_AUX_IF_1_ADDR, &aux_if[1], 1, dev); - if(rslt == BMI160_OK) { - /* update the Auxiliary interface to manual/auto mode */ - aux_if[1] = BMI160_SET_BITS(aux_if[1], BMI160_MANUAL_MODE_EN, dev->aux_cfg.manual_enable); - - /* update the burst read length defined by user */ - aux_if[1] = - BMI160_SET_BITS_POS_0(aux_if[1], BMI160_AUX_READ_BURST, dev->aux_cfg.aux_rd_burst_len); - - /* Set the secondary interface address and manual mode - * along with burst read length */ - rslt = bmi160_set_regs(BMI160_AUX_IF_0_ADDR, &aux_if[0], 2, dev); - dev->delay_ms(BMI160_AUX_COM_DELAY); - } - - return rslt; -} - -/*! - * @brief This API is used to read the raw uncompensated auxiliary sensor - * data of 8 bytes from BMI160 register address 0x04 to 0x0B - */ -int8_t bmi160_read_aux_data_auto_mode(uint8_t* aux_data, const struct bmi160_dev* dev) { - int8_t rslt; - - /* Null-pointer check */ - rslt = null_ptr_check(dev); - if(rslt != BMI160_OK) { - rslt = BMI160_E_NULL_PTR; - } else { - if((dev->aux_cfg.aux_sensor_enable == BMI160_ENABLE) && - (dev->aux_cfg.manual_enable == BMI160_DISABLE)) { - /* Read the aux. sensor's raw data */ - rslt = bmi160_get_regs(BMI160_AUX_DATA_ADDR, aux_data, 8, dev); - } else { - rslt = BMI160_E_INVALID_INPUT; - } - } - - return rslt; -} - -/*! - * @brief This is used to perform self test of accel/gyro of the BMI160 sensor - */ -int8_t bmi160_perform_self_test(uint8_t select_sensor, struct bmi160_dev* dev) { - int8_t rslt; - int8_t self_test_rslt = 0; - - /* Null-pointer check */ - rslt = null_ptr_check(dev); - if(rslt != BMI160_OK) { - rslt = BMI160_E_NULL_PTR; - } else { - /* Proceed if null check is fine */ - switch(select_sensor) { - case BMI160_ACCEL_ONLY: - rslt = perform_accel_self_test(dev); - break; - case BMI160_GYRO_ONLY: - - /* Set the power mode as normal mode */ - dev->gyro_cfg.power = BMI160_GYRO_NORMAL_MODE; - rslt = bmi160_set_power_mode(dev); - - /* Perform gyro self test */ - if(rslt == BMI160_OK) { - /* Perform gyro self test */ - rslt = perform_gyro_self_test(dev); - } - - break; - default: - rslt = BMI160_E_INVALID_INPUT; - break; - } - - /* Check to ensure bus error does not occur */ - if(rslt >= BMI160_OK) { - /* Store the status of self test result */ - self_test_rslt = rslt; - - /* Perform soft reset */ - rslt = bmi160_soft_reset(dev); - } - - /* Check to ensure bus operations are success */ - if(rslt == BMI160_OK) { - /* Restore self_test_rslt as return value */ - rslt = self_test_rslt; - } - } - - return rslt; -} - -/*! - * @brief This API reads the data from fifo buffer. - */ -int8_t bmi160_get_fifo_data(struct bmi160_dev const* dev) { - int8_t rslt = 0; - uint16_t bytes_to_read = 0; - uint16_t user_fifo_len = 0; - - /* check the bmi160 structure as NULL*/ - if((dev == NULL) || (dev->fifo->data == NULL)) { - rslt = BMI160_E_NULL_PTR; - } else { - reset_fifo_data_structure(dev); - - /* get current FIFO fill-level*/ - rslt = get_fifo_byte_counter(&bytes_to_read, dev); - if(rslt == BMI160_OK) { - user_fifo_len = dev->fifo->length; - if((dev->fifo->length > bytes_to_read)) { - /* Handling the case where user requests - * more data than available in FIFO */ - dev->fifo->length = bytes_to_read; - } - - if((dev->fifo->fifo_time_enable == BMI160_FIFO_TIME_ENABLE) && - (bytes_to_read + BMI160_FIFO_BYTES_OVERREAD <= user_fifo_len)) { - /* Handling case of sensor time availability*/ - dev->fifo->length = dev->fifo->length + BMI160_FIFO_BYTES_OVERREAD; - } - - /* read only the filled bytes in the FIFO Buffer */ - rslt = bmi160_get_regs(BMI160_FIFO_DATA_ADDR, dev->fifo->data, dev->fifo->length, dev); - } - } - - return rslt; -} - -/*! - * @brief This API writes fifo_flush command to command register.This - * action clears all data in the Fifo without changing fifo configuration - * settings - */ -int8_t bmi160_set_fifo_flush(const struct bmi160_dev* dev) { - int8_t rslt = 0; - uint8_t data = BMI160_FIFO_FLUSH_VALUE; - uint8_t reg_addr = BMI160_COMMAND_REG_ADDR; - - /* Check the bmi160_dev structure for NULL address*/ - if(dev == NULL) { - rslt = BMI160_E_NULL_PTR; - } else { - rslt = bmi160_set_regs(reg_addr, &data, BMI160_ONE, dev); - } - - return rslt; -} - -/*! - * @brief This API sets the FIFO configuration in the sensor. - */ -int8_t bmi160_set_fifo_config(uint8_t config, uint8_t enable, struct bmi160_dev const* dev) { - int8_t rslt = 0; - uint8_t data = 0; - uint8_t reg_addr = BMI160_FIFO_CONFIG_1_ADDR; - uint8_t fifo_config = config & BMI160_FIFO_CONFIG_1_MASK; - - /* Check the bmi160_dev structure for NULL address*/ - if(dev == NULL) { - rslt = BMI160_E_NULL_PTR; - } else { - rslt = bmi160_get_regs(reg_addr, &data, BMI160_ONE, dev); - if(rslt == BMI160_OK) { - if(fifo_config > 0) { - if(enable == BMI160_ENABLE) { - data = data | fifo_config; - } else { - data = data & (~fifo_config); - } - } - - /* write fifo frame content configuration*/ - rslt = bmi160_set_regs(reg_addr, &data, BMI160_ONE, dev); - if(rslt == BMI160_OK) { - /* read fifo frame content configuration*/ - rslt = bmi160_get_regs(reg_addr, &data, BMI160_ONE, dev); - if(rslt == BMI160_OK) { - /* extract fifo header enabled status */ - dev->fifo->fifo_header_enable = data & BMI160_FIFO_HEAD_ENABLE; - - /* extract accel/gyr/aux. data enabled status */ - dev->fifo->fifo_data_enable = data & BMI160_FIFO_M_G_A_ENABLE; - - /* extract fifo sensor time enabled status */ - dev->fifo->fifo_time_enable = data & BMI160_FIFO_TIME_ENABLE; - } - } - } - } - - return rslt; -} - -/*! @brief This API is used to configure the down sampling ratios of - * the accel and gyro data for FIFO.Also, it configures filtered or - * pre-filtered data for accel and gyro. - * - */ -int8_t bmi160_set_fifo_down(uint8_t fifo_down, const struct bmi160_dev* dev) { - int8_t rslt = 0; - uint8_t data = 0; - uint8_t reg_addr = BMI160_FIFO_DOWN_ADDR; - - /* Check the bmi160_dev structure for NULL address*/ - if(dev == NULL) { - rslt = BMI160_E_NULL_PTR; - } else { - rslt = bmi160_get_regs(reg_addr, &data, BMI160_ONE, dev); - if(rslt == BMI160_OK) { - data = data | fifo_down; - rslt = bmi160_set_regs(reg_addr, &data, BMI160_ONE, dev); - } - } - - return rslt; -} - -/*! - * @brief This API sets the FIFO watermark level in the sensor. - * - */ -int8_t bmi160_set_fifo_wm(uint8_t fifo_wm, const struct bmi160_dev* dev) { - int8_t rslt = 0; - uint8_t data = fifo_wm; - uint8_t reg_addr = BMI160_FIFO_CONFIG_0_ADDR; - - /* Check the bmi160_dev structure for NULL address*/ - if(dev == NULL) { - rslt = BMI160_E_NULL_PTR; - } else { - rslt = bmi160_set_regs(reg_addr, &data, BMI160_ONE, dev); - } - - return rslt; -} - -/*! - * @brief This API parses and extracts the accelerometer frames from - * FIFO data read by the "bmi160_get_fifo_data" API and stores it in - * the "accel_data" structure instance. - */ -int8_t bmi160_extract_accel( - struct bmi160_sensor_data* accel_data, - uint8_t* accel_length, - struct bmi160_dev const* dev) { - int8_t rslt = 0; - uint16_t data_index = 0; - uint16_t data_read_length = 0; - uint8_t accel_index = 0; - uint8_t fifo_data_enable = 0; - - if(dev == NULL || dev->fifo == NULL || dev->fifo->data == NULL) { - rslt = BMI160_E_NULL_PTR; - } else { - /* Parsing the FIFO data in header-less mode */ - if(dev->fifo->fifo_header_enable == 0) { - /* Number of bytes to be parsed from FIFO */ - get_accel_len_to_parse(&data_index, &data_read_length, accel_length, dev); - for(; data_index < data_read_length;) { - /*Check for the availability of next two bytes of FIFO data */ - check_frame_validity(&data_index, dev); - fifo_data_enable = dev->fifo->fifo_data_enable; - unpack_accel_frame(accel_data, &data_index, &accel_index, fifo_data_enable, dev); - } - - /* update number of accel data read*/ - *accel_length = accel_index; - - /*update the accel byte index*/ - dev->fifo->accel_byte_start_idx = data_index; - } else { - /* Parsing the FIFO data in header mode */ - extract_accel_header_mode(accel_data, accel_length, dev); - } - } - - return rslt; -} - -/*! - * @brief This API parses and extracts the gyro frames from - * FIFO data read by the "bmi160_get_fifo_data" API and stores it in - * the "gyro_data" structure instance. - */ -int8_t bmi160_extract_gyro( - struct bmi160_sensor_data* gyro_data, - uint8_t* gyro_length, - struct bmi160_dev const* dev) { - int8_t rslt = 0; - uint16_t data_index = 0; - uint16_t data_read_length = 0; - uint8_t gyro_index = 0; - uint8_t fifo_data_enable = 0; - - if(dev == NULL || dev->fifo->data == NULL) { - rslt = BMI160_E_NULL_PTR; - } else { - /* Parsing the FIFO data in header-less mode */ - if(dev->fifo->fifo_header_enable == 0) { - /* Number of bytes to be parsed from FIFO */ - get_gyro_len_to_parse(&data_index, &data_read_length, gyro_length, dev); - for(; data_index < data_read_length;) { - /*Check for the availability of next two bytes of FIFO data */ - check_frame_validity(&data_index, dev); - fifo_data_enable = dev->fifo->fifo_data_enable; - unpack_gyro_frame(gyro_data, &data_index, &gyro_index, fifo_data_enable, dev); - } - - /* update number of gyro data read */ - *gyro_length = gyro_index; - - /* update the gyro byte index */ - dev->fifo->gyro_byte_start_idx = data_index; - } else { - /* Parsing the FIFO data in header mode */ - extract_gyro_header_mode(gyro_data, gyro_length, dev); - } - } - - return rslt; -} - -/*! - * @brief This API parses and extracts the aux frames from - * FIFO data read by the "bmi160_get_fifo_data" API and stores it in - * the "aux_data" structure instance. - */ -int8_t bmi160_extract_aux( - struct bmi160_aux_data* aux_data, - uint8_t* aux_len, - struct bmi160_dev const* dev) { - int8_t rslt = 0; - uint16_t data_index = 0; - uint16_t data_read_length = 0; - uint8_t aux_index = 0; - uint8_t fifo_data_enable = 0; - - if((dev == NULL) || (dev->fifo->data == NULL) || (aux_data == NULL)) { - rslt = BMI160_E_NULL_PTR; - } else { - /* Parsing the FIFO data in header-less mode */ - if(dev->fifo->fifo_header_enable == 0) { - /* Number of bytes to be parsed from FIFO */ - get_aux_len_to_parse(&data_index, &data_read_length, aux_len, dev); - for(; data_index < data_read_length;) { - /* Check for the availability of next two - * bytes of FIFO data */ - check_frame_validity(&data_index, dev); - fifo_data_enable = dev->fifo->fifo_data_enable; - unpack_aux_frame(aux_data, &data_index, &aux_index, fifo_data_enable, dev); - } - - /* update number of aux data read */ - *aux_len = aux_index; - - /* update the aux byte index */ - dev->fifo->aux_byte_start_idx = data_index; - } else { - /* Parsing the FIFO data in header mode */ - extract_aux_header_mode(aux_data, aux_len, dev); - } - } - - return rslt; -} - -/*! - * @brief This API starts the FOC of accel and gyro - * - * @note FOC should not be used in low-power mode of sensor - * - * @note Accel FOC targets values of +1g , 0g , -1g - * Gyro FOC always targets value of 0 dps - */ -int8_t bmi160_start_foc( - const struct bmi160_foc_conf* foc_conf, - struct bmi160_offsets* offset, - struct bmi160_dev const* dev) { - int8_t rslt; - uint8_t data; - - /* Null-pointer check */ - rslt = null_ptr_check(dev); - if(rslt != BMI160_OK) { - rslt = BMI160_E_NULL_PTR; - } else { - /* Set the offset enable bits */ - rslt = configure_offset_enable(foc_conf, dev); - if(rslt == BMI160_OK) { - /* Read the FOC config from the sensor */ - rslt = bmi160_get_regs(BMI160_FOC_CONF_ADDR, &data, 1, dev); - - /* Set the FOC config for gyro */ - data = BMI160_SET_BITS(data, BMI160_GYRO_FOC_EN, foc_conf->foc_gyr_en); - - /* Set the FOC config for accel xyz axes */ - data = BMI160_SET_BITS(data, BMI160_ACCEL_FOC_X_CONF, foc_conf->foc_acc_x); - data = BMI160_SET_BITS(data, BMI160_ACCEL_FOC_Y_CONF, foc_conf->foc_acc_y); - data = BMI160_SET_BITS_POS_0(data, BMI160_ACCEL_FOC_Z_CONF, foc_conf->foc_acc_z); - if(rslt == BMI160_OK) { - /* Set the FOC config in the sensor */ - rslt = bmi160_set_regs(BMI160_FOC_CONF_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - /* Procedure to trigger - * FOC and check status */ - rslt = trigger_foc(offset, dev); - } - } - } - } - - return rslt; -} - -/*! - * @brief This API reads and stores the offset values of accel and gyro - */ -int8_t bmi160_get_offsets(struct bmi160_offsets* offset, const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data[7]; - uint8_t lsb, msb; - int16_t offset_msb, offset_lsb; - int16_t offset_data; - - /* Null-pointer check */ - rslt = null_ptr_check(dev); - if(rslt != BMI160_OK) { - rslt = BMI160_E_NULL_PTR; - } else { - /* Read the FOC config from the sensor */ - rslt = bmi160_get_regs(BMI160_OFFSET_ADDR, data, 7, dev); - - /* Accel offsets */ - offset->off_acc_x = (int8_t)data[0]; - offset->off_acc_y = (int8_t)data[1]; - offset->off_acc_z = (int8_t)data[2]; - - /* Gyro x-axis offset */ - lsb = data[3]; - msb = BMI160_GET_BITS_POS_0(data[6], BMI160_GYRO_OFFSET_X); - offset_msb = (int16_t)(msb << 14); - offset_lsb = lsb << 6; - offset_data = offset_msb | offset_lsb; - - /* Divide by 64 to get the Right shift by 6 value */ - offset->off_gyro_x = (int16_t)(offset_data / 64); - - /* Gyro y-axis offset */ - lsb = data[4]; - msb = BMI160_GET_BITS(data[6], BMI160_GYRO_OFFSET_Y); - offset_msb = (int16_t)(msb << 14); - offset_lsb = lsb << 6; - offset_data = offset_msb | offset_lsb; - - /* Divide by 64 to get the Right shift by 6 value */ - offset->off_gyro_y = (int16_t)(offset_data / 64); - - /* Gyro z-axis offset */ - lsb = data[5]; - msb = BMI160_GET_BITS(data[6], BMI160_GYRO_OFFSET_Z); - offset_msb = (int16_t)(msb << 14); - offset_lsb = lsb << 6; - offset_data = offset_msb | offset_lsb; - - /* Divide by 64 to get the Right shift by 6 value */ - offset->off_gyro_z = (int16_t)(offset_data / 64); - } - - return rslt; -} - -/*! - * @brief This API writes the offset values of accel and gyro to - * the sensor but these values will be reset on POR or soft reset. - */ -int8_t bmi160_set_offsets( - const struct bmi160_foc_conf* foc_conf, - const struct bmi160_offsets* offset, - struct bmi160_dev const* dev) { - int8_t rslt; - uint8_t data[7]; - uint8_t x_msb, y_msb, z_msb; - - /* Null-pointer check */ - rslt = null_ptr_check(dev); - if(rslt != BMI160_OK) { - rslt = BMI160_E_NULL_PTR; - } else { - /* Update the accel offset */ - data[0] = (uint8_t)offset->off_acc_x; - data[1] = (uint8_t)offset->off_acc_y; - data[2] = (uint8_t)offset->off_acc_z; - - /* Update the LSB of gyro offset */ - data[3] = BMI160_GET_LSB(offset->off_gyro_x); - data[4] = BMI160_GET_LSB(offset->off_gyro_y); - data[5] = BMI160_GET_LSB(offset->off_gyro_z); - - /* Update the MSB of gyro offset */ - x_msb = BMI160_GET_BITS(offset->off_gyro_x, BMI160_GYRO_OFFSET); - y_msb = BMI160_GET_BITS(offset->off_gyro_y, BMI160_GYRO_OFFSET); - z_msb = BMI160_GET_BITS(offset->off_gyro_z, BMI160_GYRO_OFFSET); - data[6] = (uint8_t)(z_msb << 4 | y_msb << 2 | x_msb); - - /* Set the offset enable/disable for gyro and accel */ - data[6] = BMI160_SET_BITS(data[6], BMI160_GYRO_OFFSET_EN, foc_conf->gyro_off_en); - data[6] = BMI160_SET_BITS(data[6], BMI160_ACCEL_OFFSET_EN, foc_conf->acc_off_en); - - /* Set the offset config and values in the sensor */ - rslt = bmi160_set_regs(BMI160_OFFSET_ADDR, data, 7, dev); - } - - return rslt; -} - -/*! - * @brief This API writes the image registers values to NVM which is - * stored even after POR or soft reset - */ -int8_t bmi160_update_nvm(struct bmi160_dev const* dev) { - int8_t rslt; - uint8_t data; - uint8_t cmd = BMI160_NVM_BACKUP_EN; - - /* Read the nvm_prog_en configuration */ - rslt = bmi160_get_regs(BMI160_CONF_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - data = BMI160_SET_BITS(data, BMI160_NVM_UPDATE, 1); - - /* Set the nvm_prog_en bit in the sensor */ - rslt = bmi160_set_regs(BMI160_CONF_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - /* Update NVM */ - rslt = bmi160_set_regs(BMI160_COMMAND_REG_ADDR, &cmd, 1, dev); - if(rslt == BMI160_OK) { - /* Check for NVM ready status */ - rslt = bmi160_get_regs(BMI160_STATUS_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - data = BMI160_GET_BITS(data, BMI160_NVM_STATUS); - if(data != BMI160_ENABLE) { - /* Delay to update NVM */ - dev->delay_ms(25); - } - } - } - } - } - - return rslt; -} - -/*! - * @brief This API gets the interrupt status from the sensor. - */ -int8_t bmi160_get_int_status( - enum bmi160_int_status_sel int_status_sel, - union bmi160_int_status* int_status, - struct bmi160_dev const* dev) { - int8_t rslt = 0; - - /* To get the status of all interrupts */ - if(int_status_sel == BMI160_INT_STATUS_ALL) { - rslt = bmi160_get_regs(BMI160_INT_STATUS_ADDR, &int_status->data[0], 4, dev); - } else { - if(int_status_sel & BMI160_INT_STATUS_0) { - rslt = bmi160_get_regs(BMI160_INT_STATUS_ADDR, &int_status->data[0], 1, dev); - } - - if(int_status_sel & BMI160_INT_STATUS_1) { - rslt = bmi160_get_regs(BMI160_INT_STATUS_ADDR + 1, &int_status->data[1], 1, dev); - } - - if(int_status_sel & BMI160_INT_STATUS_2) { - rslt = bmi160_get_regs(BMI160_INT_STATUS_ADDR + 2, &int_status->data[2], 1, dev); - } - - if(int_status_sel & BMI160_INT_STATUS_3) { - rslt = bmi160_get_regs(BMI160_INT_STATUS_ADDR + 3, &int_status->data[3], 1, dev); - } - } - - return rslt; -} - -/*********************** Local function definitions ***************************/ - -/*! - * @brief This API sets the any-motion interrupt of the sensor. - * This interrupt occurs when accel values exceeds preset threshold - * for a certain period of time. - */ -static int8_t - set_accel_any_motion_int(struct bmi160_int_settg* int_config, struct bmi160_dev* dev) { - int8_t rslt; - - /* Null-pointer check */ - rslt = null_ptr_check(dev); - if((rslt != BMI160_OK) || (int_config == NULL)) { - rslt = BMI160_E_NULL_PTR; - } else { - /* updating the interrupt structure to local structure */ - struct bmi160_acc_any_mot_int_cfg* any_motion_int_cfg = - &(int_config->int_type_cfg.acc_any_motion_int); - rslt = enable_accel_any_motion_int(any_motion_int_cfg, dev); - if(rslt == BMI160_OK) { - rslt = config_any_motion_int_settg(int_config, any_motion_int_cfg, dev); - } - } - - return rslt; -} - -/*! - * @brief This API sets tap interrupts.Interrupt is fired when - * tap movements happen. - */ -static int8_t - set_accel_tap_int(struct bmi160_int_settg* int_config, const struct bmi160_dev* dev) { - int8_t rslt; - - /* Null-pointer check */ - rslt = null_ptr_check(dev); - if((rslt != BMI160_OK) || (int_config == NULL)) { - rslt = BMI160_E_NULL_PTR; - } else { - /* updating the interrupt structure to local structure */ - struct bmi160_acc_tap_int_cfg* tap_int_cfg = &(int_config->int_type_cfg.acc_tap_int); - rslt = enable_tap_int(int_config, tap_int_cfg, dev); - if(rslt == BMI160_OK) { - /* Configure Interrupt pins */ - rslt = set_intr_pin_config(int_config, dev); - if(rslt == BMI160_OK) { - rslt = config_tap_int_settg(int_config, tap_int_cfg, dev); - } - } - } - - return rslt; -} - -/*! - * @brief This API sets the data ready interrupt for both accel and gyro. - * This interrupt occurs when new accel and gyro data comes. - */ -static int8_t set_accel_gyro_data_ready_int( - const struct bmi160_int_settg* int_config, - const struct bmi160_dev* dev) { - int8_t rslt; - - /* Null-pointer check */ - rslt = null_ptr_check(dev); - if((rslt != BMI160_OK) || (int_config == NULL)) { - rslt = BMI160_E_NULL_PTR; - } else { - rslt = enable_data_ready_int(dev); - if(rslt == BMI160_OK) { - /* Configure Interrupt pins */ - rslt = set_intr_pin_config(int_config, dev); - if(rslt == BMI160_OK) { - rslt = map_hardware_interrupt(int_config, dev); - } - } - } - - return rslt; -} - -/*! - * @brief This API sets the significant motion interrupt of the sensor.This - * interrupt occurs when there is change in user location. - */ -static int8_t - set_accel_sig_motion_int(struct bmi160_int_settg* int_config, struct bmi160_dev* dev) { - int8_t rslt; - - /* Null-pointer check */ - rslt = null_ptr_check(dev); - if((rslt != BMI160_OK) || (int_config == NULL)) { - rslt = BMI160_E_NULL_PTR; - } else { - /* updating the interrupt structure to local structure */ - struct bmi160_acc_sig_mot_int_cfg* sig_mot_int_cfg = - &(int_config->int_type_cfg.acc_sig_motion_int); - rslt = enable_sig_motion_int(sig_mot_int_cfg, dev); - if(rslt == BMI160_OK) { - rslt = config_sig_motion_int_settg(int_config, sig_mot_int_cfg, dev); - } - } - - return rslt; -} - -/*! - * @brief This API sets the no motion/slow motion interrupt of the sensor. - * Slow motion is similar to any motion interrupt.No motion interrupt - * occurs when slope bet. two accel values falls below preset threshold - * for preset duration. - */ -static int8_t - set_accel_no_motion_int(struct bmi160_int_settg* int_config, const struct bmi160_dev* dev) { - int8_t rslt; - - /* Null-pointer check */ - rslt = null_ptr_check(dev); - if((rslt != BMI160_OK) || (int_config == NULL)) { - rslt = BMI160_E_NULL_PTR; - } else { - /* updating the interrupt structure to local structure */ - struct bmi160_acc_no_motion_int_cfg* no_mot_int_cfg = - &(int_config->int_type_cfg.acc_no_motion_int); - rslt = enable_no_motion_int(no_mot_int_cfg, dev); - if(rslt == BMI160_OK) { - /* Configure the INT PIN settings*/ - rslt = config_no_motion_int_settg(int_config, no_mot_int_cfg, dev); - } - } - - return rslt; -} - -/*! - * @brief This API sets the step detection interrupt.This interrupt - * occurs when the single step causes accel values to go above - * preset threshold. - */ -static int8_t - set_accel_step_detect_int(struct bmi160_int_settg* int_config, const struct bmi160_dev* dev) { - int8_t rslt; - - /* Null-pointer check */ - rslt = null_ptr_check(dev); - if((rslt != BMI160_OK) || (int_config == NULL)) { - rslt = BMI160_E_NULL_PTR; - } else { - /* updating the interrupt structure to local structure */ - struct bmi160_acc_step_detect_int_cfg* step_detect_int_cfg = - &(int_config->int_type_cfg.acc_step_detect_int); - rslt = enable_step_detect_int(step_detect_int_cfg, dev); - if(rslt == BMI160_OK) { - /* Configure Interrupt pins */ - rslt = set_intr_pin_config(int_config, dev); - if(rslt == BMI160_OK) { - rslt = map_feature_interrupt(int_config, dev); - if(rslt == BMI160_OK) { - rslt = config_step_detect(step_detect_int_cfg, dev); - } - } - } - } - - return rslt; -} - -/*! - * @brief This API sets the orientation interrupt of the sensor.This - * interrupt occurs when there is orientation change in the sensor - * with respect to gravitational field vector g. - */ -static int8_t - set_accel_orientation_int(struct bmi160_int_settg* int_config, const struct bmi160_dev* dev) { - int8_t rslt; - - /* Null-pointer check */ - rslt = null_ptr_check(dev); - if((rslt != BMI160_OK) || (int_config == NULL)) { - rslt = BMI160_E_NULL_PTR; - } else { - /* updating the interrupt structure to local structure */ - struct bmi160_acc_orient_int_cfg* orient_int_cfg = - &(int_config->int_type_cfg.acc_orient_int); - rslt = enable_orient_int(orient_int_cfg, dev); - if(rslt == BMI160_OK) { - /* Configure Interrupt pins */ - rslt = set_intr_pin_config(int_config, dev); - if(rslt == BMI160_OK) { - /* map INT pin to orient interrupt */ - rslt = map_feature_interrupt(int_config, dev); - if(rslt == BMI160_OK) { - /* configure the - * orientation setting*/ - rslt = config_orient_int_settg(orient_int_cfg, dev); - } - } - } - } - - return rslt; -} - -/*! - * @brief This API sets the flat interrupt of the sensor.This interrupt - * occurs in case of flat orientation - */ -static int8_t - set_accel_flat_detect_int(struct bmi160_int_settg* int_config, const struct bmi160_dev* dev) { - int8_t rslt; - - /* Null-pointer check */ - rslt = null_ptr_check(dev); - if((rslt != BMI160_OK) || (int_config == NULL)) { - rslt = BMI160_E_NULL_PTR; - } else { - /* updating the interrupt structure to local structure */ - struct bmi160_acc_flat_detect_int_cfg* flat_detect_int = - &(int_config->int_type_cfg.acc_flat_int); - - /* enable the flat interrupt */ - rslt = enable_flat_int(flat_detect_int, dev); - if(rslt == BMI160_OK) { - /* Configure Interrupt pins */ - rslt = set_intr_pin_config(int_config, dev); - if(rslt == BMI160_OK) { - /* map INT pin to flat interrupt */ - rslt = map_feature_interrupt(int_config, dev); - if(rslt == BMI160_OK) { - /* configure the flat setting*/ - rslt = config_flat_int_settg(flat_detect_int, dev); - } - } - } - } - - return rslt; -} - -/*! - * @brief This API sets the low-g interrupt of the sensor.This interrupt - * occurs during free-fall. - */ -static int8_t - set_accel_low_g_int(struct bmi160_int_settg* int_config, const struct bmi160_dev* dev) { - int8_t rslt; - - /* Null-pointer check */ - rslt = null_ptr_check(dev); - if((rslt != BMI160_OK) || (int_config == NULL)) { - rslt = BMI160_E_NULL_PTR; - } else { - /* updating the interrupt structure to local structure */ - struct bmi160_acc_low_g_int_cfg* low_g_int = &(int_config->int_type_cfg.acc_low_g_int); - - /* Enable the low-g interrupt*/ - rslt = enable_low_g_int(low_g_int, dev); - if(rslt == BMI160_OK) { - /* Configure Interrupt pins */ - rslt = set_intr_pin_config(int_config, dev); - if(rslt == BMI160_OK) { - /* Map INT pin to low-g interrupt */ - rslt = map_feature_interrupt(int_config, dev); - if(rslt == BMI160_OK) { - /* configure the data source - * for low-g interrupt*/ - rslt = config_low_g_data_src(low_g_int, dev); - if(rslt == BMI160_OK) { - rslt = config_low_g_int_settg(low_g_int, dev); - } - } - } - } - } - - return rslt; -} - -/*! - * @brief This API sets the high-g interrupt of the sensor.The interrupt - * occurs if the absolute value of acceleration data of any enabled axis - * exceeds the programmed threshold and the sign of the value does not - * change for a preset duration. - */ -static int8_t - set_accel_high_g_int(struct bmi160_int_settg* int_config, const struct bmi160_dev* dev) { - int8_t rslt; - - /* Null-pointer check */ - rslt = null_ptr_check(dev); - if((rslt != BMI160_OK) || (int_config == NULL)) { - rslt = BMI160_E_NULL_PTR; - } else { - /* updating the interrupt structure to local structure */ - struct bmi160_acc_high_g_int_cfg* high_g_int_cfg = - &(int_config->int_type_cfg.acc_high_g_int); - - /* Enable the high-g interrupt */ - rslt = enable_high_g_int(high_g_int_cfg, dev); - if(rslt == BMI160_OK) { - /* Configure Interrupt pins */ - rslt = set_intr_pin_config(int_config, dev); - if(rslt == BMI160_OK) { - /* Map INT pin to high-g interrupt */ - rslt = map_feature_interrupt(int_config, dev); - if(rslt == BMI160_OK) { - /* configure the data source - * for high-g interrupt*/ - rslt = config_high_g_data_src(high_g_int_cfg, dev); - if(rslt == BMI160_OK) { - rslt = config_high_g_int_settg(high_g_int_cfg, dev); - } - } - } - } - } - - return rslt; -} - -/*! - * @brief This API configures the pins to fire the - * interrupt signal when it occurs. - */ -static int8_t - set_intr_pin_config(const struct bmi160_int_settg* int_config, const struct bmi160_dev* dev) { - int8_t rslt; - - /* configure the behavioural settings of interrupt pin */ - rslt = config_int_out_ctrl(int_config, dev); - if(rslt == BMI160_OK) { - rslt = config_int_latch(int_config, dev); - } - - return rslt; -} - -/*! - * @brief This internal API is used to validate the device structure pointer for - * null conditions. - */ -static int8_t null_ptr_check(const struct bmi160_dev* dev) { - int8_t rslt; - - if((dev == NULL) || (dev->read == NULL) || (dev->write == NULL) || (dev->delay_ms == NULL)) { - rslt = BMI160_E_NULL_PTR; - } else { - /* Device structure is fine */ - rslt = BMI160_OK; - } - - return rslt; -} - -/*! - * @brief This API sets the default configuration parameters of accel & gyro. - * Also maintain the previous state of configurations. - */ -static void default_param_settg(struct bmi160_dev* dev) { - /* Initializing accel and gyro params with - * default values */ - dev->accel_cfg.bw = BMI160_ACCEL_BW_NORMAL_AVG4; - dev->accel_cfg.odr = BMI160_ACCEL_ODR_100HZ; - dev->accel_cfg.power = BMI160_ACCEL_SUSPEND_MODE; - dev->accel_cfg.range = BMI160_ACCEL_RANGE_2G; - dev->gyro_cfg.bw = BMI160_GYRO_BW_NORMAL_MODE; - dev->gyro_cfg.odr = BMI160_GYRO_ODR_100HZ; - dev->gyro_cfg.power = BMI160_GYRO_SUSPEND_MODE; - dev->gyro_cfg.range = BMI160_GYRO_RANGE_2000_DPS; - - /* To maintain the previous state of accel configuration */ - dev->prev_accel_cfg = dev->accel_cfg; - - /* To maintain the previous state of gyro configuration */ - dev->prev_gyro_cfg = dev->gyro_cfg; -} - -/*! - * @brief This API set the accel configuration. - */ -static int8_t set_accel_conf(struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data[2] = {0}; - - rslt = check_accel_config(data, dev); - if(rslt == BMI160_OK) { - /* Write output data rate and bandwidth */ - rslt = bmi160_set_regs(BMI160_ACCEL_CONFIG_ADDR, &data[0], 1, dev); - if(rslt == BMI160_OK) { - dev->prev_accel_cfg.odr = dev->accel_cfg.odr; - dev->prev_accel_cfg.bw = dev->accel_cfg.bw; - - /* write accel range */ - rslt = bmi160_set_regs(BMI160_ACCEL_RANGE_ADDR, &data[1], 1, dev); - if(rslt == BMI160_OK) { - dev->prev_accel_cfg.range = dev->accel_cfg.range; - } - } - } - - return rslt; -} - -/*! - * @brief This API gets the accel configuration. - */ -static int8_t get_accel_conf(struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data[2] = {0}; - - /* Get accel configurations */ - rslt = bmi160_get_regs(BMI160_ACCEL_CONFIG_ADDR, data, 2, dev); - if(rslt == BMI160_OK) { - dev->accel_cfg.odr = (data[0] & BMI160_ACCEL_ODR_MASK); - dev->accel_cfg.bw = (data[0] & BMI160_ACCEL_BW_MASK) >> BMI160_ACCEL_BW_POS; - dev->accel_cfg.range = (data[1] & BMI160_ACCEL_RANGE_MASK); - } - - return rslt; -} - -/*! - * @brief This API check the accel configuration. - */ -static int8_t check_accel_config(uint8_t* data, const struct bmi160_dev* dev) { - int8_t rslt; - - /* read accel Output data rate and bandwidth */ - rslt = bmi160_get_regs(BMI160_ACCEL_CONFIG_ADDR, data, 2, dev); - if(rslt == BMI160_OK) { - rslt = process_accel_odr(&data[0], dev); - if(rslt == BMI160_OK) { - rslt = process_accel_bw(&data[0], dev); - if(rslt == BMI160_OK) { - rslt = process_accel_range(&data[1], dev); - } - } - } - - return rslt; -} - -/*! - * @brief This API process the accel odr. - */ -static int8_t process_accel_odr(uint8_t* data, const struct bmi160_dev* dev) { - int8_t rslt = 0; - uint8_t temp = 0; - uint8_t odr = 0; - - if(dev->accel_cfg.odr <= BMI160_ACCEL_ODR_1600HZ) { - if(dev->accel_cfg.odr != dev->prev_accel_cfg.odr) { - odr = (uint8_t)dev->accel_cfg.odr; - temp = *data & ~BMI160_ACCEL_ODR_MASK; - - /* Adding output data rate */ - *data = temp | (odr & BMI160_ACCEL_ODR_MASK); - } - } else { - rslt = BMI160_E_OUT_OF_RANGE; - } - - return rslt; -} - -/*! - * @brief This API process the accel bandwidth. - */ -static int8_t process_accel_bw(uint8_t* data, const struct bmi160_dev* dev) { - int8_t rslt = 0; - uint8_t temp = 0; - uint8_t bw = 0; - - if(dev->accel_cfg.bw <= BMI160_ACCEL_BW_RES_AVG128) { - if(dev->accel_cfg.bw != dev->prev_accel_cfg.bw) { - bw = (uint8_t)dev->accel_cfg.bw; - temp = *data & ~BMI160_ACCEL_BW_MASK; - - /* Adding bandwidth */ - *data = temp | ((bw << 4) & BMI160_ACCEL_BW_MASK); - } - } else { - rslt = BMI160_E_OUT_OF_RANGE; - } - - return rslt; -} - -/*! - * @brief This API process the accel range. - */ -static int8_t process_accel_range(uint8_t* data, const struct bmi160_dev* dev) { - int8_t rslt = 0; - uint8_t temp = 0; - uint8_t range = 0; - - if(dev->accel_cfg.range <= BMI160_ACCEL_RANGE_16G) { - if(dev->accel_cfg.range != dev->prev_accel_cfg.range) { - range = (uint8_t)dev->accel_cfg.range; - temp = *data & ~BMI160_ACCEL_RANGE_MASK; - - /* Adding range */ - *data = temp | (range & BMI160_ACCEL_RANGE_MASK); - } - } else { - rslt = BMI160_E_OUT_OF_RANGE; - } - - return rslt; -} - -/*! - * @brief This API checks the invalid settings for ODR & Bw for - * Accel and Gyro. - */ -static int8_t check_invalid_settg(const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data = 0; - - /* read the error reg */ - rslt = bmi160_get_regs(BMI160_ERROR_REG_ADDR, &data, 1, dev); - data = data >> 1; - data = data & BMI160_ERR_REG_MASK; - if(data == 1) { - rslt = BMI160_E_ACCEL_ODR_BW_INVALID; - } else if(data == 2) { - rslt = BMI160_E_GYRO_ODR_BW_INVALID; - } else if(data == 3) { - rslt = BMI160_E_LWP_PRE_FLTR_INT_INVALID; - } else if(data == 7) { - rslt = BMI160_E_LWP_PRE_FLTR_INVALID; - } - - return rslt; -} -static int8_t set_gyro_conf(struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data[2] = {0}; - - rslt = check_gyro_config(data, dev); - if(rslt == BMI160_OK) { - /* Write output data rate and bandwidth */ - rslt = bmi160_set_regs(BMI160_GYRO_CONFIG_ADDR, &data[0], 1, dev); - if(rslt == BMI160_OK) { - dev->prev_gyro_cfg.odr = dev->gyro_cfg.odr; - dev->prev_gyro_cfg.bw = dev->gyro_cfg.bw; - - /* Write gyro range */ - rslt = bmi160_set_regs(BMI160_GYRO_RANGE_ADDR, &data[1], 1, dev); - if(rslt == BMI160_OK) { - dev->prev_gyro_cfg.range = dev->gyro_cfg.range; - } - } - } - - return rslt; -} - -/*! - * @brief This API gets the gyro configuration. - */ -static int8_t get_gyro_conf(struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data[2] = {0}; - - /* Get accel configurations */ - rslt = bmi160_get_regs(BMI160_GYRO_CONFIG_ADDR, data, 2, dev); - if(rslt == BMI160_OK) { - dev->gyro_cfg.odr = (data[0] & BMI160_GYRO_ODR_MASK); - dev->gyro_cfg.bw = (data[0] & BMI160_GYRO_BW_MASK) >> BMI160_GYRO_BW_POS; - dev->gyro_cfg.range = (data[1] & BMI160_GYRO_RANGE_MASK); - } - - return rslt; -} - -/*! - * @brief This API check the gyro configuration. - */ -static int8_t check_gyro_config(uint8_t* data, const struct bmi160_dev* dev) { - int8_t rslt; - - /* read gyro Output data rate and bandwidth */ - rslt = bmi160_get_regs(BMI160_GYRO_CONFIG_ADDR, data, 2, dev); - if(rslt == BMI160_OK) { - rslt = process_gyro_odr(&data[0], dev); - if(rslt == BMI160_OK) { - rslt = process_gyro_bw(&data[0], dev); - if(rslt == BMI160_OK) { - rslt = process_gyro_range(&data[1], dev); - } - } - } - - return rslt; -} - -/*! - * @brief This API process the gyro odr. - */ -static int8_t process_gyro_odr(uint8_t* data, const struct bmi160_dev* dev) { - int8_t rslt = 0; - uint8_t temp = 0; - uint8_t odr = 0; - - if(dev->gyro_cfg.odr <= BMI160_GYRO_ODR_3200HZ) { - if(dev->gyro_cfg.odr != dev->prev_gyro_cfg.odr) { - odr = (uint8_t)dev->gyro_cfg.odr; - temp = (*data & ~BMI160_GYRO_ODR_MASK); - - /* Adding output data rate */ - *data = temp | (odr & BMI160_GYRO_ODR_MASK); - } - } else { - rslt = BMI160_E_OUT_OF_RANGE; - } - - return rslt; -} - -/*! - * @brief This API process the gyro bandwidth. - */ -static int8_t process_gyro_bw(uint8_t* data, const struct bmi160_dev* dev) { - int8_t rslt = 0; - uint8_t temp = 0; - uint8_t bw = 0; - - if(dev->gyro_cfg.bw <= BMI160_GYRO_BW_NORMAL_MODE) { - bw = (uint8_t)dev->gyro_cfg.bw; - temp = *data & ~BMI160_GYRO_BW_MASK; - - /* Adding bandwidth */ - *data = temp | ((bw << 4) & BMI160_GYRO_BW_MASK); - } else { - rslt = BMI160_E_OUT_OF_RANGE; - } - - return rslt; -} - -/*! - * @brief This API process the gyro range. - */ -static int8_t process_gyro_range(uint8_t* data, const struct bmi160_dev* dev) { - int8_t rslt = 0; - uint8_t temp = 0; - uint8_t range = 0; - - if(dev->gyro_cfg.range <= BMI160_GYRO_RANGE_125_DPS) { - if(dev->gyro_cfg.range != dev->prev_gyro_cfg.range) { - range = (uint8_t)dev->gyro_cfg.range; - temp = *data & ~BMI160_GYRO_RANGE_MASK; - - /* Adding range */ - *data = temp | (range & BMI160_GYRO_RANGE_MASK); - } - } else { - rslt = BMI160_E_OUT_OF_RANGE; - } - - return rslt; -} - -/*! - * @brief This API sets the accel power. - */ -static int8_t set_accel_pwr(struct bmi160_dev* dev) { - int8_t rslt = 0; - uint8_t data = 0; - - if((dev->accel_cfg.power >= BMI160_ACCEL_SUSPEND_MODE) && - (dev->accel_cfg.power <= BMI160_ACCEL_LOWPOWER_MODE)) { - if(dev->accel_cfg.power != dev->prev_accel_cfg.power) { - rslt = process_under_sampling(&data, dev); - if(rslt == BMI160_OK) { - /* Write accel power */ - rslt = bmi160_set_regs(BMI160_COMMAND_REG_ADDR, &dev->accel_cfg.power, 1, dev); - - /* Add delay of 3.8 ms - refer data sheet table 24*/ - if(dev->prev_accel_cfg.power == BMI160_ACCEL_SUSPEND_MODE) { - dev->delay_ms(BMI160_ACCEL_DELAY_MS); - } - - dev->prev_accel_cfg.power = dev->accel_cfg.power; - } - } - } else { - rslt = BMI160_E_INVALID_CONFIG; - } - - return rslt; -} - -/*! - * @brief This API process the undersampling setting of Accel. - */ -static int8_t process_under_sampling(uint8_t* data, const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t temp = 0; - uint8_t pre_filter[2] = {0}; - - rslt = bmi160_get_regs(BMI160_ACCEL_CONFIG_ADDR, data, 1, dev); - if(rslt == BMI160_OK) { - if(dev->accel_cfg.power == BMI160_ACCEL_LOWPOWER_MODE) { - temp = *data & ~BMI160_ACCEL_UNDERSAMPLING_MASK; - - /* Set under-sampling parameter */ - *data = temp | ((1 << 7) & BMI160_ACCEL_UNDERSAMPLING_MASK); - - /* Write data */ - rslt = bmi160_set_regs(BMI160_ACCEL_CONFIG_ADDR, data, 1, dev); - - /* Disable the pre-filter data in low power mode */ - if(rslt == BMI160_OK) { - /* Disable the Pre-filter data*/ - rslt = bmi160_set_regs(BMI160_INT_DATA_0_ADDR, pre_filter, 2, dev); - } - } else if(*data & BMI160_ACCEL_UNDERSAMPLING_MASK) { - temp = *data & ~BMI160_ACCEL_UNDERSAMPLING_MASK; - - /* Disable under-sampling parameter if already enabled */ - *data = temp; - - /* Write data */ - rslt = bmi160_set_regs(BMI160_ACCEL_CONFIG_ADDR, data, 1, dev); - } - } - - return rslt; -} - -/*! - * @brief This API sets the gyro power mode. - */ -static int8_t set_gyro_pwr(struct bmi160_dev* dev) { - int8_t rslt = 0; - - if((dev->gyro_cfg.power == BMI160_GYRO_SUSPEND_MODE) || - (dev->gyro_cfg.power == BMI160_GYRO_NORMAL_MODE) || - (dev->gyro_cfg.power == BMI160_GYRO_FASTSTARTUP_MODE)) { - if(dev->gyro_cfg.power != dev->prev_gyro_cfg.power) { - /* Write gyro power */ - rslt = bmi160_set_regs(BMI160_COMMAND_REG_ADDR, &dev->gyro_cfg.power, 1, dev); - if(dev->prev_gyro_cfg.power == BMI160_GYRO_SUSPEND_MODE) { - /* Delay of 80 ms - datasheet Table 24 */ - dev->delay_ms(BMI160_GYRO_DELAY_MS); - } else if( - (dev->prev_gyro_cfg.power == BMI160_GYRO_FASTSTARTUP_MODE) && - (dev->gyro_cfg.power == BMI160_GYRO_NORMAL_MODE)) { - /* This delay is required for transition from - * fast-startup mode to normal mode - datasheet Table 3 */ - dev->delay_ms(10); - } else { - /* do nothing */ - } - - dev->prev_gyro_cfg.power = dev->gyro_cfg.power; - } - } else { - rslt = BMI160_E_INVALID_CONFIG; - } - - return rslt; -} - -/*! - * @brief This API reads accel data along with sensor time if time is requested - * by user. Kindly refer the user guide(README.md) for more info. - */ -static int8_t - get_accel_data(uint8_t len, struct bmi160_sensor_data* accel, const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t idx = 0; - uint8_t data_array[9] = {0}; - uint8_t time_0 = 0; - uint16_t time_1 = 0; - uint32_t time_2 = 0; - uint8_t lsb; - uint8_t msb; - int16_t msblsb; - - /* read accel sensor data along with time if requested */ - rslt = bmi160_get_regs(BMI160_ACCEL_DATA_ADDR, data_array, 6 + len, dev); - if(rslt == BMI160_OK) { - /* Accel Data */ - lsb = data_array[idx++]; - msb = data_array[idx++]; - msblsb = (int16_t)((msb << 8) | lsb); - accel->x = msblsb; /* Data in X axis */ - lsb = data_array[idx++]; - msb = data_array[idx++]; - msblsb = (int16_t)((msb << 8) | lsb); - accel->y = msblsb; /* Data in Y axis */ - lsb = data_array[idx++]; - msb = data_array[idx++]; - msblsb = (int16_t)((msb << 8) | lsb); - accel->z = msblsb; /* Data in Z axis */ - if(len == 3) { - time_0 = data_array[idx++]; - time_1 = (uint16_t)(data_array[idx++] << 8); - time_2 = (uint32_t)(data_array[idx++] << 16); - accel->sensortime = (uint32_t)(time_2 | time_1 | time_0); - } else { - accel->sensortime = 0; - } - } else { - rslt = BMI160_E_COM_FAIL; - } - - return rslt; -} - -/*! - * @brief This API reads accel data along with sensor time if time is requested - * by user. Kindly refer the user guide(README.md) for more info. - */ -static int8_t - get_gyro_data(uint8_t len, struct bmi160_sensor_data* gyro, const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t idx = 0; - uint8_t data_array[15] = {0}; - uint8_t time_0 = 0; - uint16_t time_1 = 0; - uint32_t time_2 = 0; - uint8_t lsb; - uint8_t msb; - int16_t msblsb; - - if(len == 0) { - /* read gyro data only */ - rslt = bmi160_get_regs(BMI160_GYRO_DATA_ADDR, data_array, 6, dev); - if(rslt == BMI160_OK) { - /* Gyro Data */ - lsb = data_array[idx++]; - msb = data_array[idx++]; - msblsb = (int16_t)((msb << 8) | lsb); - gyro->x = msblsb; /* Data in X axis */ - lsb = data_array[idx++]; - msb = data_array[idx++]; - msblsb = (int16_t)((msb << 8) | lsb); - gyro->y = msblsb; /* Data in Y axis */ - lsb = data_array[idx++]; - msb = data_array[idx++]; - msblsb = (int16_t)((msb << 8) | lsb); - gyro->z = msblsb; /* Data in Z axis */ - gyro->sensortime = 0; - } else { - rslt = BMI160_E_COM_FAIL; - } - } else { - /* read gyro sensor data along with time */ - rslt = bmi160_get_regs(BMI160_GYRO_DATA_ADDR, data_array, 12 + len, dev); - if(rslt == BMI160_OK) { - /* Gyro Data */ - lsb = data_array[idx++]; - msb = data_array[idx++]; - msblsb = (int16_t)((msb << 8) | lsb); - gyro->x = msblsb; /* gyro X axis data */ - lsb = data_array[idx++]; - msb = data_array[idx++]; - msblsb = (int16_t)((msb << 8) | lsb); - gyro->y = msblsb; /* gyro Y axis data */ - lsb = data_array[idx++]; - msb = data_array[idx++]; - msblsb = (int16_t)((msb << 8) | lsb); - gyro->z = msblsb; /* gyro Z axis data */ - idx = idx + 6; - time_0 = data_array[idx++]; - time_1 = (uint16_t)(data_array[idx++] << 8); - time_2 = (uint32_t)(data_array[idx++] << 16); - gyro->sensortime = (uint32_t)(time_2 | time_1 | time_0); - } else { - rslt = BMI160_E_COM_FAIL; - } - } - - return rslt; -} - -/*! - * @brief This API reads accel and gyro data along with sensor time - * if time is requested by user. - * Kindly refer the user guide(README.md) for more info. - */ -static int8_t get_accel_gyro_data( - uint8_t len, - struct bmi160_sensor_data* accel, - struct bmi160_sensor_data* gyro, - const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t idx = 0; - uint8_t data_array[15] = {0}; - uint8_t time_0 = 0; - uint16_t time_1 = 0; - uint32_t time_2 = 0; - uint8_t lsb; - uint8_t msb; - int16_t msblsb; - - /* read both accel and gyro sensor data - * along with time if requested */ - rslt = bmi160_get_regs(BMI160_GYRO_DATA_ADDR, data_array, 12 + len, dev); - if(rslt == BMI160_OK) { - /* Gyro Data */ - lsb = data_array[idx++]; - msb = data_array[idx++]; - msblsb = (int16_t)((msb << 8) | lsb); - gyro->x = msblsb; /* gyro X axis data */ - lsb = data_array[idx++]; - msb = data_array[idx++]; - msblsb = (int16_t)((msb << 8) | lsb); - gyro->y = msblsb; /* gyro Y axis data */ - lsb = data_array[idx++]; - msb = data_array[idx++]; - msblsb = (int16_t)((msb << 8) | lsb); - gyro->z = msblsb; /* gyro Z axis data */ - /* Accel Data */ - lsb = data_array[idx++]; - msb = data_array[idx++]; - msblsb = (int16_t)((msb << 8) | lsb); - accel->x = (int16_t)msblsb; /* accel X axis data */ - lsb = data_array[idx++]; - msb = data_array[idx++]; - msblsb = (int16_t)((msb << 8) | lsb); - accel->y = (int16_t)msblsb; /* accel Y axis data */ - lsb = data_array[idx++]; - msb = data_array[idx++]; - msblsb = (int16_t)((msb << 8) | lsb); - accel->z = (int16_t)msblsb; /* accel Z axis data */ - if(len == 3) { - time_0 = data_array[idx++]; - time_1 = (uint16_t)(data_array[idx++] << 8); - time_2 = (uint32_t)(data_array[idx++] << 16); - accel->sensortime = (uint32_t)(time_2 | time_1 | time_0); - gyro->sensortime = (uint32_t)(time_2 | time_1 | time_0); - } else { - accel->sensortime = 0; - gyro->sensortime = 0; - } - } else { - rslt = BMI160_E_COM_FAIL; - } - - return rslt; -} - -/*! - * @brief This API enables the any-motion interrupt for accel. - */ -static int8_t enable_accel_any_motion_int( - const struct bmi160_acc_any_mot_int_cfg* any_motion_int_cfg, - struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data = 0; - uint8_t temp = 0; - - /* Enable any motion x, any motion y, any motion z - * in Int Enable 0 register */ - rslt = bmi160_get_regs(BMI160_INT_ENABLE_0_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - if(any_motion_int_cfg->anymotion_en == BMI160_ENABLE) { - temp = data & ~BMI160_ANY_MOTION_X_INT_EN_MASK; - - /* Adding Any_motion x axis */ - data = temp | (any_motion_int_cfg->anymotion_x & BMI160_ANY_MOTION_X_INT_EN_MASK); - temp = data & ~BMI160_ANY_MOTION_Y_INT_EN_MASK; - - /* Adding Any_motion y axis */ - data = temp | - ((any_motion_int_cfg->anymotion_y << 1) & BMI160_ANY_MOTION_Y_INT_EN_MASK); - temp = data & ~BMI160_ANY_MOTION_Z_INT_EN_MASK; - - /* Adding Any_motion z axis */ - data = temp | - ((any_motion_int_cfg->anymotion_z << 2) & BMI160_ANY_MOTION_Z_INT_EN_MASK); - - /* any-motion feature selected*/ - dev->any_sig_sel = BMI160_ANY_MOTION_ENABLED; - } else { - data = data & ~BMI160_ANY_MOTION_ALL_INT_EN_MASK; - - /* neither any-motion feature nor sig-motion selected */ - dev->any_sig_sel = BMI160_BOTH_ANY_SIG_MOTION_DISABLED; - } - - /* write data to Int Enable 0 register */ - rslt = bmi160_set_regs(BMI160_INT_ENABLE_0_ADDR, &data, 1, dev); - } - - return rslt; -} - -/*! - * @brief This API disable the sig-motion interrupt. - */ -static int8_t disable_sig_motion_int(const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data = 0; - uint8_t temp = 0; - - /* Disabling Significant motion interrupt if enabled */ - rslt = bmi160_get_regs(BMI160_INT_MOTION_3_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - temp = (data & BMI160_SIG_MOTION_SEL_MASK); - if(temp) { - temp = data & ~BMI160_SIG_MOTION_SEL_MASK; - data = temp; - - /* Write data to register */ - rslt = bmi160_set_regs(BMI160_INT_MOTION_3_ADDR, &data, 1, dev); - } - } - - return rslt; -} - -/*! - * @brief This API is used to map/unmap the Any/Sig motion, Step det/Low-g, - * Double tap, Single tap, Orientation, Flat, High-G, Nomotion interrupt pins. - */ -static int8_t - map_feature_interrupt(const struct bmi160_int_settg* int_config, const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data[3] = {0, 0, 0}; - uint8_t temp[3] = {0, 0, 0}; - - rslt = bmi160_get_regs(BMI160_INT_MAP_0_ADDR, data, 3, dev); - if(rslt == BMI160_OK) { - temp[0] = data[0] & ~int_mask_lookup_table[int_config->int_type]; - temp[2] = data[2] & ~int_mask_lookup_table[int_config->int_type]; - switch(int_config->int_channel) { - case BMI160_INT_CHANNEL_NONE: - data[0] = temp[0]; - data[2] = temp[2]; - break; - case BMI160_INT_CHANNEL_1: - data[0] = temp[0] | int_mask_lookup_table[int_config->int_type]; - data[2] = temp[2]; - break; - case BMI160_INT_CHANNEL_2: - data[2] = temp[2] | int_mask_lookup_table[int_config->int_type]; - data[0] = temp[0]; - break; - case BMI160_INT_CHANNEL_BOTH: - data[0] = temp[0] | int_mask_lookup_table[int_config->int_type]; - data[2] = temp[2] | int_mask_lookup_table[int_config->int_type]; - break; - default: - rslt = BMI160_E_OUT_OF_RANGE; - } - if(rslt == BMI160_OK) { - rslt = bmi160_set_regs(BMI160_INT_MAP_0_ADDR, data, 3, dev); - } - } - - return rslt; -} - -/*! - * @brief This API is used to map/unmap the Dataready(Accel & Gyro), FIFO full - * and FIFO watermark interrupt. - */ -static int8_t map_hardware_interrupt( - const struct bmi160_int_settg* int_config, - const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data = 0; - uint8_t temp = 0; - - rslt = bmi160_get_regs(BMI160_INT_MAP_1_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - temp = data & ~int_mask_lookup_table[int_config->int_type]; - temp = temp & ~((uint8_t)(int_mask_lookup_table[int_config->int_type] << 4)); - switch(int_config->int_channel) { - case BMI160_INT_CHANNEL_NONE: - data = temp; - break; - case BMI160_INT_CHANNEL_1: - data = temp | (uint8_t)((int_mask_lookup_table[int_config->int_type]) << 4); - break; - case BMI160_INT_CHANNEL_2: - data = temp | int_mask_lookup_table[int_config->int_type]; - break; - case BMI160_INT_CHANNEL_BOTH: - data = temp | int_mask_lookup_table[int_config->int_type]; - data = data | (uint8_t)((int_mask_lookup_table[int_config->int_type]) << 4); - break; - default: - rslt = BMI160_E_OUT_OF_RANGE; - } - if(rslt == BMI160_OK) { - rslt = bmi160_set_regs(BMI160_INT_MAP_1_ADDR, &data, 1, dev); - } - } - - return rslt; -} - -/*! - * @brief This API configure the source of data(filter & pre-filter) - * for any-motion interrupt. - */ -static int8_t config_any_motion_src( - const struct bmi160_acc_any_mot_int_cfg* any_motion_int_cfg, - const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data = 0; - uint8_t temp = 0; - - /* Configure Int data 1 register to add source of interrupt */ - rslt = bmi160_get_regs(BMI160_INT_DATA_1_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - temp = data & ~BMI160_MOTION_SRC_INT_MASK; - data = temp | ((any_motion_int_cfg->anymotion_data_src << 7) & BMI160_MOTION_SRC_INT_MASK); - - /* Write data to DATA 1 address */ - rslt = bmi160_set_regs(BMI160_INT_DATA_1_ADDR, &data, 1, dev); - } - - return rslt; -} - -/*! - * @brief This API configure the duration and threshold of - * any-motion interrupt. - */ -static int8_t config_any_dur_threshold( - const struct bmi160_acc_any_mot_int_cfg* any_motion_int_cfg, - const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data = 0; - uint8_t temp = 0; - uint8_t data_array[2] = {0}; - uint8_t dur; - - /* Configure Int Motion 0 register */ - rslt = bmi160_get_regs(BMI160_INT_MOTION_0_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - /* slope duration */ - dur = (uint8_t)any_motion_int_cfg->anymotion_dur; - temp = data & ~BMI160_SLOPE_INT_DUR_MASK; - data = temp | (dur & BMI160_MOTION_SRC_INT_MASK); - data_array[0] = data; - - /* add slope threshold */ - data_array[1] = any_motion_int_cfg->anymotion_thr; - - /* INT MOTION 0 and INT MOTION 1 address lie consecutively, - * hence writing data to respective registers at one go */ - - /* Writing to Int_motion 0 and - * Int_motion 1 Address simultaneously */ - rslt = bmi160_set_regs(BMI160_INT_MOTION_0_ADDR, data_array, 2, dev); - } - - return rslt; -} - -/*! - * @brief This API configure necessary setting of any-motion interrupt. - */ -static int8_t config_any_motion_int_settg( - const struct bmi160_int_settg* int_config, - const struct bmi160_acc_any_mot_int_cfg* any_motion_int_cfg, - const struct bmi160_dev* dev) { - int8_t rslt; - - /* Configure Interrupt pins */ - rslt = set_intr_pin_config(int_config, dev); - if(rslt == BMI160_OK) { - rslt = disable_sig_motion_int(dev); - if(rslt == BMI160_OK) { - rslt = map_feature_interrupt(int_config, dev); - if(rslt == BMI160_OK) { - rslt = config_any_motion_src(any_motion_int_cfg, dev); - if(rslt == BMI160_OK) { - rslt = config_any_dur_threshold(any_motion_int_cfg, dev); - } - } - } - } - - return rslt; -} - -/*! - * @brief This API enable the data ready interrupt. - */ -static int8_t enable_data_ready_int(const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data = 0; - uint8_t temp = 0; - - /* Enable data ready interrupt in Int Enable 1 register */ - rslt = bmi160_get_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - temp = data & ~BMI160_DATA_RDY_INT_EN_MASK; - data = temp | ((1 << 4) & BMI160_DATA_RDY_INT_EN_MASK); - - /* Writing data to INT ENABLE 1 Address */ - rslt = bmi160_set_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev); - } - - return rslt; -} - -/*! - * @brief This API enables the no motion/slow motion interrupt. - */ -static int8_t enable_no_motion_int( - const struct bmi160_acc_no_motion_int_cfg* no_mot_int_cfg, - const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data = 0; - uint8_t temp = 0; - - /* Enable no motion x, no motion y, no motion z - * in Int Enable 2 register */ - rslt = bmi160_get_regs(BMI160_INT_ENABLE_2_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - if(no_mot_int_cfg->no_motion_x == 1) { - temp = data & ~BMI160_NO_MOTION_X_INT_EN_MASK; - - /* Adding No_motion x axis */ - data = temp | (1 & BMI160_NO_MOTION_X_INT_EN_MASK); - } - - if(no_mot_int_cfg->no_motion_y == 1) { - temp = data & ~BMI160_NO_MOTION_Y_INT_EN_MASK; - - /* Adding No_motion x axis */ - data = temp | ((1 << 1) & BMI160_NO_MOTION_Y_INT_EN_MASK); - } - - if(no_mot_int_cfg->no_motion_z == 1) { - temp = data & ~BMI160_NO_MOTION_Z_INT_EN_MASK; - - /* Adding No_motion x axis */ - data = temp | ((1 << 2) & BMI160_NO_MOTION_Z_INT_EN_MASK); - } - - /* write data to Int Enable 2 register */ - rslt = bmi160_set_regs(BMI160_INT_ENABLE_2_ADDR, &data, 1, dev); - } - - return rslt; -} - -/*! - * @brief This API configure the interrupt PIN setting for - * no motion/slow motion interrupt. - */ -static int8_t config_no_motion_int_settg( - const struct bmi160_int_settg* int_config, - const struct bmi160_acc_no_motion_int_cfg* no_mot_int_cfg, - const struct bmi160_dev* dev) { - int8_t rslt; - - /* Configure Interrupt pins */ - rslt = set_intr_pin_config(int_config, dev); - if(rslt == BMI160_OK) { - rslt = map_feature_interrupt(int_config, dev); - if(rslt == BMI160_OK) { - rslt = config_no_motion_data_src(no_mot_int_cfg, dev); - if(rslt == BMI160_OK) { - rslt = config_no_motion_dur_thr(no_mot_int_cfg, dev); - } - } - } - - return rslt; -} - -/*! - * @brief This API configure the source of interrupt for no motion. - */ -static int8_t config_no_motion_data_src( - const struct bmi160_acc_no_motion_int_cfg* no_mot_int_cfg, - const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data = 0; - uint8_t temp = 0; - - /* Configure Int data 1 register to add source of interrupt */ - rslt = bmi160_get_regs(BMI160_INT_DATA_1_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - temp = data & ~BMI160_MOTION_SRC_INT_MASK; - data = temp | ((no_mot_int_cfg->no_motion_src << 7) & BMI160_MOTION_SRC_INT_MASK); - - /* Write data to DATA 1 address */ - rslt = bmi160_set_regs(BMI160_INT_DATA_1_ADDR, &data, 1, dev); - } - - return rslt; -} - -/*! - * @brief This API configure the duration and threshold of - * no motion/slow motion interrupt along with selection of no/slow motion. - */ -static int8_t config_no_motion_dur_thr( - const struct bmi160_acc_no_motion_int_cfg* no_mot_int_cfg, - const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data = 0; - uint8_t temp = 0; - uint8_t temp_1 = 0; - uint8_t reg_addr; - uint8_t data_array[2] = {0}; - - /* Configuring INT_MOTION register */ - reg_addr = BMI160_INT_MOTION_0_ADDR; - rslt = bmi160_get_regs(reg_addr, &data, 1, dev); - if(rslt == BMI160_OK) { - temp = data & ~BMI160_NO_MOTION_INT_DUR_MASK; - - /* Adding no_motion duration */ - data = temp | ((no_mot_int_cfg->no_motion_dur << 2) & BMI160_NO_MOTION_INT_DUR_MASK); - - /* Write data to NO_MOTION 0 address */ - rslt = bmi160_set_regs(reg_addr, &data, 1, dev); - if(rslt == BMI160_OK) { - reg_addr = BMI160_INT_MOTION_3_ADDR; - rslt = bmi160_get_regs(reg_addr, &data, 1, dev); - if(rslt == BMI160_OK) { - temp = data & ~BMI160_NO_MOTION_SEL_BIT_MASK; - - /* Adding no_motion_sel bit */ - temp_1 = (no_mot_int_cfg->no_motion_sel & BMI160_NO_MOTION_SEL_BIT_MASK); - data = (temp | temp_1); - data_array[1] = data; - - /* Adding no motion threshold */ - data_array[0] = no_mot_int_cfg->no_motion_thres; - reg_addr = BMI160_INT_MOTION_2_ADDR; - - /* writing data to INT_MOTION 2 and INT_MOTION 3 - * address simultaneously */ - rslt = bmi160_set_regs(reg_addr, data_array, 2, dev); - } - } - } - - return rslt; -} - -/*! - * @brief This API enables the sig-motion motion interrupt. - */ -static int8_t enable_sig_motion_int( - const struct bmi160_acc_sig_mot_int_cfg* sig_mot_int_cfg, - struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data = 0; - uint8_t temp = 0; - - /* For significant motion,enable any motion x,any motion y, - * any motion z in Int Enable 0 register */ - rslt = bmi160_get_regs(BMI160_INT_ENABLE_0_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - if(sig_mot_int_cfg->sig_en == BMI160_ENABLE) { - temp = data & ~BMI160_SIG_MOTION_INT_EN_MASK; - data = temp | (7 & BMI160_SIG_MOTION_INT_EN_MASK); - - /* sig-motion feature selected*/ - dev->any_sig_sel = BMI160_SIG_MOTION_ENABLED; - } else { - data = data & ~BMI160_SIG_MOTION_INT_EN_MASK; - - /* neither any-motion feature nor sig-motion selected */ - dev->any_sig_sel = BMI160_BOTH_ANY_SIG_MOTION_DISABLED; - } - - /* write data to Int Enable 0 register */ - rslt = bmi160_set_regs(BMI160_INT_ENABLE_0_ADDR, &data, 1, dev); - } - - return rslt; -} - -/*! - * @brief This API configure the interrupt PIN setting for - * significant motion interrupt. - */ -static int8_t config_sig_motion_int_settg( - const struct bmi160_int_settg* int_config, - const struct bmi160_acc_sig_mot_int_cfg* sig_mot_int_cfg, - const struct bmi160_dev* dev) { - int8_t rslt; - - /* Configure Interrupt pins */ - rslt = set_intr_pin_config(int_config, dev); - if(rslt == BMI160_OK) { - rslt = map_feature_interrupt(int_config, dev); - if(rslt == BMI160_OK) { - rslt = config_sig_motion_data_src(sig_mot_int_cfg, dev); - if(rslt == BMI160_OK) { - rslt = config_sig_dur_threshold(sig_mot_int_cfg, dev); - } - } - } - - return rslt; -} - -/*! - * @brief This API configure the source of data(filter & pre-filter) - * for sig motion interrupt. - */ -static int8_t config_sig_motion_data_src( - const struct bmi160_acc_sig_mot_int_cfg* sig_mot_int_cfg, - const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data = 0; - uint8_t temp = 0; - - /* Configure Int data 1 register to add source of interrupt */ - rslt = bmi160_get_regs(BMI160_INT_DATA_1_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - temp = data & ~BMI160_MOTION_SRC_INT_MASK; - data = temp | ((sig_mot_int_cfg->sig_data_src << 7) & BMI160_MOTION_SRC_INT_MASK); - - /* Write data to DATA 1 address */ - rslt = bmi160_set_regs(BMI160_INT_DATA_1_ADDR, &data, 1, dev); - } - - return rslt; -} - -/*! - * @brief This API configure the threshold, skip and proof time of - * sig motion interrupt. - */ -static int8_t config_sig_dur_threshold( - const struct bmi160_acc_sig_mot_int_cfg* sig_mot_int_cfg, - const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data; - uint8_t temp = 0; - - /* Configuring INT_MOTION registers */ - - /* Write significant motion threshold. - * This threshold is same as any motion threshold */ - data = sig_mot_int_cfg->sig_mot_thres; - - /* Write data to INT_MOTION 1 address */ - rslt = bmi160_set_regs(BMI160_INT_MOTION_1_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - rslt = bmi160_get_regs(BMI160_INT_MOTION_3_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - temp = data & ~BMI160_SIG_MOTION_SKIP_MASK; - - /* adding skip time of sig_motion interrupt*/ - data = temp | ((sig_mot_int_cfg->sig_mot_skip << 2) & BMI160_SIG_MOTION_SKIP_MASK); - temp = data & ~BMI160_SIG_MOTION_PROOF_MASK; - - /* adding proof time of sig_motion interrupt */ - data = temp | ((sig_mot_int_cfg->sig_mot_proof << 4) & BMI160_SIG_MOTION_PROOF_MASK); - - /* configure the int_sig_mot_sel bit to select - * significant motion interrupt */ - temp = data & ~BMI160_SIG_MOTION_SEL_MASK; - data = temp | ((sig_mot_int_cfg->sig_en << 1) & BMI160_SIG_MOTION_SEL_MASK); - rslt = bmi160_set_regs(BMI160_INT_MOTION_3_ADDR, &data, 1, dev); - } - } - - return rslt; -} - -/*! - * @brief This API enables the step detector interrupt. - */ -static int8_t enable_step_detect_int( - const struct bmi160_acc_step_detect_int_cfg* step_detect_int_cfg, - const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data = 0; - uint8_t temp = 0; - - /* Enable data ready interrupt in Int Enable 2 register */ - rslt = bmi160_get_regs(BMI160_INT_ENABLE_2_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - temp = data & ~BMI160_STEP_DETECT_INT_EN_MASK; - data = temp | - ((step_detect_int_cfg->step_detector_en << 3) & BMI160_STEP_DETECT_INT_EN_MASK); - - /* Writing data to INT ENABLE 2 Address */ - rslt = bmi160_set_regs(BMI160_INT_ENABLE_2_ADDR, &data, 1, dev); - } - - return rslt; -} - -/*! - * @brief This API configure the step detector parameter. - */ -static int8_t config_step_detect( - const struct bmi160_acc_step_detect_int_cfg* step_detect_int_cfg, - const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t temp = 0; - uint8_t data_array[2] = {0}; - - if(step_detect_int_cfg->step_detector_mode == BMI160_STEP_DETECT_NORMAL) { - /* Normal mode setting */ - data_array[0] = 0x15; - data_array[1] = 0x03; - } else if(step_detect_int_cfg->step_detector_mode == BMI160_STEP_DETECT_SENSITIVE) { - /* Sensitive mode setting */ - data_array[0] = 0x2D; - data_array[1] = 0x00; - } else if(step_detect_int_cfg->step_detector_mode == BMI160_STEP_DETECT_ROBUST) { - /* Robust mode setting */ - data_array[0] = 0x1D; - data_array[1] = 0x07; - } else if(step_detect_int_cfg->step_detector_mode == BMI160_STEP_DETECT_USER_DEFINE) { - /* Non recommended User defined setting */ - /* Configuring STEP_CONFIG register */ - rslt = bmi160_get_regs(BMI160_INT_STEP_CONFIG_0_ADDR, &data_array[0], 2, dev); - if(rslt == BMI160_OK) { - temp = data_array[0] & ~BMI160_STEP_DETECT_MIN_THRES_MASK; - - /* Adding min_threshold */ - data_array[0] = temp | ((step_detect_int_cfg->min_threshold << 3) & - BMI160_STEP_DETECT_MIN_THRES_MASK); - temp = data_array[0] & ~BMI160_STEP_DETECT_STEPTIME_MIN_MASK; - - /* Adding steptime_min */ - data_array[0] = temp | ((step_detect_int_cfg->steptime_min) & - BMI160_STEP_DETECT_STEPTIME_MIN_MASK); - temp = data_array[1] & ~BMI160_STEP_MIN_BUF_MASK; - - /* Adding steptime_min */ - data_array[1] = temp | - ((step_detect_int_cfg->step_min_buf) & BMI160_STEP_MIN_BUF_MASK); - } - } - - /* Write data to STEP_CONFIG register */ - rslt = bmi160_set_regs(BMI160_INT_STEP_CONFIG_0_ADDR, data_array, 2, dev); - - return rslt; -} - -/*! - * @brief This API enables the single/double tap interrupt. - */ -static int8_t enable_tap_int( - const struct bmi160_int_settg* int_config, - const struct bmi160_acc_tap_int_cfg* tap_int_cfg, - const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data = 0; - uint8_t temp = 0; - - /* Enable single tap or double tap interrupt in Int Enable 0 register */ - rslt = bmi160_get_regs(BMI160_INT_ENABLE_0_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - if(int_config->int_type == BMI160_ACC_SINGLE_TAP_INT) { - temp = data & ~BMI160_SINGLE_TAP_INT_EN_MASK; - data = temp | ((tap_int_cfg->tap_en << 5) & BMI160_SINGLE_TAP_INT_EN_MASK); - } else { - temp = data & ~BMI160_DOUBLE_TAP_INT_EN_MASK; - data = temp | ((tap_int_cfg->tap_en << 4) & BMI160_DOUBLE_TAP_INT_EN_MASK); - } - - /* Write to Enable 0 Address */ - rslt = bmi160_set_regs(BMI160_INT_ENABLE_0_ADDR, &data, 1, dev); - } - - return rslt; -} - -/*! - * @brief This API configure the interrupt PIN setting for - * tap interrupt. - */ -static int8_t config_tap_int_settg( - const struct bmi160_int_settg* int_config, - const struct bmi160_acc_tap_int_cfg* tap_int_cfg, - const struct bmi160_dev* dev) { - int8_t rslt; - - /* Configure Interrupt pins */ - rslt = set_intr_pin_config(int_config, dev); - if(rslt == BMI160_OK) { - rslt = map_feature_interrupt(int_config, dev); - if(rslt == BMI160_OK) { - rslt = config_tap_data_src(tap_int_cfg, dev); - if(rslt == BMI160_OK) { - rslt = config_tap_param(int_config, tap_int_cfg, dev); - } - } - } - - return rslt; -} - -/*! - * @brief This API configure the source of data(filter & pre-filter) - * for tap interrupt. - */ -static int8_t config_tap_data_src( - const struct bmi160_acc_tap_int_cfg* tap_int_cfg, - const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data = 0; - uint8_t temp = 0; - - /* Configure Int data 0 register to add source of interrupt */ - rslt = bmi160_get_regs(BMI160_INT_DATA_0_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - temp = data & ~BMI160_TAP_SRC_INT_MASK; - data = temp | ((tap_int_cfg->tap_data_src << 3) & BMI160_TAP_SRC_INT_MASK); - - /* Write data to Data 0 address */ - rslt = bmi160_set_regs(BMI160_INT_DATA_0_ADDR, &data, 1, dev); - } - - return rslt; -} - -/*! - * @brief This API configure the parameters of tap interrupt. - * Threshold, quite, shock, and duration. - */ -static int8_t config_tap_param( - const struct bmi160_int_settg* int_config, - const struct bmi160_acc_tap_int_cfg* tap_int_cfg, - const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t temp = 0; - uint8_t data = 0; - uint8_t data_array[2] = {0}; - uint8_t count = 0; - uint8_t dur, shock, quiet, thres; - - /* Configure tap 0 register for tap shock,tap quiet duration - * in case of single tap interrupt */ - rslt = bmi160_get_regs(BMI160_INT_TAP_0_ADDR, data_array, 2, dev); - if(rslt == BMI160_OK) { - data = data_array[count]; - if(int_config->int_type == BMI160_ACC_DOUBLE_TAP_INT) { - dur = (uint8_t)tap_int_cfg->tap_dur; - temp = (data & ~BMI160_TAP_DUR_MASK); - - /* Add tap duration data in case of - * double tap interrupt */ - data = temp | (dur & BMI160_TAP_DUR_MASK); - } - - shock = (uint8_t)tap_int_cfg->tap_shock; - temp = data & ~BMI160_TAP_SHOCK_DUR_MASK; - data = temp | ((shock << 6) & BMI160_TAP_SHOCK_DUR_MASK); - quiet = (uint8_t)tap_int_cfg->tap_quiet; - temp = data & ~BMI160_TAP_QUIET_DUR_MASK; - data = temp | ((quiet << 7) & BMI160_TAP_QUIET_DUR_MASK); - data_array[count++] = data; - data = data_array[count]; - thres = (uint8_t)tap_int_cfg->tap_thr; - temp = data & ~BMI160_TAP_THRES_MASK; - data = temp | (thres & BMI160_TAP_THRES_MASK); - data_array[count++] = data; - - /* TAP 0 and TAP 1 address lie consecutively, - * hence writing data to respective registers at one go */ - - /* Writing to Tap 0 and Tap 1 Address simultaneously */ - rslt = bmi160_set_regs(BMI160_INT_TAP_0_ADDR, data_array, count, dev); - } - - return rslt; -} - -/*! - * @brief This API configure the secondary interface. - */ -static int8_t config_sec_if(const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t if_conf = 0; - uint8_t cmd = BMI160_AUX_NORMAL_MODE; - - /* set the aux power mode to normal*/ - rslt = bmi160_set_regs(BMI160_COMMAND_REG_ADDR, &cmd, 1, dev); - if(rslt == BMI160_OK) { - /* 0.5ms delay - refer datasheet table 24*/ - dev->delay_ms(1); - rslt = bmi160_get_regs(BMI160_IF_CONF_ADDR, &if_conf, 1, dev); - if_conf |= (uint8_t)(1 << 5); - if(rslt == BMI160_OK) { - /*enable the secondary interface also*/ - rslt = bmi160_set_regs(BMI160_IF_CONF_ADDR, &if_conf, 1, dev); - } - } - - return rslt; -} - -/*! - * @brief This API configure the ODR of the auxiliary sensor. - */ -static int8_t config_aux_odr(const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t aux_odr; - - rslt = bmi160_get_regs(BMI160_AUX_ODR_ADDR, &aux_odr, 1, dev); - if(rslt == BMI160_OK) { - aux_odr = (uint8_t)(dev->aux_cfg.aux_odr); - - /* Set the secondary interface ODR - * i.e polling rate of secondary sensor */ - rslt = bmi160_set_regs(BMI160_AUX_ODR_ADDR, &aux_odr, 1, dev); - dev->delay_ms(BMI160_AUX_COM_DELAY); - } - - return rslt; -} - -/*! - * @brief This API maps the actual burst read length set by user. - */ -static int8_t map_read_len(uint16_t* len, const struct bmi160_dev* dev) { - int8_t rslt = BMI160_OK; - - switch(dev->aux_cfg.aux_rd_burst_len) { - case BMI160_AUX_READ_LEN_0: - *len = 1; - break; - case BMI160_AUX_READ_LEN_1: - *len = 2; - break; - case BMI160_AUX_READ_LEN_2: - *len = 6; - break; - case BMI160_AUX_READ_LEN_3: - *len = 8; - break; - default: - rslt = BMI160_E_INVALID_INPUT; - break; - } - - return rslt; -} - -/*! - * @brief This API configure the settings of auxiliary sensor. - */ -static int8_t config_aux_settg(const struct bmi160_dev* dev) { - int8_t rslt; - - rslt = config_sec_if(dev); - if(rslt == BMI160_OK) { - /* Configures the auxiliary interface settings */ - rslt = bmi160_config_aux_mode(dev); - } - - return rslt; -} - -/*! - * @brief This API extract the read data from auxiliary sensor. - */ -static int8_t extract_aux_read( - uint16_t map_len, - uint8_t reg_addr, - uint8_t* aux_data, - uint16_t len, - const struct bmi160_dev* dev) { - int8_t rslt = BMI160_OK; - uint8_t data[8] = { - 0, - }; - uint8_t read_addr = BMI160_AUX_DATA_ADDR; - uint8_t count = 0; - uint8_t read_count; - uint8_t read_len = (uint8_t)map_len; - - for(; count < len;) { - /* set address to read */ - rslt = bmi160_set_regs(BMI160_AUX_IF_2_ADDR, ®_addr, 1, dev); - dev->delay_ms(BMI160_AUX_COM_DELAY); - if(rslt == BMI160_OK) { - rslt = bmi160_get_regs(read_addr, data, map_len, dev); - if(rslt == BMI160_OK) { - read_count = 0; - - /* if read len is less the burst read len - * mention by user*/ - if(len < map_len) { - read_len = (uint8_t)len; - } else if((len - count) < map_len) { - read_len = (uint8_t)(len - count); - } - - for(; read_count < read_len; read_count++) { - aux_data[count + read_count] = data[read_count]; - } - - reg_addr += (uint8_t)map_len; - count += (uint8_t)map_len; - } else { - rslt = BMI160_E_COM_FAIL; - break; - } - } - } - - return rslt; -} - -/*! - * @brief This API enables the orient interrupt. - */ -static int8_t enable_orient_int( - const struct bmi160_acc_orient_int_cfg* orient_int_cfg, - const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data = 0; - uint8_t temp = 0; - - /* Enable data ready interrupt in Int Enable 0 register */ - rslt = bmi160_get_regs(BMI160_INT_ENABLE_0_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - temp = data & ~BMI160_ORIENT_INT_EN_MASK; - data = temp | ((orient_int_cfg->orient_en << 6) & BMI160_ORIENT_INT_EN_MASK); - - /* write data to Int Enable 0 register */ - rslt = bmi160_set_regs(BMI160_INT_ENABLE_0_ADDR, &data, 1, dev); - } - - return rslt; -} - -/*! - * @brief This API configure the necessary setting of orientation interrupt. - */ -static int8_t config_orient_int_settg( - const struct bmi160_acc_orient_int_cfg* orient_int_cfg, - const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data = 0; - uint8_t temp = 0; - uint8_t data_array[2] = {0, 0}; - - /* Configuring INT_ORIENT registers */ - rslt = bmi160_get_regs(BMI160_INT_ORIENT_0_ADDR, data_array, 2, dev); - if(rslt == BMI160_OK) { - data = data_array[0]; - temp = data & ~BMI160_ORIENT_MODE_MASK; - - /* Adding Orientation mode */ - data = temp | ((orient_int_cfg->orient_mode) & BMI160_ORIENT_MODE_MASK); - temp = data & ~BMI160_ORIENT_BLOCK_MASK; - - /* Adding Orientation blocking */ - data = temp | ((orient_int_cfg->orient_blocking << 2) & BMI160_ORIENT_BLOCK_MASK); - temp = data & ~BMI160_ORIENT_HYST_MASK; - - /* Adding Orientation hysteresis */ - data = temp | ((orient_int_cfg->orient_hyst << 4) & BMI160_ORIENT_HYST_MASK); - data_array[0] = data; - data = data_array[1]; - temp = data & ~BMI160_ORIENT_THETA_MASK; - - /* Adding Orientation threshold */ - data = temp | ((orient_int_cfg->orient_theta) & BMI160_ORIENT_THETA_MASK); - temp = data & ~BMI160_ORIENT_UD_ENABLE; - - /* Adding Orient_ud_en */ - data = temp | ((orient_int_cfg->orient_ud_en << 6) & BMI160_ORIENT_UD_ENABLE); - temp = data & ~BMI160_AXES_EN_MASK; - - /* Adding axes_en */ - data = temp | ((orient_int_cfg->axes_ex << 7) & BMI160_AXES_EN_MASK); - data_array[1] = data; - - /* Writing data to INT_ORIENT 0 and INT_ORIENT 1 - * registers simultaneously */ - rslt = bmi160_set_regs(BMI160_INT_ORIENT_0_ADDR, data_array, 2, dev); - } - - return rslt; -} - -/*! - * @brief This API enables the flat interrupt. - */ -static int8_t enable_flat_int( - const struct bmi160_acc_flat_detect_int_cfg* flat_int, - const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data = 0; - uint8_t temp = 0; - - /* Enable flat interrupt in Int Enable 0 register */ - rslt = bmi160_get_regs(BMI160_INT_ENABLE_0_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - temp = data & ~BMI160_FLAT_INT_EN_MASK; - data = temp | ((flat_int->flat_en << 7) & BMI160_FLAT_INT_EN_MASK); - - /* write data to Int Enable 0 register */ - rslt = bmi160_set_regs(BMI160_INT_ENABLE_0_ADDR, &data, 1, dev); - } - - return rslt; -} - -/*! - * @brief This API configure the necessary setting of flat interrupt. - */ -static int8_t config_flat_int_settg( - const struct bmi160_acc_flat_detect_int_cfg* flat_int, - const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data = 0; - uint8_t temp = 0; - uint8_t data_array[2] = {0, 0}; - - /* Configuring INT_FLAT register */ - rslt = bmi160_get_regs(BMI160_INT_FLAT_0_ADDR, data_array, 2, dev); - if(rslt == BMI160_OK) { - data = data_array[0]; - temp = data & ~BMI160_FLAT_THRES_MASK; - - /* Adding flat theta */ - data = temp | ((flat_int->flat_theta) & BMI160_FLAT_THRES_MASK); - data_array[0] = data; - data = data_array[1]; - temp = data & ~BMI160_FLAT_HOLD_TIME_MASK; - - /* Adding flat hold time */ - data = temp | ((flat_int->flat_hold_time << 4) & BMI160_FLAT_HOLD_TIME_MASK); - temp = data & ~BMI160_FLAT_HYST_MASK; - - /* Adding flat hysteresis */ - data = temp | ((flat_int->flat_hy) & BMI160_FLAT_HYST_MASK); - data_array[1] = data; - - /* Writing data to INT_FLAT 0 and INT_FLAT 1 - * registers simultaneously */ - rslt = bmi160_set_regs(BMI160_INT_FLAT_0_ADDR, data_array, 2, dev); - } - - return rslt; -} - -/*! - * @brief This API enables the Low-g interrupt. - */ -static int8_t enable_low_g_int( - const struct bmi160_acc_low_g_int_cfg* low_g_int, - const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data = 0; - uint8_t temp = 0; - - /* Enable low-g interrupt in Int Enable 1 register */ - rslt = bmi160_get_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - temp = data & ~BMI160_LOW_G_INT_EN_MASK; - data = temp | ((low_g_int->low_en << 3) & BMI160_LOW_G_INT_EN_MASK); - - /* write data to Int Enable 0 register */ - rslt = bmi160_set_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev); - } - - return rslt; -} - -/*! - * @brief This API configure the source of data(filter & pre-filter) - * for low-g interrupt. - */ -static int8_t config_low_g_data_src( - const struct bmi160_acc_low_g_int_cfg* low_g_int, - const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data = 0; - uint8_t temp = 0; - - /* Configure Int data 0 register to add source of interrupt */ - rslt = bmi160_get_regs(BMI160_INT_DATA_0_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - temp = data & ~BMI160_LOW_HIGH_SRC_INT_MASK; - data = temp | ((low_g_int->low_data_src << 7) & BMI160_LOW_HIGH_SRC_INT_MASK); - - /* Write data to Data 0 address */ - rslt = bmi160_set_regs(BMI160_INT_DATA_0_ADDR, &data, 1, dev); - } - - return rslt; -} - -/*! - * @brief This API configure the necessary setting of low-g interrupt. - */ -static int8_t config_low_g_int_settg( - const struct bmi160_acc_low_g_int_cfg* low_g_int, - const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t temp = 0; - uint8_t data_array[3] = {0, 0, 0}; - - /* Configuring INT_LOWHIGH register for low-g interrupt */ - rslt = bmi160_get_regs(BMI160_INT_LOWHIGH_2_ADDR, &data_array[2], 1, dev); - if(rslt == BMI160_OK) { - temp = data_array[2] & ~BMI160_LOW_G_HYST_MASK; - - /* Adding low-g hysteresis */ - data_array[2] = temp | (low_g_int->low_hyst & BMI160_LOW_G_HYST_MASK); - temp = data_array[2] & ~BMI160_LOW_G_LOW_MODE_MASK; - - /* Adding low-mode */ - data_array[2] = temp | ((low_g_int->low_mode << 2) & BMI160_LOW_G_LOW_MODE_MASK); - - /* Adding low-g threshold */ - data_array[1] = low_g_int->low_thres; - - /* Adding low-g interrupt delay */ - data_array[0] = low_g_int->low_dur; - - /* Writing data to INT_LOWHIGH 0,1,2 registers simultaneously*/ - rslt = bmi160_set_regs(BMI160_INT_LOWHIGH_0_ADDR, data_array, 3, dev); - } - - return rslt; -} - -/*! - * @brief This API enables the high-g interrupt. - */ -static int8_t enable_high_g_int( - const struct bmi160_acc_high_g_int_cfg* high_g_int_cfg, - const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data = 0; - uint8_t temp = 0; - - /* Enable low-g interrupt in Int Enable 1 register */ - rslt = bmi160_get_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - /* Adding high-g X-axis */ - temp = data & ~BMI160_HIGH_G_X_INT_EN_MASK; - data = temp | (high_g_int_cfg->high_g_x & BMI160_HIGH_G_X_INT_EN_MASK); - - /* Adding high-g Y-axis */ - temp = data & ~BMI160_HIGH_G_Y_INT_EN_MASK; - data = temp | ((high_g_int_cfg->high_g_y << 1) & BMI160_HIGH_G_Y_INT_EN_MASK); - - /* Adding high-g Z-axis */ - temp = data & ~BMI160_HIGH_G_Z_INT_EN_MASK; - data = temp | ((high_g_int_cfg->high_g_z << 2) & BMI160_HIGH_G_Z_INT_EN_MASK); - - /* write data to Int Enable 0 register */ - rslt = bmi160_set_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev); - } - - return rslt; -} - -/*! - * @brief This API configure the source of data(filter & pre-filter) - * for high-g interrupt. - */ -static int8_t config_high_g_data_src( - const struct bmi160_acc_high_g_int_cfg* high_g_int_cfg, - const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data = 0; - uint8_t temp = 0; - - /* Configure Int data 0 register to add source of interrupt */ - rslt = bmi160_get_regs(BMI160_INT_DATA_0_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - temp = data & ~BMI160_LOW_HIGH_SRC_INT_MASK; - data = temp | ((high_g_int_cfg->high_data_src << 7) & BMI160_LOW_HIGH_SRC_INT_MASK); - - /* Write data to Data 0 address */ - rslt = bmi160_set_regs(BMI160_INT_DATA_0_ADDR, &data, 1, dev); - } - - return rslt; -} - -/*! - * @brief This API configure the necessary setting of high-g interrupt. - */ -static int8_t config_high_g_int_settg( - const struct bmi160_acc_high_g_int_cfg* high_g_int_cfg, - const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t temp = 0; - uint8_t data_array[3] = {0, 0, 0}; - - rslt = bmi160_get_regs(BMI160_INT_LOWHIGH_2_ADDR, &data_array[0], 1, dev); - if(rslt == BMI160_OK) { - temp = data_array[0] & ~BMI160_HIGH_G_HYST_MASK; - - /* Adding high-g hysteresis */ - data_array[0] = temp | ((high_g_int_cfg->high_hy << 6) & BMI160_HIGH_G_HYST_MASK); - - /* Adding high-g duration */ - data_array[1] = high_g_int_cfg->high_dur; - - /* Adding high-g threshold */ - data_array[2] = high_g_int_cfg->high_thres; - rslt = bmi160_set_regs(BMI160_INT_LOWHIGH_2_ADDR, data_array, 3, dev); - } - - return rslt; -} - -/*! - * @brief This API configure the behavioural setting of interrupt pin. - */ -static int8_t - config_int_out_ctrl(const struct bmi160_int_settg* int_config, const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t temp = 0; - uint8_t data = 0; - - /* Configuration of output interrupt signals on pins INT1 and INT2 are - * done in BMI160_INT_OUT_CTRL_ADDR register*/ - rslt = bmi160_get_regs(BMI160_INT_OUT_CTRL_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - /* updating the interrupt pin structure to local structure */ - const struct bmi160_int_pin_settg* intr_pin_sett = &(int_config->int_pin_settg); - - /* Configuring channel 1 */ - if(int_config->int_channel == BMI160_INT_CHANNEL_1) { - /* Output enable */ - temp = data & ~BMI160_INT1_OUTPUT_EN_MASK; - data = temp | ((intr_pin_sett->output_en << 3) & BMI160_INT1_OUTPUT_EN_MASK); - - /* Output mode */ - temp = data & ~BMI160_INT1_OUTPUT_MODE_MASK; - data = temp | ((intr_pin_sett->output_mode << 2) & BMI160_INT1_OUTPUT_MODE_MASK); - - /* Output type */ - temp = data & ~BMI160_INT1_OUTPUT_TYPE_MASK; - data = temp | ((intr_pin_sett->output_type << 1) & BMI160_INT1_OUTPUT_TYPE_MASK); - - /* edge control */ - temp = data & ~BMI160_INT1_EDGE_CTRL_MASK; - data = temp | ((intr_pin_sett->edge_ctrl) & BMI160_INT1_EDGE_CTRL_MASK); - } else { - /* Configuring channel 2 */ - /* Output enable */ - temp = data & ~BMI160_INT2_OUTPUT_EN_MASK; - data = temp | ((intr_pin_sett->output_en << 7) & BMI160_INT2_OUTPUT_EN_MASK); - - /* Output mode */ - temp = data & ~BMI160_INT2_OUTPUT_MODE_MASK; - data = temp | ((intr_pin_sett->output_mode << 6) & BMI160_INT2_OUTPUT_MODE_MASK); - - /* Output type */ - temp = data & ~BMI160_INT2_OUTPUT_TYPE_MASK; - data = temp | ((intr_pin_sett->output_type << 5) & BMI160_INT2_OUTPUT_TYPE_MASK); - - /* edge control */ - temp = data & ~BMI160_INT2_EDGE_CTRL_MASK; - data = temp | ((intr_pin_sett->edge_ctrl << 4) & BMI160_INT2_EDGE_CTRL_MASK); - } - - rslt = bmi160_set_regs(BMI160_INT_OUT_CTRL_ADDR, &data, 1, dev); - } - - return rslt; -} - -/*! - * @brief This API configure the mode(input enable, latch or non-latch) of interrupt pin. - */ -static int8_t - config_int_latch(const struct bmi160_int_settg* int_config, const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t temp = 0; - uint8_t data = 0; - - /* Configuration of latch on pins INT1 and INT2 are done in - * BMI160_INT_LATCH_ADDR register*/ - rslt = bmi160_get_regs(BMI160_INT_LATCH_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - /* updating the interrupt pin structure to local structure */ - const struct bmi160_int_pin_settg* intr_pin_sett = &(int_config->int_pin_settg); - if(int_config->int_channel == BMI160_INT_CHANNEL_1) { - /* Configuring channel 1 */ - /* Input enable */ - temp = data & ~BMI160_INT1_INPUT_EN_MASK; - data = temp | ((intr_pin_sett->input_en << 4) & BMI160_INT1_INPUT_EN_MASK); - } else { - /* Configuring channel 2 */ - /* Input enable */ - temp = data & ~BMI160_INT2_INPUT_EN_MASK; - data = temp | ((intr_pin_sett->input_en << 5) & BMI160_INT2_INPUT_EN_MASK); - } - - /* In case of latch interrupt,update the latch duration */ - - /* Latching holds the interrupt for the amount of latch - * duration time */ - temp = data & ~BMI160_INT_LATCH_MASK; - data = temp | (intr_pin_sett->latch_dur & BMI160_INT_LATCH_MASK); - - /* OUT_CTRL_INT and LATCH_INT address lie consecutively, - * hence writing data to respective registers at one go */ - rslt = bmi160_set_regs(BMI160_INT_LATCH_ADDR, &data, 1, dev); - } - - return rslt; -} - -/*! - * @brief This API performs the self test for accelerometer of BMI160 - */ -static int8_t perform_accel_self_test(struct bmi160_dev* dev) { - int8_t rslt; - struct bmi160_sensor_data accel_pos, accel_neg; - - /* Enable Gyro self test bit */ - rslt = enable_accel_self_test(dev); - if(rslt == BMI160_OK) { - /* Perform accel self test with positive excitation */ - rslt = accel_self_test_positive_excitation(&accel_pos, dev); - if(rslt == BMI160_OK) { - /* Perform accel self test with negative excitation */ - rslt = accel_self_test_negative_excitation(&accel_neg, dev); - if(rslt == BMI160_OK) { - /* Validate the self test result */ - rslt = validate_accel_self_test(&accel_pos, &accel_neg); - } - } - } - - return rslt; -} - -/*! - * @brief This API enables to perform the accel self test by setting proper - * configurations to facilitate accel self test - */ -static int8_t enable_accel_self_test(struct bmi160_dev* dev) { - int8_t rslt; - uint8_t reg_data; - - /* Set the Accel power mode as normal mode */ - dev->accel_cfg.power = BMI160_ACCEL_NORMAL_MODE; - - /* Set the sensor range configuration as 8G */ - dev->accel_cfg.range = BMI160_ACCEL_RANGE_8G; - rslt = bmi160_set_sens_conf(dev); - if(rslt == BMI160_OK) { - /* Accel configurations are set to facilitate self test - * acc_odr - 1600Hz ; acc_bwp = 2 ; acc_us = 0 */ - reg_data = BMI160_ACCEL_SELF_TEST_CONFIG; - rslt = bmi160_set_regs(BMI160_ACCEL_CONFIG_ADDR, ®_data, 1, dev); - } - - return rslt; -} - -/*! - * @brief This API performs accel self test with positive excitation - */ -static int8_t accel_self_test_positive_excitation( - struct bmi160_sensor_data* accel_pos, - const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t reg_data; - - /* Enable accel self test with positive self-test excitation - * and with amplitude of deflection set as high */ - reg_data = BMI160_ACCEL_SELF_TEST_POSITIVE_EN; - rslt = bmi160_set_regs(BMI160_SELF_TEST_ADDR, ®_data, 1, dev); - if(rslt == BMI160_OK) { - /* Read the data after a delay of 50ms - refer datasheet 2.8.1 accel self test*/ - dev->delay_ms(BMI160_ACCEL_SELF_TEST_DELAY); - rslt = bmi160_get_sensor_data(BMI160_ACCEL_ONLY, accel_pos, NULL, dev); - } - - return rslt; -} - -/*! - * @brief This API performs accel self test with negative excitation - */ -static int8_t accel_self_test_negative_excitation( - struct bmi160_sensor_data* accel_neg, - const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t reg_data; - - /* Enable accel self test with negative self-test excitation - * and with amplitude of deflection set as high */ - reg_data = BMI160_ACCEL_SELF_TEST_NEGATIVE_EN; - rslt = bmi160_set_regs(BMI160_SELF_TEST_ADDR, ®_data, 1, dev); - if(rslt == BMI160_OK) { - /* Read the data after a delay of 50ms */ - dev->delay_ms(BMI160_ACCEL_SELF_TEST_DELAY); - rslt = bmi160_get_sensor_data(BMI160_ACCEL_ONLY, accel_neg, NULL, dev); - } - - return rslt; -} - -/*! - * @brief This API validates the accel self test results - */ -static int8_t validate_accel_self_test( - const struct bmi160_sensor_data* accel_pos, - const struct bmi160_sensor_data* accel_neg) { - int8_t rslt; - - /* Validate the results of self test */ - if(((accel_neg->x - accel_pos->x) > BMI160_ACCEL_SELF_TEST_LIMIT) && - ((accel_neg->y - accel_pos->y) > BMI160_ACCEL_SELF_TEST_LIMIT) && - ((accel_neg->z - accel_pos->z) > BMI160_ACCEL_SELF_TEST_LIMIT)) { - /* Self test pass condition */ - rslt = BMI160_OK; - } else { - rslt = BMI160_W_ACCEl_SELF_TEST_FAIL; - } - - return rslt; -} - -/*! - * @brief This API performs the self test for gyroscope of BMI160 - */ -static int8_t perform_gyro_self_test(const struct bmi160_dev* dev) { - int8_t rslt; - - /* Enable Gyro self test bit */ - rslt = enable_gyro_self_test(dev); - if(rslt == BMI160_OK) { - /* Validate the gyro self test a delay of 50ms */ - dev->delay_ms(50); - - /* Validate the gyro self test results */ - rslt = validate_gyro_self_test(dev); - } - - return rslt; -} - -/*! - * @brief This API enables the self test bit to trigger self test for Gyro - */ -static int8_t enable_gyro_self_test(const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t reg_data; - - /* Enable the Gyro self test bit to trigger the self test */ - rslt = bmi160_get_regs(BMI160_SELF_TEST_ADDR, ®_data, 1, dev); - if(rslt == BMI160_OK) { - reg_data = BMI160_SET_BITS(reg_data, BMI160_GYRO_SELF_TEST, 1); - rslt = bmi160_set_regs(BMI160_SELF_TEST_ADDR, ®_data, 1, dev); - if(rslt == BMI160_OK) { - /* Delay to enable gyro self test */ - dev->delay_ms(15); - } - } - - return rslt; -} - -/*! - * @brief This API validates the self test results of Gyro - */ -static int8_t validate_gyro_self_test(const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t reg_data; - - /* Validate the Gyro self test result */ - rslt = bmi160_get_regs(BMI160_STATUS_ADDR, ®_data, 1, dev); - if(rslt == BMI160_OK) { - reg_data = BMI160_GET_BITS(reg_data, BMI160_GYRO_SELF_TEST_STATUS); - if(reg_data == BMI160_ENABLE) { - /* Gyro self test success case */ - rslt = BMI160_OK; - } else { - rslt = BMI160_W_GYRO_SELF_TEST_FAIL; - } - } - - return rslt; -} - -/*! - * @brief This API sets FIFO full interrupt of the sensor.This interrupt - * occurs when the FIFO is full and the next full data sample would cause - * a FIFO overflow, which may delete the old samples. - */ -static int8_t - set_fifo_full_int(const struct bmi160_int_settg* int_config, const struct bmi160_dev* dev) { - int8_t rslt = BMI160_OK; - - /* Null-pointer check */ - if((dev == NULL) || (dev->delay_ms == NULL)) { - rslt = BMI160_E_NULL_PTR; - } else { - /*enable the fifo full interrupt */ - rslt = enable_fifo_full_int(int_config, dev); - if(rslt == BMI160_OK) { - /* Configure Interrupt pins */ - rslt = set_intr_pin_config(int_config, dev); - if(rslt == BMI160_OK) { - rslt = map_hardware_interrupt(int_config, dev); - } - } - } - - return rslt; -} - -/*! - * @brief This enable the FIFO full interrupt engine. - */ -static int8_t - enable_fifo_full_int(const struct bmi160_int_settg* int_config, const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data = 0; - - rslt = bmi160_get_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - data = BMI160_SET_BITS(data, BMI160_FIFO_FULL_INT, int_config->fifo_full_int_en); - - /* Writing data to INT ENABLE 1 Address */ - rslt = bmi160_set_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev); - } - - return rslt; -} - -/*! - * @brief This API sets FIFO watermark interrupt of the sensor.The FIFO - * watermark interrupt is fired, when the FIFO fill level is above a fifo - * watermark. - */ -static int8_t set_fifo_watermark_int( - const struct bmi160_int_settg* int_config, - const struct bmi160_dev* dev) { - int8_t rslt = BMI160_OK; - - if((dev == NULL) || (dev->delay_ms == NULL)) { - rslt = BMI160_E_NULL_PTR; - } else { - /* Enable fifo-watermark interrupt in Int Enable 1 register */ - rslt = enable_fifo_wtm_int(int_config, dev); - if(rslt == BMI160_OK) { - /* Configure Interrupt pins */ - rslt = set_intr_pin_config(int_config, dev); - if(rslt == BMI160_OK) { - rslt = map_hardware_interrupt(int_config, dev); - } - } - } - - return rslt; -} - -/*! - * @brief This enable the FIFO watermark interrupt engine. - */ -static int8_t - enable_fifo_wtm_int(const struct bmi160_int_settg* int_config, const struct bmi160_dev* dev) { - int8_t rslt; - uint8_t data = 0; - - rslt = bmi160_get_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - data = BMI160_SET_BITS(data, BMI160_FIFO_WTM_INT, int_config->fifo_wtm_int_en); - - /* Writing data to INT ENABLE 1 Address */ - rslt = bmi160_set_regs(BMI160_INT_ENABLE_1_ADDR, &data, 1, dev); - } - - return rslt; -} - -/*! - * @brief This API is used to reset the FIFO related configurations - * in the fifo_frame structure. - */ -static void reset_fifo_data_structure(const struct bmi160_dev* dev) { - /*Prepare for next FIFO read by resetting FIFO's - * internal data structures*/ - dev->fifo->accel_byte_start_idx = 0; - dev->fifo->gyro_byte_start_idx = 0; - dev->fifo->aux_byte_start_idx = 0; - dev->fifo->sensor_time = 0; - dev->fifo->skipped_frame_count = 0; -} - -/*! - * @brief This API is used to read fifo_byte_counter value (i.e) - * current fill-level in Fifo buffer. - */ -static int8_t get_fifo_byte_counter(uint16_t* bytes_to_read, struct bmi160_dev const* dev) { - int8_t rslt = 0; - uint8_t data[2]; - uint8_t addr = BMI160_FIFO_LENGTH_ADDR; - - rslt |= bmi160_get_regs(addr, data, 2, dev); - data[1] = data[1] & BMI160_FIFO_BYTE_COUNTER_MASK; - - /* Available data in FIFO is stored in bytes_to_read*/ - *bytes_to_read = (((uint16_t)data[1] << 8) | ((uint16_t)data[0])); - - return rslt; -} - -/*! - * @brief This API is used to compute the number of bytes of accel FIFO data - * which is to be parsed in header-less mode - */ -static void get_accel_len_to_parse( - uint16_t* data_index, - uint16_t* data_read_length, - const uint8_t* acc_frame_count, - const struct bmi160_dev* dev) { - /* Data start index */ - *data_index = dev->fifo->accel_byte_start_idx; - if(dev->fifo->fifo_data_enable == BMI160_FIFO_A_ENABLE) { - *data_read_length = (*acc_frame_count) * BMI160_FIFO_A_LENGTH; - } else if(dev->fifo->fifo_data_enable == BMI160_FIFO_G_A_ENABLE) { - *data_read_length = (*acc_frame_count) * BMI160_FIFO_GA_LENGTH; - } else if(dev->fifo->fifo_data_enable == BMI160_FIFO_M_A_ENABLE) { - *data_read_length = (*acc_frame_count) * BMI160_FIFO_MA_LENGTH; - } else if(dev->fifo->fifo_data_enable == BMI160_FIFO_M_G_A_ENABLE) { - *data_read_length = (*acc_frame_count) * BMI160_FIFO_MGA_LENGTH; - } else { - /* When accel is not enabled ,there will be no accel data. - * so we update the data index as complete */ - *data_index = dev->fifo->length; - } - - if(*data_read_length > dev->fifo->length) { - /* Handling the case where more data is requested - * than that is available*/ - *data_read_length = dev->fifo->length; - } -} - -/*! - * @brief This API is used to parse the accelerometer data from the - * FIFO data in both header mode and header-less mode. - * It updates the idx value which is used to store the index of - * the current data byte which is parsed. - */ -static void unpack_accel_frame( - struct bmi160_sensor_data* acc, - uint16_t* idx, - uint8_t* acc_idx, - uint8_t frame_info, - const struct bmi160_dev* dev) { - switch(frame_info) { - case BMI160_FIFO_HEAD_A: - case BMI160_FIFO_A_ENABLE: - - /*Partial read, then skip the data*/ - if((*idx + BMI160_FIFO_A_LENGTH) > dev->fifo->length) { - /*Update the data index as complete*/ - *idx = dev->fifo->length; - break; - } - - /*Unpack the data array into the structure instance "acc" */ - unpack_accel_data(&acc[*acc_idx], *idx, dev); - - /*Move the data index*/ - *idx = *idx + BMI160_FIFO_A_LENGTH; - (*acc_idx)++; - break; - case BMI160_FIFO_HEAD_G_A: - case BMI160_FIFO_G_A_ENABLE: - - /*Partial read, then skip the data*/ - if((*idx + BMI160_FIFO_GA_LENGTH) > dev->fifo->length) { - /*Update the data index as complete*/ - *idx = dev->fifo->length; - break; - } - - /*Unpack the data array into structure instance "acc"*/ - unpack_accel_data(&acc[*acc_idx], *idx + BMI160_FIFO_G_LENGTH, dev); - - /*Move the data index*/ - *idx = *idx + BMI160_FIFO_GA_LENGTH; - (*acc_idx)++; - break; - case BMI160_FIFO_HEAD_M_A: - case BMI160_FIFO_M_A_ENABLE: - - /*Partial read, then skip the data*/ - if((*idx + BMI160_FIFO_MA_LENGTH) > dev->fifo->length) { - /*Update the data index as complete*/ - *idx = dev->fifo->length; - break; - } - - /*Unpack the data array into structure instance "acc"*/ - unpack_accel_data(&acc[*acc_idx], *idx + BMI160_FIFO_M_LENGTH, dev); - - /*Move the data index*/ - *idx = *idx + BMI160_FIFO_MA_LENGTH; - (*acc_idx)++; - break; - case BMI160_FIFO_HEAD_M_G_A: - case BMI160_FIFO_M_G_A_ENABLE: - - /*Partial read, then skip the data*/ - if((*idx + BMI160_FIFO_MGA_LENGTH) > dev->fifo->length) { - /*Update the data index as complete*/ - *idx = dev->fifo->length; - break; - } - - /*Unpack the data array into structure instance "acc"*/ - unpack_accel_data(&acc[*acc_idx], *idx + BMI160_FIFO_MG_LENGTH, dev); - - /*Move the data index*/ - *idx = *idx + BMI160_FIFO_MGA_LENGTH; - (*acc_idx)++; - break; - case BMI160_FIFO_HEAD_M: - case BMI160_FIFO_M_ENABLE: - (*idx) = (*idx) + BMI160_FIFO_M_LENGTH; - break; - case BMI160_FIFO_HEAD_G: - case BMI160_FIFO_G_ENABLE: - (*idx) = (*idx) + BMI160_FIFO_G_LENGTH; - break; - case BMI160_FIFO_HEAD_M_G: - case BMI160_FIFO_M_G_ENABLE: - (*idx) = (*idx) + BMI160_FIFO_MG_LENGTH; - break; - default: - break; - } -} - -/*! - * @brief This API is used to parse the accelerometer data from the - * FIFO data and store it in the instance of the structure bmi160_sensor_data. - */ -static void unpack_accel_data( - struct bmi160_sensor_data* accel_data, - uint16_t data_start_index, - const struct bmi160_dev* dev) { - uint16_t data_lsb; - uint16_t data_msb; - - /* Accel raw x data */ - data_lsb = dev->fifo->data[data_start_index++]; - data_msb = dev->fifo->data[data_start_index++]; - accel_data->x = (int16_t)((data_msb << 8) | data_lsb); - - /* Accel raw y data */ - data_lsb = dev->fifo->data[data_start_index++]; - data_msb = dev->fifo->data[data_start_index++]; - accel_data->y = (int16_t)((data_msb << 8) | data_lsb); - - /* Accel raw z data */ - data_lsb = dev->fifo->data[data_start_index++]; - data_msb = dev->fifo->data[data_start_index++]; - accel_data->z = (int16_t)((data_msb << 8) | data_lsb); -} - -/*! - * @brief This API is used to parse the accelerometer data from the - * FIFO data in header mode. - */ -static void extract_accel_header_mode( - struct bmi160_sensor_data* accel_data, - uint8_t* accel_length, - const struct bmi160_dev* dev) { - uint8_t frame_header = 0; - uint16_t data_index; - uint8_t accel_index = 0; - - for(data_index = dev->fifo->accel_byte_start_idx; data_index < dev->fifo->length;) { - /* extracting Frame header */ - frame_header = (dev->fifo->data[data_index] & BMI160_FIFO_TAG_INTR_MASK); - - /*Index is moved to next byte where the data is starting*/ - data_index++; - switch(frame_header) { - /* Accel frame */ - case BMI160_FIFO_HEAD_A: - case BMI160_FIFO_HEAD_M_A: - case BMI160_FIFO_HEAD_G_A: - case BMI160_FIFO_HEAD_M_G_A: - unpack_accel_frame(accel_data, &data_index, &accel_index, frame_header, dev); - break; - case BMI160_FIFO_HEAD_M: - move_next_frame(&data_index, BMI160_FIFO_M_LENGTH, dev); - break; - case BMI160_FIFO_HEAD_G: - move_next_frame(&data_index, BMI160_FIFO_G_LENGTH, dev); - break; - case BMI160_FIFO_HEAD_M_G: - move_next_frame(&data_index, BMI160_FIFO_MG_LENGTH, dev); - break; - - /* Sensor time frame */ - case BMI160_FIFO_HEAD_SENSOR_TIME: - unpack_sensortime_frame(&data_index, dev); - break; - - /* Skip frame */ - case BMI160_FIFO_HEAD_SKIP_FRAME: - unpack_skipped_frame(&data_index, dev); - break; - - /* Input config frame */ - case BMI160_FIFO_HEAD_INPUT_CONFIG: - move_next_frame(&data_index, 1, dev); - break; - case BMI160_FIFO_HEAD_OVER_READ: - - /* Update the data index as complete in case of Over read */ - data_index = dev->fifo->length; - break; - default: - break; - } - if(*accel_length == accel_index) { - /* Number of frames to read completed */ - break; - } - } - - /*Update number of accel data read*/ - *accel_length = accel_index; - - /*Update the accel frame index*/ - dev->fifo->accel_byte_start_idx = data_index; -} - -/*! - * @brief This API computes the number of bytes of gyro FIFO data - * which is to be parsed in header-less mode - */ -static void get_gyro_len_to_parse( - uint16_t* data_index, - uint16_t* data_read_length, - const uint8_t* gyro_frame_count, - const struct bmi160_dev* dev) { - /* Data start index */ - *data_index = dev->fifo->gyro_byte_start_idx; - if(dev->fifo->fifo_data_enable == BMI160_FIFO_G_ENABLE) { - *data_read_length = (*gyro_frame_count) * BMI160_FIFO_G_LENGTH; - } else if(dev->fifo->fifo_data_enable == BMI160_FIFO_G_A_ENABLE) { - *data_read_length = (*gyro_frame_count) * BMI160_FIFO_GA_LENGTH; - } else if(dev->fifo->fifo_data_enable == BMI160_FIFO_M_G_ENABLE) { - *data_read_length = (*gyro_frame_count) * BMI160_FIFO_MG_LENGTH; - } else if(dev->fifo->fifo_data_enable == BMI160_FIFO_M_G_A_ENABLE) { - *data_read_length = (*gyro_frame_count) * BMI160_FIFO_MGA_LENGTH; - } else { - /* When gyro is not enabled ,there will be no gyro data. - * so we update the data index as complete */ - *data_index = dev->fifo->length; - } - - if(*data_read_length > dev->fifo->length) { - /* Handling the case where more data is requested - * than that is available*/ - *data_read_length = dev->fifo->length; - } -} - -/*! - * @brief This API is used to parse the gyroscope's data from the - * FIFO data in both header mode and header-less mode. - * It updates the idx value which is used to store the index of - * the current data byte which is parsed. - */ -static void unpack_gyro_frame( - struct bmi160_sensor_data* gyro, - uint16_t* idx, - uint8_t* gyro_idx, - uint8_t frame_info, - const struct bmi160_dev* dev) { - switch(frame_info) { - case BMI160_FIFO_HEAD_G: - case BMI160_FIFO_G_ENABLE: - - /*Partial read, then skip the data*/ - if((*idx + BMI160_FIFO_G_LENGTH) > dev->fifo->length) { - /*Update the data index as complete*/ - *idx = dev->fifo->length; - break; - } - - /*Unpack the data array into structure instance "gyro"*/ - unpack_gyro_data(&gyro[*gyro_idx], *idx, dev); - - /*Move the data index*/ - (*idx) = (*idx) + BMI160_FIFO_G_LENGTH; - (*gyro_idx)++; - break; - case BMI160_FIFO_HEAD_G_A: - case BMI160_FIFO_G_A_ENABLE: - - /*Partial read, then skip the data*/ - if((*idx + BMI160_FIFO_GA_LENGTH) > dev->fifo->length) { - /*Update the data index as complete*/ - *idx = dev->fifo->length; - break; - } - - /* Unpack the data array into structure instance "gyro" */ - unpack_gyro_data(&gyro[*gyro_idx], *idx, dev); - - /* Move the data index */ - *idx = *idx + BMI160_FIFO_GA_LENGTH; - (*gyro_idx)++; - break; - case BMI160_FIFO_HEAD_M_G_A: - case BMI160_FIFO_M_G_A_ENABLE: - - /*Partial read, then skip the data*/ - if((*idx + BMI160_FIFO_MGA_LENGTH) > dev->fifo->length) { - /*Update the data index as complete*/ - *idx = dev->fifo->length; - break; - } - - /*Unpack the data array into structure instance "gyro"*/ - unpack_gyro_data(&gyro[*gyro_idx], *idx + BMI160_FIFO_M_LENGTH, dev); - - /*Move the data index*/ - *idx = *idx + BMI160_FIFO_MGA_LENGTH; - (*gyro_idx)++; - break; - case BMI160_FIFO_HEAD_M_A: - case BMI160_FIFO_M_A_ENABLE: - - /* Move the data index */ - *idx = *idx + BMI160_FIFO_MA_LENGTH; - break; - case BMI160_FIFO_HEAD_M: - case BMI160_FIFO_M_ENABLE: - (*idx) = (*idx) + BMI160_FIFO_M_LENGTH; - break; - case BMI160_FIFO_HEAD_M_G: - case BMI160_FIFO_M_G_ENABLE: - - /*Partial read, then skip the data*/ - if((*idx + BMI160_FIFO_MG_LENGTH) > dev->fifo->length) { - /*Update the data index as complete*/ - *idx = dev->fifo->length; - break; - } - - /*Unpack the data array into structure instance "gyro"*/ - unpack_gyro_data(&gyro[*gyro_idx], *idx + BMI160_FIFO_M_LENGTH, dev); - - /*Move the data index*/ - (*idx) = (*idx) + BMI160_FIFO_MG_LENGTH; - (*gyro_idx)++; - break; - case BMI160_FIFO_HEAD_A: - case BMI160_FIFO_A_ENABLE: - - /*Move the data index*/ - *idx = *idx + BMI160_FIFO_A_LENGTH; - break; - default: - break; - } -} - -/*! - * @brief This API is used to parse the gyro data from the - * FIFO data and store it in the instance of the structure bmi160_sensor_data. - */ -static void unpack_gyro_data( - struct bmi160_sensor_data* gyro_data, - uint16_t data_start_index, - const struct bmi160_dev* dev) { - uint16_t data_lsb; - uint16_t data_msb; - - /* Gyro raw x data */ - data_lsb = dev->fifo->data[data_start_index++]; - data_msb = dev->fifo->data[data_start_index++]; - gyro_data->x = (int16_t)((data_msb << 8) | data_lsb); - - /* Gyro raw y data */ - data_lsb = dev->fifo->data[data_start_index++]; - data_msb = dev->fifo->data[data_start_index++]; - gyro_data->y = (int16_t)((data_msb << 8) | data_lsb); - - /* Gyro raw z data */ - data_lsb = dev->fifo->data[data_start_index++]; - data_msb = dev->fifo->data[data_start_index++]; - gyro_data->z = (int16_t)((data_msb << 8) | data_lsb); -} - -/*! - * @brief This API is used to parse the gyro data from the - * FIFO data in header mode. - */ -static void extract_gyro_header_mode( - struct bmi160_sensor_data* gyro_data, - uint8_t* gyro_length, - const struct bmi160_dev* dev) { - uint8_t frame_header = 0; - uint16_t data_index; - uint8_t gyro_index = 0; - - for(data_index = dev->fifo->gyro_byte_start_idx; data_index < dev->fifo->length;) { - /* extracting Frame header */ - frame_header = (dev->fifo->data[data_index] & BMI160_FIFO_TAG_INTR_MASK); - - /*Index is moved to next byte where the data is starting*/ - data_index++; - switch(frame_header) { - /* GYRO frame */ - case BMI160_FIFO_HEAD_G: - case BMI160_FIFO_HEAD_G_A: - case BMI160_FIFO_HEAD_M_G: - case BMI160_FIFO_HEAD_M_G_A: - unpack_gyro_frame(gyro_data, &data_index, &gyro_index, frame_header, dev); - break; - case BMI160_FIFO_HEAD_A: - move_next_frame(&data_index, BMI160_FIFO_A_LENGTH, dev); - break; - case BMI160_FIFO_HEAD_M: - move_next_frame(&data_index, BMI160_FIFO_M_LENGTH, dev); - break; - case BMI160_FIFO_HEAD_M_A: - move_next_frame(&data_index, BMI160_FIFO_M_LENGTH, dev); - break; - - /* Sensor time frame */ - case BMI160_FIFO_HEAD_SENSOR_TIME: - unpack_sensortime_frame(&data_index, dev); - break; - - /* Skip frame */ - case BMI160_FIFO_HEAD_SKIP_FRAME: - unpack_skipped_frame(&data_index, dev); - break; - - /* Input config frame */ - case BMI160_FIFO_HEAD_INPUT_CONFIG: - move_next_frame(&data_index, 1, dev); - break; - case BMI160_FIFO_HEAD_OVER_READ: - - /* Update the data index as complete in case of over read */ - data_index = dev->fifo->length; - break; - default: - break; - } - if(*gyro_length == gyro_index) { - /*Number of frames to read completed*/ - break; - } - } - - /*Update number of gyro data read*/ - *gyro_length = gyro_index; - - /*Update the gyro frame index*/ - dev->fifo->gyro_byte_start_idx = data_index; +int8_t bmi160_write_i2c(uint8_t dev_addr, uint8_t reg_addr, uint8_t* data, uint16_t len) { + if(furi_hal_i2c_write_mem(&furi_hal_i2c_handle_external, dev_addr, reg_addr, data, len, 50)) + return BMI160_OK; + return BMI160_E_COM_FAIL; } -/*! - * @brief This API computes the number of bytes of aux FIFO data - * which is to be parsed in header-less mode - */ -static void get_aux_len_to_parse( - uint16_t* data_index, - uint16_t* data_read_length, - const uint8_t* aux_frame_count, - const struct bmi160_dev* dev) { - /* Data start index */ - *data_index = dev->fifo->gyro_byte_start_idx; - if(dev->fifo->fifo_data_enable == BMI160_FIFO_M_ENABLE) { - *data_read_length = (*aux_frame_count) * BMI160_FIFO_M_LENGTH; - } else if(dev->fifo->fifo_data_enable == BMI160_FIFO_M_A_ENABLE) { - *data_read_length = (*aux_frame_count) * BMI160_FIFO_MA_LENGTH; - } else if(dev->fifo->fifo_data_enable == BMI160_FIFO_M_G_ENABLE) { - *data_read_length = (*aux_frame_count) * BMI160_FIFO_MG_LENGTH; - } else if(dev->fifo->fifo_data_enable == BMI160_FIFO_M_G_A_ENABLE) { - *data_read_length = (*aux_frame_count) * BMI160_FIFO_MGA_LENGTH; - } else { - /* When aux is not enabled ,there will be no aux data. - * so we update the data index as complete */ - *data_index = dev->fifo->length; - } - - if(*data_read_length > dev->fifo->length) { - /* Handling the case where more data is requested - * than that is available */ - *data_read_length = dev->fifo->length; - } +int8_t bmi160_read_i2c(uint8_t dev_addr, uint8_t reg_addr, uint8_t* read_data, uint16_t len) { + if(furi_hal_i2c_read_mem(&furi_hal_i2c_handle_external, dev_addr, reg_addr, read_data, len, 50)) + return BMI160_OK; + return BMI160_E_COM_FAIL; } -/*! - * @brief This API is used to parse the aux's data from the - * FIFO data in both header mode and header-less mode. - * It updates the idx value which is used to store the index of - * the current data byte which is parsed - */ -static void unpack_aux_frame( - struct bmi160_aux_data* aux_data, - uint16_t* idx, - uint8_t* aux_index, - uint8_t frame_info, - const struct bmi160_dev* dev) { - switch(frame_info) { - case BMI160_FIFO_HEAD_M: - case BMI160_FIFO_M_ENABLE: - - /* Partial read, then skip the data */ - if((*idx + BMI160_FIFO_M_LENGTH) > dev->fifo->length) { - /* Update the data index as complete */ - *idx = dev->fifo->length; - break; - } - - /* Unpack the data array into structure instance */ - unpack_aux_data(&aux_data[*aux_index], *idx, dev); - - /* Move the data index */ - *idx = *idx + BMI160_FIFO_M_LENGTH; - (*aux_index)++; - break; - case BMI160_FIFO_HEAD_M_A: - case BMI160_FIFO_M_A_ENABLE: - - /* Partial read, then skip the data */ - if((*idx + BMI160_FIFO_MA_LENGTH) > dev->fifo->length) { - /* Update the data index as complete */ - *idx = dev->fifo->length; - break; - } - - /* Unpack the data array into structure instance */ - unpack_aux_data(&aux_data[*aux_index], *idx, dev); - - /* Move the data index */ - *idx = *idx + BMI160_FIFO_MA_LENGTH; - (*aux_index)++; - break; - case BMI160_FIFO_HEAD_M_G: - case BMI160_FIFO_M_G_ENABLE: - - /* Partial read, then skip the data */ - if((*idx + BMI160_FIFO_MG_LENGTH) > dev->fifo->length) { - /* Update the data index as complete */ - *idx = dev->fifo->length; - break; - } +bool bmi160_begin() { + FURI_LOG_I(BMI160_TAG, "Init BMI160"); - /* Unpack the data array into structure instance */ - unpack_aux_data(&aux_data[*aux_index], *idx, dev); - - /* Move the data index */ - (*idx) = (*idx) + BMI160_FIFO_MG_LENGTH; - (*aux_index)++; - break; - case BMI160_FIFO_HEAD_M_G_A: - case BMI160_FIFO_M_G_A_ENABLE: - - /*Partial read, then skip the data*/ - if((*idx + BMI160_FIFO_MGA_LENGTH) > dev->fifo->length) { - /* Update the data index as complete */ - *idx = dev->fifo->length; - break; - } - - /* Unpack the data array into structure instance */ - unpack_aux_data(&aux_data[*aux_index], *idx, dev); - - /*Move the data index*/ - *idx = *idx + BMI160_FIFO_MGA_LENGTH; - (*aux_index)++; - break; - case BMI160_FIFO_HEAD_G: - case BMI160_FIFO_G_ENABLE: - - /* Move the data index */ - (*idx) = (*idx) + BMI160_FIFO_G_LENGTH; - break; - case BMI160_FIFO_HEAD_G_A: - case BMI160_FIFO_G_A_ENABLE: - - /* Move the data index */ - *idx = *idx + BMI160_FIFO_GA_LENGTH; - break; - case BMI160_FIFO_HEAD_A: - case BMI160_FIFO_A_ENABLE: - - /* Move the data index */ - *idx = *idx + BMI160_FIFO_A_LENGTH; - break; - default: - break; + if(!furi_hal_i2c_is_device_ready(&furi_hal_i2c_handle_external, BMI160_DEV_ADDR, 50)) { + FURI_LOG_E(BMI160_TAG, "Device not ready!"); + return false; } -} -/*! - * @brief This API is used to parse the aux data from the - * FIFO data and store it in the instance of the structure bmi160_aux_data. - */ -static void unpack_aux_data( - struct bmi160_aux_data* aux_data, - uint16_t data_start_index, - const struct bmi160_dev* dev) { - /* Aux data bytes */ - aux_data->data[0] = dev->fifo->data[data_start_index++]; - aux_data->data[1] = dev->fifo->data[data_start_index++]; - aux_data->data[2] = dev->fifo->data[data_start_index++]; - aux_data->data[3] = dev->fifo->data[data_start_index++]; - aux_data->data[4] = dev->fifo->data[data_start_index++]; - aux_data->data[5] = dev->fifo->data[data_start_index++]; - aux_data->data[6] = dev->fifo->data[data_start_index++]; - aux_data->data[7] = dev->fifo->data[data_start_index++]; -} - -/*! - * @brief This API is used to parse the aux data from the - * FIFO data in header mode. - */ -static void extract_aux_header_mode( - struct bmi160_aux_data* aux_data, - uint8_t* aux_length, - const struct bmi160_dev* dev) { - uint8_t frame_header = 0; - uint16_t data_index; - uint8_t aux_index = 0; - - for(data_index = dev->fifo->aux_byte_start_idx; data_index < dev->fifo->length;) { - /* extracting Frame header */ - frame_header = (dev->fifo->data[data_index] & BMI160_FIFO_TAG_INTR_MASK); - - /*Index is moved to next byte where the data is starting*/ - data_index++; - switch(frame_header) { - /* Aux frame */ - case BMI160_FIFO_HEAD_M: - case BMI160_FIFO_HEAD_M_A: - case BMI160_FIFO_HEAD_M_G: - case BMI160_FIFO_HEAD_M_G_A: - unpack_aux_frame(aux_data, &data_index, &aux_index, frame_header, dev); - break; - case BMI160_FIFO_HEAD_G: - move_next_frame(&data_index, BMI160_FIFO_G_LENGTH, dev); - break; - case BMI160_FIFO_HEAD_G_A: - move_next_frame(&data_index, BMI160_FIFO_GA_LENGTH, dev); - break; - case BMI160_FIFO_HEAD_A: - move_next_frame(&data_index, BMI160_FIFO_A_LENGTH, dev); - break; + FURI_LOG_I(BMI160_TAG, "Device ready!"); - /* Sensor time frame */ - case BMI160_FIFO_HEAD_SENSOR_TIME: - unpack_sensortime_frame(&data_index, dev); - break; + bmi160dev.id = BMI160_DEV_ADDR; + bmi160dev.intf = BMI160_I2C_INTF; + bmi160dev.read = bmi160_read_i2c; + bmi160dev.write = bmi160_write_i2c; + bmi160dev.delay_ms = furi_delay_ms; - /* Skip frame */ - case BMI160_FIFO_HEAD_SKIP_FRAME: - unpack_skipped_frame(&data_index, dev); - break; - - /* Input config frame */ - case BMI160_FIFO_HEAD_INPUT_CONFIG: - move_next_frame(&data_index, 1, dev); - break; - case BMI160_FIFO_HEAD_OVER_READ: - - /* Update the data index as complete in case - * of over read */ - data_index = dev->fifo->length; - break; - default: - - /* Update the data index as complete in case of - * getting other headers like 0x00 */ - data_index = dev->fifo->length; - break; - } - if(*aux_length == aux_index) { - /*Number of frames to read completed*/ - break; - } + if(bmi160_init(&bmi160dev) != BMI160_OK) { + FURI_LOG_E(BMI160_TAG, "Initialization failure!"); + FURI_LOG_E(BMI160_TAG, "Chip ID 0x%X", bmi160dev.chip_id); + return false; } - /* Update number of aux data read */ - *aux_length = aux_index; - - /* Update the aux frame index */ - dev->fifo->aux_byte_start_idx = data_index; -} - -/*! - * @brief This API checks the presence of non-valid frames in the read fifo data. - */ -static void check_frame_validity(uint16_t* data_index, const struct bmi160_dev* dev) { - if((*data_index + 2) < dev->fifo->length) { - /* Check if FIFO is empty */ - if((dev->fifo->data[*data_index] == FIFO_CONFIG_MSB_CHECK) && - (dev->fifo->data[*data_index + 1] == FIFO_CONFIG_LSB_CHECK)) { - /*Update the data index as complete*/ - *data_index = dev->fifo->length; - } - } -} + bmi160dev.accel_cfg.odr = BMI160_ACCEL_ODR_400HZ; + bmi160dev.accel_cfg.range = BMI160_ACCEL_RANGE_4G; + bmi160dev.accel_cfg.bw = BMI160_ACCEL_BW_NORMAL_AVG4; + bmi160dev.accel_cfg.power = BMI160_ACCEL_NORMAL_MODE; + bmi160dev.gyro_cfg.odr = BMI160_GYRO_ODR_400HZ; + bmi160dev.gyro_cfg.range = BMI160_GYRO_RANGE_2000_DPS; + bmi160dev.gyro_cfg.bw = BMI160_GYRO_BW_NORMAL_MODE; + bmi160dev.gyro_cfg.power = BMI160_GYRO_NORMAL_MODE; -/*! - * @brief This API is used to move the data index ahead of the - * current_frame_length parameter when unnecessary FIFO data appears while - * extracting the user specified data. - */ -static void move_next_frame( - uint16_t* data_index, - uint8_t current_frame_length, - const struct bmi160_dev* dev) { - /*Partial read, then move the data index to last data*/ - if((*data_index + current_frame_length) > dev->fifo->length) { - /*Update the data index as complete*/ - *data_index = dev->fifo->length; - } else { - /*Move the data index to next frame*/ - *data_index = *data_index + current_frame_length; + if(bmi160_set_sens_conf(&bmi160dev) != BMI160_OK) { + FURI_LOG_E(BMI160_TAG, "Initialization failure!"); + FURI_LOG_E(BMI160_TAG, "Chip ID 0x%X", bmi160dev.chip_id); + return false; } -} - -/*! - * @brief This API is used to parse and store the sensor time from the - * FIFO data in the structure instance dev. - */ -static void unpack_sensortime_frame(uint16_t* data_index, const struct bmi160_dev* dev) { - uint32_t sensor_time_byte3 = 0; - uint16_t sensor_time_byte2 = 0; - uint8_t sensor_time_byte1 = 0; - /*Partial read, then move the data index to last data*/ - if((*data_index + BMI160_SENSOR_TIME_LENGTH) > dev->fifo->length) { - /*Update the data index as complete*/ - *data_index = dev->fifo->length; - } else { - sensor_time_byte3 = dev->fifo->data[(*data_index) + BMI160_SENSOR_TIME_MSB_BYTE] << 16; - sensor_time_byte2 = dev->fifo->data[(*data_index) + BMI160_SENSOR_TIME_XLSB_BYTE] << 8; - sensor_time_byte1 = dev->fifo->data[(*data_index)]; + FURI_LOG_I(BMI160_TAG, "Initialization success!"); + FURI_LOG_I(BMI160_TAG, "Chip ID 0x%X", bmi160dev.chip_id); - /* Sensor time */ - dev->fifo->sensor_time = - (uint32_t)(sensor_time_byte3 | sensor_time_byte2 | sensor_time_byte1); - *data_index = (*data_index) + BMI160_SENSOR_TIME_LENGTH; - } + return true; } -/*! - * @brief This API is used to parse and store the skipped_frame_count from - * the FIFO data in the structure instance dev. - */ -static void unpack_skipped_frame(uint16_t* data_index, const struct bmi160_dev* dev) { - /*Partial read, then move the data index to last data*/ - if(*data_index >= dev->fifo->length) { - /*Update the data index as complete*/ - *data_index = dev->fifo->length; - } else { - dev->fifo->skipped_frame_count = dev->fifo->data[*data_index]; - - /*Move the data index*/ - *data_index = (*data_index) + 1; +int bmi160_read(double* vec) { + if(bmi160_get_sensor_data( + (BMI160_ACCEL_SEL | BMI160_GYRO_SEL), &bmi160_accel, &bmi160_gyro, &bmi160dev) != + BMI160_OK) { + return 0; } -} - -/*! - * @brief This API is used to get the FOC status from the sensor - */ -static int8_t get_foc_status(uint8_t* foc_status, struct bmi160_dev const* dev) { - int8_t rslt; - uint8_t data; - /* Read the FOC status from sensor */ - rslt = bmi160_get_regs(BMI160_STATUS_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - /* Get the foc_status bit */ - *foc_status = BMI160_GET_BITS(data, BMI160_FOC_STATUS); - } + vec[0] = ((double)bmi160_accel.x * 4 / 32768) * GRAVITY; + vec[1] = ((double)bmi160_accel.y * 4 / 32768) * GRAVITY; + vec[2] = ((double)bmi160_accel.z * 4 / 32768) * GRAVITY; + vec[3] = ((double)bmi160_gyro.x * 2000 / 32768) * DEG_TO_RAD; + vec[4] = ((double)bmi160_gyro.y * 2000 / 32768) * DEG_TO_RAD; + vec[5] = ((double)bmi160_gyro.z * 2000 / 32768) * DEG_TO_RAD; - return rslt; + return ACC_DATA_READY | GYR_DATA_READY; } -/*! - * @brief This API is used to configure the offset enable bits in the sensor - */ -static int8_t - configure_offset_enable(const struct bmi160_foc_conf* foc_conf, struct bmi160_dev const* dev) { - int8_t rslt; - uint8_t data; - - /* Null-pointer check */ - rslt = null_ptr_check(dev); - if(rslt != BMI160_OK) { - rslt = BMI160_E_NULL_PTR; - } else { - /* Read the FOC config from the sensor */ - rslt = bmi160_get_regs(BMI160_OFFSET_CONF_ADDR, &data, 1, dev); - if(rslt == BMI160_OK) { - /* Set the offset enable/disable for gyro */ - data = BMI160_SET_BITS(data, BMI160_GYRO_OFFSET_EN, foc_conf->gyro_off_en); - - /* Set the offset enable/disable for accel */ - data = BMI160_SET_BITS(data, BMI160_ACCEL_OFFSET_EN, foc_conf->acc_off_en); - - /* Set the offset config in the sensor */ - rslt = bmi160_set_regs(BMI160_OFFSET_CONF_ADDR, &data, 1, dev); - } - } - - return rslt; +void bmi160_end() { } -static int8_t trigger_foc(struct bmi160_offsets* offset, struct bmi160_dev const* dev) { - int8_t rslt; - uint8_t foc_status = BMI160_ENABLE; - uint8_t cmd = BMI160_START_FOC_CMD; - uint8_t timeout = 0; - uint8_t data_array[20]; - - /* Start the FOC process */ - rslt = bmi160_set_regs(BMI160_COMMAND_REG_ADDR, &cmd, 1, dev); - if(rslt == BMI160_OK) { - /* Check the FOC status*/ - rslt = get_foc_status(&foc_status, dev); - - if((rslt != BMI160_OK) || (foc_status != BMI160_ENABLE)) { - while((foc_status != BMI160_ENABLE) && (timeout < 11)) { - /* Maximum time of 250ms is given in 10 - * steps of 25ms each - 250ms refer datasheet 2.9.1 */ - dev->delay_ms(25); - - /* Check the FOC status*/ - rslt = get_foc_status(&foc_status, dev); - timeout++; - } - - if((rslt == BMI160_OK) && (foc_status == BMI160_ENABLE)) { - /* Get offset values from sensor */ - rslt = bmi160_get_offsets(offset, dev); - } else { - /* FOC failure case */ - rslt = BMI160_E_FOC_FAILURE; - } - } - - if(rslt == BMI160_OK) { - /* Read registers 0x04-0x17 */ - rslt = bmi160_get_regs(BMI160_GYRO_DATA_ADDR, data_array, 20, dev); - } - } - - return rslt; -} +struct imu_t imu_bmi160 = {BMI160_DEV_ADDR, bmi160_begin, bmi160_end, bmi160_read, BMI160_TAG}; diff --git a/airmouse/tracking/imu/bmi160_defs.h b/airmouse/tracking/imu/bmi160_defs.h deleted file mode 100644 index 458ecaad5e7..00000000000 --- a/airmouse/tracking/imu/bmi160_defs.h +++ /dev/null @@ -1,1619 +0,0 @@ -/** -* Copyright (c) 2021 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 bmi160_defs.h -* @date 2021-10-05 -* @version v3.9.2 -* -*/ - -#ifndef BMI160_DEFS_H_ -#define BMI160_DEFS_H_ - -/*************************** C types headers *****************************/ -#ifdef __KERNEL__ -#include -#include -#else -#include -#include -#endif - -/*************************** Common macros *****************************/ - -#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 - -/**@}*/ -/**\name C standard macros */ -#ifndef NULL -#ifdef __cplusplus -#define NULL 0 -#else -#define NULL ((void*)0) -#endif -#endif - -/*************************** Sensor macros *****************************/ -/* Test for an endian machine */ -#ifndef __ORDER_LITTLE_ENDIAN__ -#define __ORDER_LITTLE_ENDIAN__ 0 -#endif - -#ifndef __BYTE_ORDER__ -#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ -#endif - -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -#ifndef LITTLE_ENDIAN -#define LITTLE_ENDIAN 1 -#endif -#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -#ifndef BIG_ENDIAN -#define BIG_ENDIAN 1 -#endif -#else -#error "Code does not support Endian format of the processor" -#endif - -/** Mask definitions */ -#define BMI160_ACCEL_BW_MASK UINT8_C(0x70) -#define BMI160_ACCEL_ODR_MASK UINT8_C(0x0F) -#define BMI160_ACCEL_UNDERSAMPLING_MASK UINT8_C(0x80) -#define BMI160_ACCEL_RANGE_MASK UINT8_C(0x0F) -#define BMI160_GYRO_BW_MASK UINT8_C(0x30) -#define BMI160_GYRO_ODR_MASK UINT8_C(0x0F) -#define BMI160_GYRO_RANGE_MASK UINT8_C(0x07) - -#define BMI160_ACCEL_BW_POS UINT8_C(4) -#define BMI160_GYRO_BW_POS UINT8_C(4) - -/** Mask definitions for INT_EN registers */ -#define BMI160_ANY_MOTION_X_INT_EN_MASK UINT8_C(0x01) -#define BMI160_HIGH_G_X_INT_EN_MASK UINT8_C(0x01) -#define BMI160_NO_MOTION_X_INT_EN_MASK UINT8_C(0x01) -#define BMI160_ANY_MOTION_Y_INT_EN_MASK UINT8_C(0x02) -#define BMI160_HIGH_G_Y_INT_EN_MASK UINT8_C(0x02) -#define BMI160_NO_MOTION_Y_INT_EN_MASK UINT8_C(0x02) -#define BMI160_ANY_MOTION_Z_INT_EN_MASK UINT8_C(0x04) -#define BMI160_HIGH_G_Z_INT_EN_MASK UINT8_C(0x04) -#define BMI160_NO_MOTION_Z_INT_EN_MASK UINT8_C(0x04) -#define BMI160_SIG_MOTION_INT_EN_MASK UINT8_C(0x07) -#define BMI160_ANY_MOTION_ALL_INT_EN_MASK UINT8_C(0x07) -#define BMI160_STEP_DETECT_INT_EN_MASK UINT8_C(0x08) -#define BMI160_DOUBLE_TAP_INT_EN_MASK UINT8_C(0x10) -#define BMI160_SINGLE_TAP_INT_EN_MASK UINT8_C(0x20) -#define BMI160_FIFO_FULL_INT_EN_MASK UINT8_C(0x20) -#define BMI160_ORIENT_INT_EN_MASK UINT8_C(0x40) -#define BMI160_FIFO_WATERMARK_INT_EN_MASK UINT8_C(0x40) -#define BMI160_LOW_G_INT_EN_MASK UINT8_C(0x08) -#define BMI160_STEP_DETECT_EN_MASK UINT8_C(0x08) -#define BMI160_FLAT_INT_EN_MASK UINT8_C(0x80) -#define BMI160_DATA_RDY_INT_EN_MASK UINT8_C(0x10) - -/** PMU status Macros */ -#define BMI160_AUX_PMU_SUSPEND UINT8_C(0x00) -#define BMI160_AUX_PMU_NORMAL UINT8_C(0x01) -#define BMI160_AUX_PMU_LOW_POWER UINT8_C(0x02) - -#define BMI160_GYRO_PMU_SUSPEND UINT8_C(0x00) -#define BMI160_GYRO_PMU_NORMAL UINT8_C(0x01) -#define BMI160_GYRO_PMU_FSU UINT8_C(0x03) - -#define BMI160_ACCEL_PMU_SUSPEND UINT8_C(0x00) -#define BMI160_ACCEL_PMU_NORMAL UINT8_C(0x01) -#define BMI160_ACCEL_PMU_LOW_POWER UINT8_C(0x02) - -/** Mask definitions for INT_OUT_CTRL register */ -#define BMI160_INT1_EDGE_CTRL_MASK UINT8_C(0x01) -#define BMI160_INT1_OUTPUT_MODE_MASK UINT8_C(0x04) -#define BMI160_INT1_OUTPUT_TYPE_MASK UINT8_C(0x02) -#define BMI160_INT1_OUTPUT_EN_MASK UINT8_C(0x08) -#define BMI160_INT2_EDGE_CTRL_MASK UINT8_C(0x10) -#define BMI160_INT2_OUTPUT_MODE_MASK UINT8_C(0x40) -#define BMI160_INT2_OUTPUT_TYPE_MASK UINT8_C(0x20) -#define BMI160_INT2_OUTPUT_EN_MASK UINT8_C(0x80) - -/** Mask definitions for INT_LATCH register */ -#define BMI160_INT1_INPUT_EN_MASK UINT8_C(0x10) -#define BMI160_INT2_INPUT_EN_MASK UINT8_C(0x20) -#define BMI160_INT_LATCH_MASK UINT8_C(0x0F) - -/** Mask definitions for INT_MAP register */ -#define BMI160_INT1_LOW_G_MASK UINT8_C(0x01) -#define BMI160_INT1_HIGH_G_MASK UINT8_C(0x02) -#define BMI160_INT1_SLOPE_MASK UINT8_C(0x04) -#define BMI160_INT1_NO_MOTION_MASK UINT8_C(0x08) -#define BMI160_INT1_DOUBLE_TAP_MASK UINT8_C(0x10) -#define BMI160_INT1_SINGLE_TAP_MASK UINT8_C(0x20) -#define BMI160_INT1_FIFO_FULL_MASK UINT8_C(0x20) -#define BMI160_INT1_FIFO_WM_MASK UINT8_C(0x40) -#define BMI160_INT1_ORIENT_MASK UINT8_C(0x40) -#define BMI160_INT1_FLAT_MASK UINT8_C(0x80) -#define BMI160_INT1_DATA_READY_MASK UINT8_C(0x80) -#define BMI160_INT2_LOW_G_MASK UINT8_C(0x01) -#define BMI160_INT1_LOW_STEP_DETECT_MASK UINT8_C(0x01) -#define BMI160_INT2_LOW_STEP_DETECT_MASK UINT8_C(0x01) -#define BMI160_INT2_HIGH_G_MASK UINT8_C(0x02) -#define BMI160_INT2_FIFO_FULL_MASK UINT8_C(0x02) -#define BMI160_INT2_FIFO_WM_MASK UINT8_C(0x04) -#define BMI160_INT2_SLOPE_MASK UINT8_C(0x04) -#define BMI160_INT2_DATA_READY_MASK UINT8_C(0x08) -#define BMI160_INT2_NO_MOTION_MASK UINT8_C(0x08) -#define BMI160_INT2_DOUBLE_TAP_MASK UINT8_C(0x10) -#define BMI160_INT2_SINGLE_TAP_MASK UINT8_C(0x20) -#define BMI160_INT2_ORIENT_MASK UINT8_C(0x40) -#define BMI160_INT2_FLAT_MASK UINT8_C(0x80) - -/** Mask definitions for INT_DATA register */ -#define BMI160_TAP_SRC_INT_MASK UINT8_C(0x08) -#define BMI160_LOW_HIGH_SRC_INT_MASK UINT8_C(0x80) -#define BMI160_MOTION_SRC_INT_MASK UINT8_C(0x80) - -/** Mask definitions for INT_MOTION register */ -#define BMI160_SLOPE_INT_DUR_MASK UINT8_C(0x03) -#define BMI160_NO_MOTION_INT_DUR_MASK UINT8_C(0xFC) -#define BMI160_NO_MOTION_SEL_BIT_MASK UINT8_C(0x01) - -/** Mask definitions for INT_TAP register */ -#define BMI160_TAP_DUR_MASK UINT8_C(0x07) -#define BMI160_TAP_SHOCK_DUR_MASK UINT8_C(0x40) -#define BMI160_TAP_QUIET_DUR_MASK UINT8_C(0x80) -#define BMI160_TAP_THRES_MASK UINT8_C(0x1F) - -/** Mask definitions for INT_FLAT register */ -#define BMI160_FLAT_THRES_MASK UINT8_C(0x3F) -#define BMI160_FLAT_HOLD_TIME_MASK UINT8_C(0x30) -#define BMI160_FLAT_HYST_MASK UINT8_C(0x07) - -/** Mask definitions for INT_LOWHIGH register */ -#define BMI160_LOW_G_HYST_MASK UINT8_C(0x03) -#define BMI160_LOW_G_LOW_MODE_MASK UINT8_C(0x04) -#define BMI160_HIGH_G_HYST_MASK UINT8_C(0xC0) - -/** Mask definitions for INT_SIG_MOTION register */ -#define BMI160_SIG_MOTION_SEL_MASK UINT8_C(0x02) -#define BMI160_SIG_MOTION_SKIP_MASK UINT8_C(0x0C) -#define BMI160_SIG_MOTION_PROOF_MASK UINT8_C(0x30) - -/** Mask definitions for INT_ORIENT register */ -#define BMI160_ORIENT_MODE_MASK UINT8_C(0x03) -#define BMI160_ORIENT_BLOCK_MASK UINT8_C(0x0C) -#define BMI160_ORIENT_HYST_MASK UINT8_C(0xF0) -#define BMI160_ORIENT_THETA_MASK UINT8_C(0x3F) -#define BMI160_ORIENT_UD_ENABLE UINT8_C(0x40) -#define BMI160_AXES_EN_MASK UINT8_C(0x80) - -/** Mask definitions for FIFO_CONFIG register */ -#define BMI160_FIFO_GYRO UINT8_C(0x80) -#define BMI160_FIFO_ACCEL UINT8_C(0x40) -#define BMI160_FIFO_AUX UINT8_C(0x20) -#define BMI160_FIFO_TAG_INT1 UINT8_C(0x08) -#define BMI160_FIFO_TAG_INT2 UINT8_C(0x04) -#define BMI160_FIFO_TIME UINT8_C(0x02) -#define BMI160_FIFO_HEADER UINT8_C(0x10) -#define BMI160_FIFO_CONFIG_1_MASK UINT8_C(0xFE) - -/** Mask definitions for STEP_CONF register */ -#define BMI160_STEP_COUNT_EN_BIT_MASK UINT8_C(0x08) -#define BMI160_STEP_DETECT_MIN_THRES_MASK UINT8_C(0x18) -#define BMI160_STEP_DETECT_STEPTIME_MIN_MASK UINT8_C(0x07) -#define BMI160_STEP_MIN_BUF_MASK UINT8_C(0x07) - -/** Mask definition for FIFO Header Data Tag */ -#define BMI160_FIFO_TAG_INTR_MASK UINT8_C(0xFC) - -/** Fifo byte counter mask definitions */ -#define BMI160_FIFO_BYTE_COUNTER_MASK UINT8_C(0x07) - -/** Enable/disable bit value */ -#define BMI160_ENABLE UINT8_C(0x01) -#define BMI160_DISABLE UINT8_C(0x00) - -/** Latch Duration */ -#define BMI160_LATCH_DUR_NONE UINT8_C(0x00) -#define BMI160_LATCH_DUR_312_5_MICRO_SEC UINT8_C(0x01) -#define BMI160_LATCH_DUR_625_MICRO_SEC UINT8_C(0x02) -#define BMI160_LATCH_DUR_1_25_MILLI_SEC UINT8_C(0x03) -#define BMI160_LATCH_DUR_2_5_MILLI_SEC UINT8_C(0x04) -#define BMI160_LATCH_DUR_5_MILLI_SEC UINT8_C(0x05) -#define BMI160_LATCH_DUR_10_MILLI_SEC UINT8_C(0x06) -#define BMI160_LATCH_DUR_20_MILLI_SEC UINT8_C(0x07) -#define BMI160_LATCH_DUR_40_MILLI_SEC UINT8_C(0x08) -#define BMI160_LATCH_DUR_80_MILLI_SEC UINT8_C(0x09) -#define BMI160_LATCH_DUR_160_MILLI_SEC UINT8_C(0x0A) -#define BMI160_LATCH_DUR_320_MILLI_SEC UINT8_C(0x0B) -#define BMI160_LATCH_DUR_640_MILLI_SEC UINT8_C(0x0C) -#define BMI160_LATCH_DUR_1_28_SEC UINT8_C(0x0D) -#define BMI160_LATCH_DUR_2_56_SEC UINT8_C(0x0E) -#define BMI160_LATCHED UINT8_C(0x0F) - -/** BMI160 Register map */ -#define BMI160_CHIP_ID_ADDR UINT8_C(0x00) -#define BMI160_ERROR_REG_ADDR UINT8_C(0x02) -#define BMI160_PMU_STATUS_ADDR UINT8_C(0x03) -#define BMI160_AUX_DATA_ADDR UINT8_C(0x04) -#define BMI160_GYRO_DATA_ADDR UINT8_C(0x0C) -#define BMI160_ACCEL_DATA_ADDR UINT8_C(0x12) -#define BMI160_STATUS_ADDR UINT8_C(0x1B) -#define BMI160_INT_STATUS_ADDR UINT8_C(0x1C) -#define BMI160_FIFO_LENGTH_ADDR UINT8_C(0x22) -#define BMI160_FIFO_DATA_ADDR UINT8_C(0x24) -#define BMI160_ACCEL_CONFIG_ADDR UINT8_C(0x40) -#define BMI160_ACCEL_RANGE_ADDR UINT8_C(0x41) -#define BMI160_GYRO_CONFIG_ADDR UINT8_C(0x42) -#define BMI160_GYRO_RANGE_ADDR UINT8_C(0x43) -#define BMI160_AUX_ODR_ADDR UINT8_C(0x44) -#define BMI160_FIFO_DOWN_ADDR UINT8_C(0x45) -#define BMI160_FIFO_CONFIG_0_ADDR UINT8_C(0x46) -#define BMI160_FIFO_CONFIG_1_ADDR UINT8_C(0x47) -#define BMI160_AUX_IF_0_ADDR UINT8_C(0x4B) -#define BMI160_AUX_IF_1_ADDR UINT8_C(0x4C) -#define BMI160_AUX_IF_2_ADDR UINT8_C(0x4D) -#define BMI160_AUX_IF_3_ADDR UINT8_C(0x4E) -#define BMI160_AUX_IF_4_ADDR UINT8_C(0x4F) -#define BMI160_INT_ENABLE_0_ADDR UINT8_C(0x50) -#define BMI160_INT_ENABLE_1_ADDR UINT8_C(0x51) -#define BMI160_INT_ENABLE_2_ADDR UINT8_C(0x52) -#define BMI160_INT_OUT_CTRL_ADDR UINT8_C(0x53) -#define BMI160_INT_LATCH_ADDR UINT8_C(0x54) -#define BMI160_INT_MAP_0_ADDR UINT8_C(0x55) -#define BMI160_INT_MAP_1_ADDR UINT8_C(0x56) -#define BMI160_INT_MAP_2_ADDR UINT8_C(0x57) -#define BMI160_INT_DATA_0_ADDR UINT8_C(0x58) -#define BMI160_INT_DATA_1_ADDR UINT8_C(0x59) -#define BMI160_INT_LOWHIGH_0_ADDR UINT8_C(0x5A) -#define BMI160_INT_LOWHIGH_1_ADDR UINT8_C(0x5B) -#define BMI160_INT_LOWHIGH_2_ADDR UINT8_C(0x5C) -#define BMI160_INT_LOWHIGH_3_ADDR UINT8_C(0x5D) -#define BMI160_INT_LOWHIGH_4_ADDR UINT8_C(0x5E) -#define BMI160_INT_MOTION_0_ADDR UINT8_C(0x5F) -#define BMI160_INT_MOTION_1_ADDR UINT8_C(0x60) -#define BMI160_INT_MOTION_2_ADDR UINT8_C(0x61) -#define BMI160_INT_MOTION_3_ADDR UINT8_C(0x62) -#define BMI160_INT_TAP_0_ADDR UINT8_C(0x63) -#define BMI160_INT_TAP_1_ADDR UINT8_C(0x64) -#define BMI160_INT_ORIENT_0_ADDR UINT8_C(0x65) -#define BMI160_INT_ORIENT_1_ADDR UINT8_C(0x66) -#define BMI160_INT_FLAT_0_ADDR UINT8_C(0x67) -#define BMI160_INT_FLAT_1_ADDR UINT8_C(0x68) -#define BMI160_FOC_CONF_ADDR UINT8_C(0x69) -#define BMI160_CONF_ADDR UINT8_C(0x6A) - -#define BMI160_IF_CONF_ADDR UINT8_C(0x6B) -#define BMI160_SELF_TEST_ADDR UINT8_C(0x6D) -#define BMI160_OFFSET_ADDR UINT8_C(0x71) -#define BMI160_OFFSET_CONF_ADDR UINT8_C(0x77) -#define BMI160_INT_STEP_CNT_0_ADDR UINT8_C(0x78) -#define BMI160_INT_STEP_CONFIG_0_ADDR UINT8_C(0x7A) -#define BMI160_INT_STEP_CONFIG_1_ADDR UINT8_C(0x7B) -#define BMI160_COMMAND_REG_ADDR UINT8_C(0x7E) -#define BMI160_SPI_COMM_TEST_ADDR UINT8_C(0x7F) -#define BMI160_INTL_PULLUP_CONF_ADDR UINT8_C(0x85) - -/** Error code definitions */ -#define BMI160_OK INT8_C(0) -#define BMI160_E_NULL_PTR INT8_C(-1) -#define BMI160_E_COM_FAIL INT8_C(-2) -#define BMI160_E_DEV_NOT_FOUND INT8_C(-3) -#define BMI160_E_OUT_OF_RANGE INT8_C(-4) -#define BMI160_E_INVALID_INPUT INT8_C(-5) -#define BMI160_E_ACCEL_ODR_BW_INVALID INT8_C(-6) -#define BMI160_E_GYRO_ODR_BW_INVALID INT8_C(-7) -#define BMI160_E_LWP_PRE_FLTR_INT_INVALID INT8_C(-8) -#define BMI160_E_LWP_PRE_FLTR_INVALID INT8_C(-9) -#define BMI160_E_AUX_NOT_FOUND INT8_C(-10) -#define BMI160_E_FOC_FAILURE INT8_C(-11) -#define BMI160_E_READ_WRITE_LENGTH_INVALID INT8_C(-12) -#define BMI160_E_INVALID_CONFIG INT8_C(-13) - -/**\name API warning codes */ -#define BMI160_W_GYRO_SELF_TEST_FAIL INT8_C(1) -#define BMI160_W_ACCEl_SELF_TEST_FAIL INT8_C(2) - -/** BMI160 unique chip identifier */ -#define BMI160_CHIP_ID UINT8_C(0xD1) - -/** Soft reset command */ -#define BMI160_SOFT_RESET_CMD UINT8_C(0xb6) -#define BMI160_SOFT_RESET_DELAY_MS UINT8_C(1) - -/** Start FOC command */ -#define BMI160_START_FOC_CMD UINT8_C(0x03) - -/** NVM backup enabling command */ -#define BMI160_NVM_BACKUP_EN UINT8_C(0xA0) - -/* Delay in ms settings */ -#define BMI160_ACCEL_DELAY_MS UINT8_C(5) -#define BMI160_GYRO_DELAY_MS UINT8_C(80) -#define BMI160_ONE_MS_DELAY UINT8_C(1) -#define BMI160_AUX_COM_DELAY UINT8_C(10) -#define BMI160_GYRO_SELF_TEST_DELAY UINT8_C(20) -#define BMI160_ACCEL_SELF_TEST_DELAY UINT8_C(50) - -/** Self test configurations */ -#define BMI160_ACCEL_SELF_TEST_CONFIG UINT8_C(0x2C) -#define BMI160_ACCEL_SELF_TEST_POSITIVE_EN UINT8_C(0x0D) -#define BMI160_ACCEL_SELF_TEST_NEGATIVE_EN UINT8_C(0x09) -#define BMI160_ACCEL_SELF_TEST_LIMIT UINT16_C(8192) - -/** Power mode settings */ -/* Accel power mode */ -#define BMI160_ACCEL_NORMAL_MODE UINT8_C(0x11) -#define BMI160_ACCEL_LOWPOWER_MODE UINT8_C(0x12) -#define BMI160_ACCEL_SUSPEND_MODE UINT8_C(0x10) - -/* Gyro power mode */ -#define BMI160_GYRO_SUSPEND_MODE UINT8_C(0x14) -#define BMI160_GYRO_NORMAL_MODE UINT8_C(0x15) -#define BMI160_GYRO_FASTSTARTUP_MODE UINT8_C(0x17) - -/* Aux power mode */ -#define BMI160_AUX_SUSPEND_MODE UINT8_C(0x18) -#define BMI160_AUX_NORMAL_MODE UINT8_C(0x19) -#define BMI160_AUX_LOWPOWER_MODE UINT8_C(0x1A) - -/** Range settings */ -/* Accel Range */ -#define BMI160_ACCEL_RANGE_2G UINT8_C(0x03) -#define BMI160_ACCEL_RANGE_4G UINT8_C(0x05) -#define BMI160_ACCEL_RANGE_8G UINT8_C(0x08) -#define BMI160_ACCEL_RANGE_16G UINT8_C(0x0C) - -/* Gyro Range */ -#define BMI160_GYRO_RANGE_2000_DPS UINT8_C(0x00) -#define BMI160_GYRO_RANGE_1000_DPS UINT8_C(0x01) -#define BMI160_GYRO_RANGE_500_DPS UINT8_C(0x02) -#define BMI160_GYRO_RANGE_250_DPS UINT8_C(0x03) -#define BMI160_GYRO_RANGE_125_DPS UINT8_C(0x04) - -/** Bandwidth settings */ -/* Accel Bandwidth */ -#define BMI160_ACCEL_BW_OSR4_AVG1 UINT8_C(0x00) -#define BMI160_ACCEL_BW_OSR2_AVG2 UINT8_C(0x01) -#define BMI160_ACCEL_BW_NORMAL_AVG4 UINT8_C(0x02) -#define BMI160_ACCEL_BW_RES_AVG8 UINT8_C(0x03) -#define BMI160_ACCEL_BW_RES_AVG16 UINT8_C(0x04) -#define BMI160_ACCEL_BW_RES_AVG32 UINT8_C(0x05) -#define BMI160_ACCEL_BW_RES_AVG64 UINT8_C(0x06) -#define BMI160_ACCEL_BW_RES_AVG128 UINT8_C(0x07) - -#define BMI160_GYRO_BW_OSR4_MODE UINT8_C(0x00) -#define BMI160_GYRO_BW_OSR2_MODE UINT8_C(0x01) -#define BMI160_GYRO_BW_NORMAL_MODE UINT8_C(0x02) - -/* Output Data Rate settings */ -/* Accel Output data rate */ -#define BMI160_ACCEL_ODR_RESERVED UINT8_C(0x00) -#define BMI160_ACCEL_ODR_0_78HZ UINT8_C(0x01) -#define BMI160_ACCEL_ODR_1_56HZ UINT8_C(0x02) -#define BMI160_ACCEL_ODR_3_12HZ UINT8_C(0x03) -#define BMI160_ACCEL_ODR_6_25HZ UINT8_C(0x04) -#define BMI160_ACCEL_ODR_12_5HZ UINT8_C(0x05) -#define BMI160_ACCEL_ODR_25HZ UINT8_C(0x06) -#define BMI160_ACCEL_ODR_50HZ UINT8_C(0x07) -#define BMI160_ACCEL_ODR_100HZ UINT8_C(0x08) -#define BMI160_ACCEL_ODR_200HZ UINT8_C(0x09) -#define BMI160_ACCEL_ODR_400HZ UINT8_C(0x0A) -#define BMI160_ACCEL_ODR_800HZ UINT8_C(0x0B) -#define BMI160_ACCEL_ODR_1600HZ UINT8_C(0x0C) -#define BMI160_ACCEL_ODR_RESERVED0 UINT8_C(0x0D) -#define BMI160_ACCEL_ODR_RESERVED1 UINT8_C(0x0E) -#define BMI160_ACCEL_ODR_RESERVED2 UINT8_C(0x0F) - -/* Gyro Output data rate */ -#define BMI160_GYRO_ODR_RESERVED UINT8_C(0x00) -#define BMI160_GYRO_ODR_25HZ UINT8_C(0x06) -#define BMI160_GYRO_ODR_50HZ UINT8_C(0x07) -#define BMI160_GYRO_ODR_100HZ UINT8_C(0x08) -#define BMI160_GYRO_ODR_200HZ UINT8_C(0x09) -#define BMI160_GYRO_ODR_400HZ UINT8_C(0x0A) -#define BMI160_GYRO_ODR_800HZ UINT8_C(0x0B) -#define BMI160_GYRO_ODR_1600HZ UINT8_C(0x0C) -#define BMI160_GYRO_ODR_3200HZ UINT8_C(0x0D) - -/* Auxiliary sensor Output data rate */ -#define BMI160_AUX_ODR_RESERVED UINT8_C(0x00) -#define BMI160_AUX_ODR_0_78HZ UINT8_C(0x01) -#define BMI160_AUX_ODR_1_56HZ UINT8_C(0x02) -#define BMI160_AUX_ODR_3_12HZ UINT8_C(0x03) -#define BMI160_AUX_ODR_6_25HZ UINT8_C(0x04) -#define BMI160_AUX_ODR_12_5HZ UINT8_C(0x05) -#define BMI160_AUX_ODR_25HZ UINT8_C(0x06) -#define BMI160_AUX_ODR_50HZ UINT8_C(0x07) -#define BMI160_AUX_ODR_100HZ UINT8_C(0x08) -#define BMI160_AUX_ODR_200HZ UINT8_C(0x09) -#define BMI160_AUX_ODR_400HZ UINT8_C(0x0A) -#define BMI160_AUX_ODR_800HZ UINT8_C(0x0B) - -/** FIFO_CONFIG Definitions */ -#define BMI160_FIFO_TIME_ENABLE UINT8_C(0x02) -#define BMI160_FIFO_TAG_INT2_ENABLE UINT8_C(0x04) -#define BMI160_FIFO_TAG_INT1_ENABLE UINT8_C(0x08) -#define BMI160_FIFO_HEAD_ENABLE UINT8_C(0x10) -#define BMI160_FIFO_M_ENABLE UINT8_C(0x20) -#define BMI160_FIFO_A_ENABLE UINT8_C(0x40) -#define BMI160_FIFO_M_A_ENABLE UINT8_C(0x60) -#define BMI160_FIFO_G_ENABLE UINT8_C(0x80) -#define BMI160_FIFO_M_G_ENABLE UINT8_C(0xA0) -#define BMI160_FIFO_G_A_ENABLE UINT8_C(0xC0) -#define BMI160_FIFO_M_G_A_ENABLE UINT8_C(0xE0) - -/* Macro to specify the number of bytes over-read from the - * FIFO in order to get the sensor time at the end of FIFO */ -#ifndef BMI160_FIFO_BYTES_OVERREAD -#define BMI160_FIFO_BYTES_OVERREAD UINT8_C(25) -#endif - -/* Accel, gyro and aux. sensor length and also their combined - * length definitions in FIFO */ -#define BMI160_FIFO_G_LENGTH UINT8_C(6) -#define BMI160_FIFO_A_LENGTH UINT8_C(6) -#define BMI160_FIFO_M_LENGTH UINT8_C(8) -#define BMI160_FIFO_GA_LENGTH UINT8_C(12) -#define BMI160_FIFO_MA_LENGTH UINT8_C(14) -#define BMI160_FIFO_MG_LENGTH UINT8_C(14) -#define BMI160_FIFO_MGA_LENGTH UINT8_C(20) - -/** FIFO Header Data definitions */ -#define BMI160_FIFO_HEAD_SKIP_FRAME UINT8_C(0x40) -#define BMI160_FIFO_HEAD_SENSOR_TIME UINT8_C(0x44) -#define BMI160_FIFO_HEAD_INPUT_CONFIG UINT8_C(0x48) -#define BMI160_FIFO_HEAD_OVER_READ UINT8_C(0x80) -#define BMI160_FIFO_HEAD_A UINT8_C(0x84) -#define BMI160_FIFO_HEAD_G UINT8_C(0x88) -#define BMI160_FIFO_HEAD_G_A UINT8_C(0x8C) -#define BMI160_FIFO_HEAD_M UINT8_C(0x90) -#define BMI160_FIFO_HEAD_M_A UINT8_C(0x94) -#define BMI160_FIFO_HEAD_M_G UINT8_C(0x98) -#define BMI160_FIFO_HEAD_M_G_A UINT8_C(0x9C) - -/** FIFO sensor time length definitions */ -#define BMI160_SENSOR_TIME_LENGTH UINT8_C(3) - -/** FIFO DOWN selection */ -/* Accel fifo down-sampling values*/ -#define BMI160_ACCEL_FIFO_DOWN_ZERO UINT8_C(0x00) -#define BMI160_ACCEL_FIFO_DOWN_ONE UINT8_C(0x10) -#define BMI160_ACCEL_FIFO_DOWN_TWO UINT8_C(0x20) -#define BMI160_ACCEL_FIFO_DOWN_THREE UINT8_C(0x30) -#define BMI160_ACCEL_FIFO_DOWN_FOUR UINT8_C(0x40) -#define BMI160_ACCEL_FIFO_DOWN_FIVE UINT8_C(0x50) -#define BMI160_ACCEL_FIFO_DOWN_SIX UINT8_C(0x60) -#define BMI160_ACCEL_FIFO_DOWN_SEVEN UINT8_C(0x70) - -/* Gyro fifo down-smapling values*/ -#define BMI160_GYRO_FIFO_DOWN_ZERO UINT8_C(0x00) -#define BMI160_GYRO_FIFO_DOWN_ONE UINT8_C(0x01) -#define BMI160_GYRO_FIFO_DOWN_TWO UINT8_C(0x02) -#define BMI160_GYRO_FIFO_DOWN_THREE UINT8_C(0x03) -#define BMI160_GYRO_FIFO_DOWN_FOUR UINT8_C(0x04) -#define BMI160_GYRO_FIFO_DOWN_FIVE UINT8_C(0x05) -#define BMI160_GYRO_FIFO_DOWN_SIX UINT8_C(0x06) -#define BMI160_GYRO_FIFO_DOWN_SEVEN UINT8_C(0x07) - -/* Accel Fifo filter enable*/ -#define BMI160_ACCEL_FIFO_FILT_EN UINT8_C(0x80) - -/* Gyro Fifo filter enable*/ -#define BMI160_GYRO_FIFO_FILT_EN UINT8_C(0x08) - -/** Definitions to check validity of FIFO frames */ -#define FIFO_CONFIG_MSB_CHECK UINT8_C(0x80) -#define FIFO_CONFIG_LSB_CHECK UINT8_C(0x00) - -/*! BMI160 accel FOC configurations */ -#define BMI160_FOC_ACCEL_DISABLED UINT8_C(0x00) -#define BMI160_FOC_ACCEL_POSITIVE_G UINT8_C(0x01) -#define BMI160_FOC_ACCEL_NEGATIVE_G UINT8_C(0x02) -#define BMI160_FOC_ACCEL_0G UINT8_C(0x03) - -/** Array Parameter DefinItions */ -#define BMI160_SENSOR_TIME_LSB_BYTE UINT8_C(0) -#define BMI160_SENSOR_TIME_XLSB_BYTE UINT8_C(1) -#define BMI160_SENSOR_TIME_MSB_BYTE UINT8_C(2) - -/** Interface settings */ -#define BMI160_SPI_INTF UINT8_C(1) -#define BMI160_I2C_INTF UINT8_C(0) -#define BMI160_SPI_RD_MASK UINT8_C(0x80) -#define BMI160_SPI_WR_MASK UINT8_C(0x7F) - -/* Sensor & time select definition*/ -#define BMI160_ACCEL_SEL UINT8_C(0x01) -#define BMI160_GYRO_SEL UINT8_C(0x02) -#define BMI160_TIME_SEL UINT8_C(0x04) - -/* Sensor select mask*/ -#define BMI160_SEN_SEL_MASK UINT8_C(0x07) - -/* Error code mask */ -#define BMI160_ERR_REG_MASK UINT8_C(0x0F) - -/* BMI160 I2C address */ -#define BMI160_I2C_ADDR UINT8_C(0x68) - -/* BMI160 secondary IF address */ -#define BMI160_AUX_BMM150_I2C_ADDR UINT8_C(0x10) - -/** BMI160 Length definitions */ -#define BMI160_ONE UINT8_C(1) -#define BMI160_TWO UINT8_C(2) -#define BMI160_THREE UINT8_C(3) -#define BMI160_FOUR UINT8_C(4) -#define BMI160_FIVE UINT8_C(5) - -/** BMI160 fifo level Margin */ -#define BMI160_FIFO_LEVEL_MARGIN UINT8_C(16) - -/** BMI160 fifo flush Command */ -#define BMI160_FIFO_FLUSH_VALUE UINT8_C(0xB0) - -/** BMI160 offset values for xyz axes of accel */ -#define BMI160_ACCEL_MIN_OFFSET INT8_C(-128) -#define BMI160_ACCEL_MAX_OFFSET INT8_C(127) - -/** BMI160 offset values for xyz axes of gyro */ -#define BMI160_GYRO_MIN_OFFSET INT16_C(-512) -#define BMI160_GYRO_MAX_OFFSET INT16_C(511) - -/** BMI160 fifo full interrupt position and mask */ -#define BMI160_FIFO_FULL_INT_POS UINT8_C(5) -#define BMI160_FIFO_FULL_INT_MSK UINT8_C(0x20) -#define BMI160_FIFO_WTM_INT_POS UINT8_C(6) -#define BMI160_FIFO_WTM_INT_MSK UINT8_C(0x40) - -#define BMI160_FIFO_FULL_INT_PIN1_POS UINT8_C(5) -#define BMI160_FIFO_FULL_INT_PIN1_MSK UINT8_C(0x20) -#define BMI160_FIFO_FULL_INT_PIN2_POS UINT8_C(1) -#define BMI160_FIFO_FULL_INT_PIN2_MSK UINT8_C(0x02) - -#define BMI160_FIFO_WTM_INT_PIN1_POS UINT8_C(6) -#define BMI160_FIFO_WTM_INT_PIN1_MSK UINT8_C(0x40) -#define BMI160_FIFO_WTM_INT_PIN2_POS UINT8_C(2) -#define BMI160_FIFO_WTM_INT_PIN2_MSK UINT8_C(0x04) - -#define BMI160_MANUAL_MODE_EN_POS UINT8_C(7) -#define BMI160_MANUAL_MODE_EN_MSK UINT8_C(0x80) -#define BMI160_AUX_READ_BURST_POS UINT8_C(0) -#define BMI160_AUX_READ_BURST_MSK UINT8_C(0x03) - -#define BMI160_GYRO_SELF_TEST_POS UINT8_C(4) -#define BMI160_GYRO_SELF_TEST_MSK UINT8_C(0x10) -#define BMI160_GYRO_SELF_TEST_STATUS_POS UINT8_C(1) -#define BMI160_GYRO_SELF_TEST_STATUS_MSK UINT8_C(0x02) - -#define BMI160_GYRO_FOC_EN_POS UINT8_C(6) -#define BMI160_GYRO_FOC_EN_MSK UINT8_C(0x40) - -#define BMI160_ACCEL_FOC_X_CONF_POS UINT8_C(4) -#define BMI160_ACCEL_FOC_X_CONF_MSK UINT8_C(0x30) - -#define BMI160_ACCEL_FOC_Y_CONF_POS UINT8_C(2) -#define BMI160_ACCEL_FOC_Y_CONF_MSK UINT8_C(0x0C) - -#define BMI160_ACCEL_FOC_Z_CONF_MSK UINT8_C(0x03) - -#define BMI160_FOC_STATUS_POS UINT8_C(3) -#define BMI160_FOC_STATUS_MSK UINT8_C(0x08) - -#define BMI160_GYRO_OFFSET_X_MSK UINT8_C(0x03) - -#define BMI160_GYRO_OFFSET_Y_POS UINT8_C(2) -#define BMI160_GYRO_OFFSET_Y_MSK UINT8_C(0x0C) - -#define BMI160_GYRO_OFFSET_Z_POS UINT8_C(4) -#define BMI160_GYRO_OFFSET_Z_MSK UINT8_C(0x30) - -#define BMI160_GYRO_OFFSET_EN_POS UINT8_C(7) -#define BMI160_GYRO_OFFSET_EN_MSK UINT8_C(0x80) - -#define BMI160_ACCEL_OFFSET_EN_POS UINT8_C(6) -#define BMI160_ACCEL_OFFSET_EN_MSK UINT8_C(0x40) - -#define BMI160_GYRO_OFFSET_POS UINT16_C(8) -#define BMI160_GYRO_OFFSET_MSK UINT16_C(0x0300) - -#define BMI160_NVM_UPDATE_POS UINT8_C(1) -#define BMI160_NVM_UPDATE_MSK UINT8_C(0x02) - -#define BMI160_NVM_STATUS_POS UINT8_C(4) -#define BMI160_NVM_STATUS_MSK UINT8_C(0x10) - -#define BMI160_MAG_POWER_MODE_MSK UINT8_C(0x03) - -#define BMI160_ACCEL_POWER_MODE_MSK UINT8_C(0x30) -#define BMI160_ACCEL_POWER_MODE_POS UINT8_C(4) - -#define BMI160_GYRO_POWER_MODE_MSK UINT8_C(0x0C) -#define BMI160_GYRO_POWER_MODE_POS UINT8_C(2) - -/* BIT SLICE GET AND SET FUNCTIONS */ -#define BMI160_GET_BITS(regvar, bitname) ((regvar & bitname##_MSK) >> bitname##_POS) -#define BMI160_SET_BITS(regvar, bitname, val) \ - ((regvar & ~bitname##_MSK) | ((val << bitname##_POS) & bitname##_MSK)) - -#define BMI160_SET_BITS_POS_0(reg_data, bitname, data) \ - ((reg_data & ~(bitname##_MSK)) | (data & bitname##_MSK)) - -#define BMI160_GET_BITS_POS_0(reg_data, bitname) (reg_data & (bitname##_MSK)) - -/**\name UTILITY MACROS */ -#define BMI160_SET_LOW_BYTE UINT16_C(0x00FF) -#define BMI160_SET_HIGH_BYTE UINT16_C(0xFF00) - -#define BMI160_GET_LSB(var) (uint8_t)(var & BMI160_SET_LOW_BYTE) -#define BMI160_GET_MSB(var) (uint8_t)((var & BMI160_SET_HIGH_BYTE) >> 8) - -/*****************************************************************************/ -/* type definitions */ - -/*! - * @brief Bus communication function pointer which should be mapped to - * the platform specific read functions of the user - */ -typedef int8_t ( - *bmi160_read_fptr_t)(uint8_t dev_addr, uint8_t reg_addr, uint8_t* data, uint16_t len); - -/*! - * @brief Bus communication function pointer which should be mapped to - * the platform specific write functions of the user - */ -typedef int8_t ( - *bmi160_write_fptr_t)(uint8_t dev_addr, uint8_t reg_addr, uint8_t* read_data, uint16_t len); -typedef void (*bmi160_delay_fptr_t)(uint32_t period); - -/*************************** Data structures *********************************/ - -/*! - * @brief bmi160 interrupt status selection enum. - */ -enum bmi160_int_status_sel { - BMI160_INT_STATUS_0 = 1, - BMI160_INT_STATUS_1 = 2, - BMI160_INT_STATUS_2 = 4, - BMI160_INT_STATUS_3 = 8, - BMI160_INT_STATUS_ALL = 15 -}; - -/*! - * @brief bmi160 interrupt status bits structure - */ -struct bmi160_int_status_bits { -#ifdef LITTLE_ENDIAN - - uint32_t step : 1; - uint32_t sigmot : 1; - uint32_t anym : 1; - - /* pmu trigger will be handled later */ - uint32_t pmu_trigger_reserved : 1; - uint32_t d_tap : 1; - uint32_t s_tap : 1; - uint32_t orient : 1; - uint32_t flat_int : 1; - uint32_t reserved : 2; - uint32_t high_g : 1; - uint32_t low_g : 1; - uint32_t drdy : 1; - uint32_t ffull : 1; - uint32_t fwm : 1; - uint32_t nomo : 1; - uint32_t anym_first_x : 1; - uint32_t anym_first_y : 1; - uint32_t anym_first_z : 1; - uint32_t anym_sign : 1; - uint32_t tap_first_x : 1; - uint32_t tap_first_y : 1; - uint32_t tap_first_z : 1; - uint32_t tap_sign : 1; - uint32_t high_first_x : 1; - uint32_t high_first_y : 1; - uint32_t high_first_z : 1; - uint32_t high_sign : 1; - uint32_t orient_1_0 : 2; - uint32_t orient_2 : 1; - uint32_t flat : 1; -#else - uint32_t high_first_x : 1; - uint32_t high_first_y : 1; - uint32_t high_first_z : 1; - uint32_t high_sign : 1; - uint32_t orient_1_0 : 2; - uint32_t orient_2 : 1; - uint32_t flat : 1; - uint32_t anym_first_x : 1; - uint32_t anym_first_y : 1; - uint32_t anym_first_z : 1; - uint32_t anym_sign : 1; - uint32_t tap_first_x : 1; - uint32_t tap_first_y : 1; - uint32_t tap_first_z : 1; - uint32_t tap_sign : 1; - uint32_t reserved : 2; - uint32_t high_g : 1; - uint32_t low_g : 1; - uint32_t drdy : 1; - uint32_t ffull : 1; - uint32_t fwm : 1; - uint32_t nomo : 1; - uint32_t step : 1; - uint32_t sigmot : 1; - uint32_t anym : 1; - - /* pmu trigger will be handled later */ - uint32_t pmu_trigger_reserved : 1; - uint32_t d_tap : 1; - uint32_t s_tap : 1; - uint32_t orient : 1; - uint32_t flat_int : 1; -#endif -}; - -/*! - * @brief bmi160 interrupt status structure - */ -union bmi160_int_status { - uint8_t data[4]; - struct bmi160_int_status_bits bit; -}; - -/*! - * @brief bmi160 sensor data structure which comprises of accel data - */ -struct bmi160_sensor_data { - /*! X-axis sensor data */ - int16_t x; - - /*! Y-axis sensor data */ - int16_t y; - - /*! Z-axis sensor data */ - int16_t z; - - /*! sensor time */ - uint32_t sensortime; -}; - -/*! - * @brief bmi160 aux data structure which comprises of 8 bytes of accel data - */ -struct bmi160_aux_data { - /*! Auxiliary data */ - uint8_t data[8]; -}; - -/*! - * @brief bmi160 FOC configuration structure - */ -struct bmi160_foc_conf { - /*! Enabling FOC in gyro - * Assignable macros : - * - BMI160_ENABLE - * - BMI160_DISABLE - */ - uint8_t foc_gyr_en; - - /*! Accel FOC configurations - * Assignable macros : - * - BMI160_FOC_ACCEL_DISABLED - * - BMI160_FOC_ACCEL_POSITIVE_G - * - BMI160_FOC_ACCEL_NEGATIVE_G - * - BMI160_FOC_ACCEL_0G - */ - uint8_t foc_acc_x; - uint8_t foc_acc_y; - uint8_t foc_acc_z; - - /*! Enabling offset compensation for accel in data registers - * Assignable macros : - * - BMI160_ENABLE - * - BMI160_DISABLE - */ - uint8_t acc_off_en; - - /*! Enabling offset compensation for gyro in data registers - * Assignable macros : - * - BMI160_ENABLE - * - BMI160_DISABLE - */ - uint8_t gyro_off_en; -}; - -/*! - * @brief bmi160 accel gyro offsets - */ -struct bmi160_offsets { - /*! Accel offset for x axis */ - int8_t off_acc_x; - - /*! Accel offset for y axis */ - int8_t off_acc_y; - - /*! Accel offset for z axis */ - int8_t off_acc_z; - - /*! Gyro offset for x axis */ - int16_t off_gyro_x; - - /*! Gyro offset for y axis */ - int16_t off_gyro_y; - - /*! Gyro offset for z axis */ - int16_t off_gyro_z; -}; - -/*! - * @brief FIFO aux. sensor data structure - */ -struct bmi160_aux_fifo_data { - /*! The value of aux. sensor x LSB data */ - uint8_t aux_x_lsb; - - /*! The value of aux. sensor x MSB data */ - uint8_t aux_x_msb; - - /*! The value of aux. sensor y LSB data */ - uint8_t aux_y_lsb; - - /*! The value of aux. sensor y MSB data */ - uint8_t aux_y_msb; - - /*! The value of aux. sensor z LSB data */ - uint8_t aux_z_lsb; - - /*! The value of aux. sensor z MSB data */ - uint8_t aux_z_msb; - - /*! The value of aux. sensor r for BMM150 LSB data */ - uint8_t aux_r_y2_lsb; - - /*! The value of aux. sensor r for BMM150 MSB data */ - uint8_t aux_r_y2_msb; -}; - -/*! - * @brief bmi160 sensor select structure - */ -enum bmi160_select_sensor { BMI160_ACCEL_ONLY = 1, BMI160_GYRO_ONLY, BMI160_BOTH_ACCEL_AND_GYRO }; - -/*! - * @brief bmi160 sensor step detector mode structure - */ -enum bmi160_step_detect_mode { - BMI160_STEP_DETECT_NORMAL, - BMI160_STEP_DETECT_SENSITIVE, - BMI160_STEP_DETECT_ROBUST, - - /*! Non recommended User defined setting */ - BMI160_STEP_DETECT_USER_DEFINE -}; - -/*! - * @brief enum for auxiliary burst read selection - */ -enum bmi160_aux_read_len { - BMI160_AUX_READ_LEN_0, - BMI160_AUX_READ_LEN_1, - BMI160_AUX_READ_LEN_2, - BMI160_AUX_READ_LEN_3 -}; - -/*! - * @brief bmi160 sensor configuration structure - */ -struct bmi160_cfg { - /*! power mode */ - uint8_t power; - - /*! output data rate */ - uint8_t odr; - - /*! range */ - uint8_t range; - - /*! bandwidth */ - uint8_t bw; -}; - -/*! - * @brief Aux sensor configuration structure - */ -struct bmi160_aux_cfg { - /*! Aux sensor, 1 - enable 0 - disable */ - uint8_t aux_sensor_enable : 1; - - /*! Aux manual/auto mode status */ - uint8_t manual_enable : 1; - - /*! Aux read burst length */ - uint8_t aux_rd_burst_len : 2; - - /*! output data rate */ - uint8_t aux_odr : 4; - - /*! i2c addr of auxiliary sensor */ - uint8_t aux_i2c_addr; -}; - -/*! - * @brief bmi160 interrupt channel selection structure - */ -enum bmi160_int_channel { - /*! Un-map both channels */ - BMI160_INT_CHANNEL_NONE, - - /*! interrupt Channel 1 */ - BMI160_INT_CHANNEL_1, - - /*! interrupt Channel 2 */ - BMI160_INT_CHANNEL_2, - - /*! Map both channels */ - BMI160_INT_CHANNEL_BOTH -}; -enum bmi160_int_types { - /*! Slope/Any-motion interrupt */ - BMI160_ACC_ANY_MOTION_INT, - - /*! Significant motion interrupt */ - BMI160_ACC_SIG_MOTION_INT, - - /*! Step detector interrupt */ - BMI160_STEP_DETECT_INT, - - /*! double tap interrupt */ - BMI160_ACC_DOUBLE_TAP_INT, - - /*! single tap interrupt */ - BMI160_ACC_SINGLE_TAP_INT, - - /*! orientation interrupt */ - BMI160_ACC_ORIENT_INT, - - /*! flat interrupt */ - BMI160_ACC_FLAT_INT, - - /*! high-g interrupt */ - BMI160_ACC_HIGH_G_INT, - - /*! low-g interrupt */ - BMI160_ACC_LOW_G_INT, - - /*! slow/no-motion interrupt */ - BMI160_ACC_SLOW_NO_MOTION_INT, - - /*! data ready interrupt */ - BMI160_ACC_GYRO_DATA_RDY_INT, - - /*! fifo full interrupt */ - BMI160_ACC_GYRO_FIFO_FULL_INT, - - /*! fifo watermark interrupt */ - BMI160_ACC_GYRO_FIFO_WATERMARK_INT, - - /*! fifo tagging feature support */ - BMI160_FIFO_TAG_INT_PIN -}; - -/*! - * @brief bmi160 active state of any & sig motion interrupt. - */ -enum bmi160_any_sig_motion_active_interrupt_state { - /*! Both any & sig motion are disabled */ - BMI160_BOTH_ANY_SIG_MOTION_DISABLED = -1, - - /*! Any-motion selected */ - BMI160_ANY_MOTION_ENABLED, - - /*! Sig-motion selected */ - BMI160_SIG_MOTION_ENABLED -}; -struct bmi160_acc_tap_int_cfg { -#ifdef LITTLE_ENDIAN - - /*! tap threshold */ - uint16_t tap_thr : 5; - - /*! tap shock */ - uint16_t tap_shock : 1; - - /*! tap quiet */ - uint16_t tap_quiet : 1; - - /*! tap duration */ - uint16_t tap_dur : 3; - - /*! data source 0- filter & 1 pre-filter*/ - uint16_t tap_data_src : 1; - - /*! tap enable, 1 - enable, 0 - disable */ - uint16_t tap_en : 1; -#else - - /*! tap enable, 1 - enable, 0 - disable */ - uint16_t tap_en : 1; - - /*! data source 0- filter & 1 pre-filter*/ - uint16_t tap_data_src : 1; - - /*! tap duration */ - uint16_t tap_dur : 3; - - /*! tap quiet */ - uint16_t tap_quiet : 1; - - /*! tap shock */ - uint16_t tap_shock : 1; - - /*! tap threshold */ - uint16_t tap_thr : 5; -#endif -}; -struct bmi160_acc_any_mot_int_cfg { -#ifdef LITTLE_ENDIAN - - /*! 1 any-motion enable, 0 - any-motion disable */ - uint8_t anymotion_en : 1; - - /*! slope interrupt x, 1 - enable, 0 - disable */ - uint8_t anymotion_x : 1; - - /*! slope interrupt y, 1 - enable, 0 - disable */ - uint8_t anymotion_y : 1; - - /*! slope interrupt z, 1 - enable, 0 - disable */ - uint8_t anymotion_z : 1; - - /*! slope duration */ - uint8_t anymotion_dur : 2; - - /*! data source 0- filter & 1 pre-filter*/ - uint8_t anymotion_data_src : 1; - - /*! slope threshold */ - uint8_t anymotion_thr; -#else - - /*! slope threshold */ - uint8_t anymotion_thr; - - /*! data source 0- filter & 1 pre-filter*/ - uint8_t anymotion_data_src : 1; - - /*! slope duration */ - uint8_t anymotion_dur : 2; - - /*! slope interrupt z, 1 - enable, 0 - disable */ - uint8_t anymotion_z : 1; - - /*! slope interrupt y, 1 - enable, 0 - disable */ - uint8_t anymotion_y : 1; - - /*! slope interrupt x, 1 - enable, 0 - disable */ - uint8_t anymotion_x : 1; - - /*! 1 any-motion enable, 0 - any-motion disable */ - uint8_t anymotion_en : 1; -#endif -}; -struct bmi160_acc_sig_mot_int_cfg { -#ifdef LITTLE_ENDIAN - - /*! skip time of sig-motion interrupt */ - uint8_t sig_mot_skip : 2; - - /*! proof time of sig-motion interrupt */ - uint8_t sig_mot_proof : 2; - - /*! data source 0- filter & 1 pre-filter*/ - uint8_t sig_data_src : 1; - - /*! 1 - enable sig, 0 - disable sig & enable anymotion */ - uint8_t sig_en : 1; - - /*! sig-motion threshold */ - uint8_t sig_mot_thres; -#else - - /*! sig-motion threshold */ - uint8_t sig_mot_thres; - - /*! 1 - enable sig, 0 - disable sig & enable anymotion */ - uint8_t sig_en : 1; - - /*! data source 0- filter & 1 pre-filter*/ - uint8_t sig_data_src : 1; - - /*! proof time of sig-motion interrupt */ - uint8_t sig_mot_proof : 2; - - /*! skip time of sig-motion interrupt */ - uint8_t sig_mot_skip : 2; -#endif -}; -struct bmi160_acc_step_detect_int_cfg { -#ifdef LITTLE_ENDIAN - - /*! 1- step detector enable, 0- step detector disable */ - uint16_t step_detector_en : 1; - - /*! minimum threshold */ - uint16_t min_threshold : 2; - - /*! minimal detectable step time */ - uint16_t steptime_min : 3; - - /*! enable step counter mode setting */ - uint16_t step_detector_mode : 2; - - /*! minimum step buffer size*/ - uint16_t step_min_buf : 3; -#else - - /*! minimum step buffer size*/ - uint16_t step_min_buf : 3; - - /*! enable step counter mode setting */ - uint16_t step_detector_mode : 2; - - /*! minimal detectable step time */ - uint16_t steptime_min : 3; - - /*! minimum threshold */ - uint16_t min_threshold : 2; - - /*! 1- step detector enable, 0- step detector disable */ - uint16_t step_detector_en : 1; -#endif -}; -struct bmi160_acc_no_motion_int_cfg { -#ifdef LITTLE_ENDIAN - - /*! no motion interrupt x */ - uint16_t no_motion_x : 1; - - /*! no motion interrupt y */ - uint16_t no_motion_y : 1; - - /*! no motion interrupt z */ - uint16_t no_motion_z : 1; - - /*! no motion duration */ - uint16_t no_motion_dur : 6; - - /*! no motion sel , 1 - enable no-motion ,0- enable slow-motion */ - uint16_t no_motion_sel : 1; - - /*! data source 0- filter & 1 pre-filter*/ - uint16_t no_motion_src : 1; - - /*! no motion threshold */ - uint8_t no_motion_thres; -#else - - /*! no motion threshold */ - uint8_t no_motion_thres; - - /*! data source 0- filter & 1 pre-filter*/ - uint16_t no_motion_src : 1; - - /*! no motion sel , 1 - enable no-motion ,0- enable slow-motion */ - uint16_t no_motion_sel : 1; - - /*! no motion duration */ - uint16_t no_motion_dur : 6; - - /* no motion interrupt z */ - uint16_t no_motion_z : 1; - - /*! no motion interrupt y */ - uint16_t no_motion_y : 1; - - /*! no motion interrupt x */ - uint16_t no_motion_x : 1; -#endif -}; -struct bmi160_acc_orient_int_cfg { -#ifdef LITTLE_ENDIAN - - /*! thresholds for switching between the different orientations */ - uint16_t orient_mode : 2; - - /*! blocking_mode */ - uint16_t orient_blocking : 2; - - /*! Orientation interrupt hysteresis */ - uint16_t orient_hyst : 4; - - /*! Orientation interrupt theta */ - uint16_t orient_theta : 6; - - /*! Enable/disable Orientation interrupt */ - uint16_t orient_ud_en : 1; - - /*! exchange x- and z-axis in algorithm ,0 - z, 1 - x */ - uint16_t axes_ex : 1; - - /*! 1 - orient enable, 0 - orient disable */ - uint8_t orient_en : 1; -#else - - /*! 1 - orient enable, 0 - orient disable */ - uint8_t orient_en : 1; - - /*! exchange x- and z-axis in algorithm ,0 - z, 1 - x */ - uint16_t axes_ex : 1; - - /*! Enable/disable Orientation interrupt */ - uint16_t orient_ud_en : 1; - - /*! Orientation interrupt theta */ - uint16_t orient_theta : 6; - - /*! Orientation interrupt hysteresis */ - uint16_t orient_hyst : 4; - - /*! blocking_mode */ - uint16_t orient_blocking : 2; - - /*! thresholds for switching between the different orientations */ - uint16_t orient_mode : 2; -#endif -}; -struct bmi160_acc_flat_detect_int_cfg { -#ifdef LITTLE_ENDIAN - - /*! flat threshold */ - uint16_t flat_theta : 6; - - /*! flat interrupt hysteresis */ - uint16_t flat_hy : 3; - - /*! delay time for which the flat value must remain stable for the - * flat interrupt to be generated */ - uint16_t flat_hold_time : 2; - - /*! 1 - flat enable, 0 - flat disable */ - uint16_t flat_en : 1; -#else - - /*! 1 - flat enable, 0 - flat disable */ - uint16_t flat_en : 1; - - /*! delay time for which the flat value must remain stable for the - * flat interrupt to be generated */ - uint16_t flat_hold_time : 2; - - /*! flat interrupt hysteresis */ - uint16_t flat_hy : 3; - - /*! flat threshold */ - uint16_t flat_theta : 6; -#endif -}; -struct bmi160_acc_low_g_int_cfg { -#ifdef LITTLE_ENDIAN - - /*! low-g interrupt trigger delay */ - uint8_t low_dur; - - /*! low-g interrupt trigger threshold */ - uint8_t low_thres; - - /*! hysteresis of low-g interrupt */ - uint8_t low_hyst : 2; - - /*! 0 - single-axis mode ,1 - axis-summing mode */ - uint8_t low_mode : 1; - - /*! data source 0- filter & 1 pre-filter */ - uint8_t low_data_src : 1; - - /*! 1 - enable low-g, 0 - disable low-g */ - uint8_t low_en : 1; -#else - - /*! 1 - enable low-g, 0 - disable low-g */ - uint8_t low_en : 1; - - /*! data source 0- filter & 1 pre-filter */ - uint8_t low_data_src : 1; - - /*! 0 - single-axis mode ,1 - axis-summing mode */ - uint8_t low_mode : 1; - - /*! hysteresis of low-g interrupt */ - uint8_t low_hyst : 2; - - /*! low-g interrupt trigger threshold */ - uint8_t low_thres; - - /*! low-g interrupt trigger delay */ - uint8_t low_dur; -#endif -}; -struct bmi160_acc_high_g_int_cfg { -#ifdef LITTLE_ENDIAN - - /*! High-g interrupt x, 1 - enable, 0 - disable */ - uint8_t high_g_x : 1; - - /*! High-g interrupt y, 1 - enable, 0 - disable */ - uint8_t high_g_y : 1; - - /*! High-g interrupt z, 1 - enable, 0 - disable */ - uint8_t high_g_z : 1; - - /*! High-g hysteresis */ - uint8_t high_hy : 2; - - /*! data source 0- filter & 1 pre-filter */ - uint8_t high_data_src : 1; - - /*! High-g threshold */ - uint8_t high_thres; - - /*! High-g duration */ - uint8_t high_dur; -#else - - /*! High-g duration */ - uint8_t high_dur; - - /*! High-g threshold */ - uint8_t high_thres; - - /*! data source 0- filter & 1 pre-filter */ - uint8_t high_data_src : 1; - - /*! High-g hysteresis */ - uint8_t high_hy : 2; - - /*! High-g interrupt z, 1 - enable, 0 - disable */ - uint8_t high_g_z : 1; - - /*! High-g interrupt y, 1 - enable, 0 - disable */ - uint8_t high_g_y : 1; - - /*! High-g interrupt x, 1 - enable, 0 - disable */ - uint8_t high_g_x : 1; -#endif -}; -struct bmi160_int_pin_settg { -#ifdef LITTLE_ENDIAN - - /*! To enable either INT1 or INT2 pin as output. - * 0- output disabled ,1- output enabled */ - uint16_t output_en : 1; - - /*! 0 - push-pull 1- open drain,only valid if output_en is set 1 */ - uint16_t output_mode : 1; - - /*! 0 - active low , 1 - active high level. - * if output_en is 1,this applies to interrupts,else PMU_trigger */ - uint16_t output_type : 1; - - /*! 0 - level trigger , 1 - edge trigger */ - uint16_t edge_ctrl : 1; - - /*! To enable either INT1 or INT2 pin as input. - * 0 - input disabled ,1 - input enabled */ - uint16_t input_en : 1; - - /*! latch duration*/ - uint16_t latch_dur : 4; -#else - - /*! latch duration*/ - uint16_t latch_dur : 4; - - /*! Latched,non-latched or temporary interrupt modes */ - uint16_t input_en : 1; - - /*! 1 - edge trigger, 0 - level trigger */ - uint16_t edge_ctrl : 1; - - /*! 0 - active low , 1 - active high level. - * if output_en is 1,this applies to interrupts,else PMU_trigger */ - uint16_t output_type : 1; - - /*! 0 - push-pull , 1 - open drain,only valid if output_en is set 1 */ - uint16_t output_mode : 1; - - /*! To enable either INT1 or INT2 pin as output. - * 0 - output disabled , 1 - output enabled */ - uint16_t output_en : 1; -#endif -}; -union bmi160_int_type_cfg { - /*! Tap interrupt structure */ - struct bmi160_acc_tap_int_cfg acc_tap_int; - - /*! Slope interrupt structure */ - struct bmi160_acc_any_mot_int_cfg acc_any_motion_int; - - /*! Significant motion interrupt structure */ - struct bmi160_acc_sig_mot_int_cfg acc_sig_motion_int; - - /*! Step detector interrupt structure */ - struct bmi160_acc_step_detect_int_cfg acc_step_detect_int; - - /*! No motion interrupt structure */ - struct bmi160_acc_no_motion_int_cfg acc_no_motion_int; - - /*! Orientation interrupt structure */ - struct bmi160_acc_orient_int_cfg acc_orient_int; - - /*! Flat interrupt structure */ - struct bmi160_acc_flat_detect_int_cfg acc_flat_int; - - /*! Low-g interrupt structure */ - struct bmi160_acc_low_g_int_cfg acc_low_g_int; - - /*! High-g interrupt structure */ - struct bmi160_acc_high_g_int_cfg acc_high_g_int; -}; -struct bmi160_int_settg { - /*! Interrupt channel */ - enum bmi160_int_channel int_channel; - - /*! Select Interrupt */ - enum bmi160_int_types int_type; - - /*! Structure configuring Interrupt pins */ - struct bmi160_int_pin_settg int_pin_settg; - - /*! Union configures required interrupt */ - union bmi160_int_type_cfg int_type_cfg; - - /*! FIFO FULL INT 1-enable, 0-disable */ - uint8_t fifo_full_int_en : 1; - - /*! FIFO WTM INT 1-enable, 0-disable */ - uint8_t fifo_wtm_int_en : 1; -}; - -/*! - * @brief This structure holds the information for usage of - * FIFO by the user. - */ -struct bmi160_fifo_frame { - /*! Data buffer of user defined length is to be mapped here */ - uint8_t* data; - - /*! While calling the API "bmi160_get_fifo_data" , length stores - * number of bytes in FIFO to be read (specified by user as input) - * and after execution of the API ,number of FIFO data bytes - * available is provided as an output to user - */ - uint16_t length; - - /*! FIFO time enable */ - uint8_t fifo_time_enable; - - /*! Enabling of the FIFO header to stream in header mode */ - uint8_t fifo_header_enable; - - /*! Streaming of the Accelerometer, Gyroscope - * sensor data or both in FIFO */ - uint8_t fifo_data_enable; - - /*! Will be equal to length when no more frames are there to parse */ - uint16_t accel_byte_start_idx; - - /*! Will be equal to length when no more frames are there to parse */ - uint16_t gyro_byte_start_idx; - - /*! Will be equal to length when no more frames are there to parse */ - uint16_t aux_byte_start_idx; - - /*! Value of FIFO sensor time time */ - uint32_t sensor_time; - - /*! Value of Skipped frame counts */ - uint8_t skipped_frame_count; -}; -struct bmi160_dev { - /*! Chip Id */ - uint8_t chip_id; - - /*! Device Id */ - uint8_t id; - - /*! 0 - I2C , 1 - SPI Interface */ - uint8_t intf; - - /*! Hold active interrupts status for any and sig motion - * 0 - Any-motion enable, 1 - Sig-motion enable, - * -1 neither any-motion nor sig-motion selected */ - enum bmi160_any_sig_motion_active_interrupt_state any_sig_sel; - - /*! Structure to configure Accel sensor */ - struct bmi160_cfg accel_cfg; - - /*! Structure to hold previous/old accel config parameters. - * This is used at driver level to prevent overwriting of same - * data, hence user does not change it in the code */ - struct bmi160_cfg prev_accel_cfg; - - /*! Structure to configure Gyro sensor */ - struct bmi160_cfg gyro_cfg; - - /*! Structure to hold previous/old gyro config parameters. - * This is used at driver level to prevent overwriting of same - * data, hence user does not change it in the code */ - struct bmi160_cfg prev_gyro_cfg; - - /*! Structure to configure the auxiliary sensor */ - struct bmi160_aux_cfg aux_cfg; - - /*! Structure to hold previous/old aux config parameters. - * This is used at driver level to prevent overwriting of same - * data, hence user does not change it in the code */ - struct bmi160_aux_cfg prev_aux_cfg; - - /*! FIFO related configurations */ - struct bmi160_fifo_frame* fifo; - - /*! Read function pointer */ - bmi160_read_fptr_t read; - - /*! Write function pointer */ - bmi160_write_fptr_t write; - - /*! Delay function pointer */ - bmi160_delay_fptr_t delay_ms; - - /*! User set read/write length */ - uint16_t read_write_len; -}; - -#endif /* BMI160_DEFS_H_ */ diff --git a/airmouse/tracking/imu/imu.c b/airmouse/tracking/imu/imu.c index 5e89c9504d7..8c4cd6486ca 100644 --- a/airmouse/tracking/imu/imu.c +++ b/airmouse/tracking/imu/imu.c @@ -1,29 +1,54 @@ #include "imu.h" -#include -bool bmi160_begin(); -int bmi160_read(double* vec); +#define IMU_TAG "IMU_H" -bool lsm6ds3trc_begin(); -void lsm6ds3trc_end(); -int lsm6ds3trc_read(double* vec); +extern struct imu_t imu_bmi160; +extern struct imu_t imu_lsm6ds3trc; +extern struct imu_t imu_lsm6dso; + +struct imu_t* imu_types[] = {&imu_bmi160, &imu_lsm6ds3trc, &imu_lsm6dso}; + +static const int imu_count = sizeof(imu_types) / sizeof(struct imu_t*); + +static struct imu_t* imu_found; + +struct imu_t* find_imu() { + unsigned int i; + for(i = 0; i < imu_count; i++) { + if(furi_hal_i2c_is_device_ready(&furi_hal_i2c_handle_external, imu_types[i]->address, 50)) { + FURI_LOG_E(IMU_TAG, "found i2c device address 0x%X", imu_types[i]->address); + return imu_types[i]; + } + } + return NULL; +} bool imu_begin() { + bool ret = false; furi_hal_i2c_acquire(&furi_hal_i2c_handle_external); - bool ret = bmi160_begin(); // lsm6ds3trc_begin(); + + if(imu_found == NULL) { + imu_found = find_imu(); + if(imu_found != NULL) FURI_LOG_E(IMU_TAG, "Found Device %s", imu_found->name); + } + + if(imu_found != NULL) ret = imu_found->begin(); + furi_hal_i2c_release(&furi_hal_i2c_handle_external); return ret; } void imu_end() { - // furi_hal_i2c_acquire(&furi_hal_i2c_handle_external); - // lsm6ds3trc_end(); - // furi_hal_i2c_release(&furi_hal_i2c_handle_external); + if(imu_found == NULL) return; + furi_hal_i2c_acquire(&furi_hal_i2c_handle_external); + imu_found->end(); + furi_hal_i2c_release(&furi_hal_i2c_handle_external); } int imu_read(double* vec) { + if(imu_found == NULL) return 0; furi_hal_i2c_acquire(&furi_hal_i2c_handle_external); - int ret = bmi160_read(vec); // lsm6ds3trc_read(vec); + int ret = imu_found->read(vec); furi_hal_i2c_release(&furi_hal_i2c_handle_external); return ret; } diff --git a/airmouse/tracking/imu/imu.h b/airmouse/tracking/imu/imu.h index f4c5e4b1da6..9b416d2e2c9 100644 --- a/airmouse/tracking/imu/imu.h +++ b/airmouse/tracking/imu/imu.h @@ -1,14 +1,27 @@ -#pragma once +#ifndef IMU_H +#define IMU_H #include +#include #ifdef __cplusplus extern "C" { #endif +struct imu_t { + unsigned int address; + bool (*begin)(void); + void (*end)(void); + int (*read)(double* vec); + char* name; +}; + #define ACC_DATA_READY (1 << 0) #define GYR_DATA_READY (1 << 1) +static const double DEG_TO_RAD = 0.017453292519943295769236907684886; +static const double GRAVITY = 9.81; + bool imu_begin(); void imu_end(); int imu_read(double* vec); @@ -16,3 +29,4 @@ int imu_read(double* vec); #ifdef __cplusplus } #endif +#endif // IMU_H diff --git a/airmouse/tracking/imu/imu_bmi160.c b/airmouse/tracking/imu/imu_bmi160.c deleted file mode 100644 index af771302f40..00000000000 --- a/airmouse/tracking/imu/imu_bmi160.c +++ /dev/null @@ -1,88 +0,0 @@ -#include "bmi160.h" - -#include - -#include "imu.h" - -#define TAG "BMI160" - -#define BMI160_DEV_ADDR (0x69 << 1) - -static const double DEG_TO_RAD = 0.017453292519943295769236907684886; -static const double G = 9.81; - -struct bmi160_dev bmi160dev; -struct bmi160_sensor_data bmi160_accel; -struct bmi160_sensor_data bmi160_gyro; - -int8_t bmi160_write_i2c(uint8_t dev_addr, uint8_t reg_addr, uint8_t* data, uint16_t len) { - if(furi_hal_i2c_write_mem(&furi_hal_i2c_handle_external, dev_addr, reg_addr, data, len, 50)) - return BMI160_OK; - return BMI160_E_COM_FAIL; -} - -int8_t bmi160_read_i2c(uint8_t dev_addr, uint8_t reg_addr, uint8_t* read_data, uint16_t len) { - if(furi_hal_i2c_read_mem(&furi_hal_i2c_handle_external, dev_addr, reg_addr, read_data, len, 50)) - return BMI160_OK; - return BMI160_E_COM_FAIL; -} - -bool bmi160_begin() { - FURI_LOG_I(TAG, "Init BMI160"); - - if(!furi_hal_i2c_is_device_ready(&furi_hal_i2c_handle_external, BMI160_DEV_ADDR, 50)) { - FURI_LOG_E(TAG, "Device not ready!"); - return false; - } - - FURI_LOG_I(TAG, "Device ready!"); - - bmi160dev.id = BMI160_DEV_ADDR; - bmi160dev.intf = BMI160_I2C_INTF; - bmi160dev.read = bmi160_read_i2c; - bmi160dev.write = bmi160_write_i2c; - bmi160dev.delay_ms = furi_delay_ms; - - if(bmi160_init(&bmi160dev) != BMI160_OK) { - FURI_LOG_E(TAG, "Initialization failure!"); - FURI_LOG_E(TAG, "Chip ID 0x%X", bmi160dev.chip_id); - return false; - } - - bmi160dev.accel_cfg.odr = BMI160_ACCEL_ODR_400HZ; - bmi160dev.accel_cfg.range = BMI160_ACCEL_RANGE_4G; - bmi160dev.accel_cfg.bw = BMI160_ACCEL_BW_NORMAL_AVG4; - bmi160dev.accel_cfg.power = BMI160_ACCEL_NORMAL_MODE; - bmi160dev.gyro_cfg.odr = BMI160_GYRO_ODR_400HZ; - bmi160dev.gyro_cfg.range = BMI160_GYRO_RANGE_2000_DPS; - bmi160dev.gyro_cfg.bw = BMI160_GYRO_BW_NORMAL_MODE; - bmi160dev.gyro_cfg.power = BMI160_GYRO_NORMAL_MODE; - - if(bmi160_set_sens_conf(&bmi160dev) != BMI160_OK) { - FURI_LOG_E(TAG, "Initialization failure!"); - FURI_LOG_E(TAG, "Chip ID 0x%X", bmi160dev.chip_id); - return false; - } - - FURI_LOG_I(TAG, "Initialization success!"); - FURI_LOG_I(TAG, "Chip ID 0x%X", bmi160dev.chip_id); - - return true; -} - -int bmi160_read(double* vec) { - if(bmi160_get_sensor_data( - (BMI160_ACCEL_SEL | BMI160_GYRO_SEL), &bmi160_accel, &bmi160_gyro, &bmi160dev) != - BMI160_OK) { - return 0; - } - - vec[0] = ((double)bmi160_accel.x * 4 / 32768) * G; - vec[1] = ((double)bmi160_accel.y * 4 / 32768) * G; - vec[2] = ((double)bmi160_accel.z * 4 / 32768) * G; - vec[3] = ((double)bmi160_gyro.x * 2000 / 32768) * DEG_TO_RAD; - vec[4] = ((double)bmi160_gyro.y * 2000 / 32768) * DEG_TO_RAD; - vec[5] = ((double)bmi160_gyro.z * 2000 / 32768) * DEG_TO_RAD; - - return ACC_DATA_READY | GYR_DATA_READY; -} diff --git a/airmouse/tracking/imu/lsm6ds3tr_c_reg.c b/airmouse/tracking/imu/lsm6ds3tr_c_reg.c deleted file mode 100644 index 9f1890d2cad..00000000000 --- a/airmouse/tracking/imu/lsm6ds3tr_c_reg.c +++ /dev/null @@ -1,7105 +0,0 @@ -/** - ****************************************************************************** - * @file lsm6ds3tr_c_reg.c - * @author Sensors Software Solution Team - * @brief LSM6DS3TR_C driver file - ****************************************************************************** - * @attention - * - *

© Copyright (c) 2021 STMicroelectronics. - * All rights reserved.

- * - * This software component is licensed by ST under BSD 3-Clause license, - * the "License"; You may not use this file except in compliance with the - * License. You may obtain a copy of the License at: - * opensource.org/licenses/BSD-3-Clause - * - ****************************************************************************** - */ - -#include "lsm6ds3tr_c_reg.h" - -/** - * @defgroup LSM6DS3TR_C - * @brief This file provides a set of functions needed to drive the - * lsm6ds3tr_c enanced inertial module. - * @{ - * - */ - -/** - * @defgroup LSM6DS3TR_C_interfaces_functions - * @brief This section provide a set of functions used to read and - * write a generic register of the device. - * MANDATORY: return 0 -> no Error. - * @{ - * - */ - -/** - * @brief Read generic device register - * - * @param ctx read / write interface definitions(ptr) - * @param reg register to read - * @param data pointer to buffer that store the data read(ptr) - * @param len number of consecutive register to read - * @retval interface status (MANDATORY: return 0 -> no Error) - * - */ -int32_t lsm6ds3tr_c_read_reg(stmdev_ctx_t* ctx, uint8_t reg, uint8_t* data, uint16_t len) { - int32_t ret; - - ret = ctx->read_reg(ctx->handle, reg, data, len); - - return ret; -} - -/** - * @brief Write generic device register - * - * @param ctx read / write interface definitions(ptr) - * @param reg register to write - * @param data pointer to data to write in register reg(ptr) - * @param len number of consecutive register to write - * @retval interface status (MANDATORY: return 0 -> no Error) - * - */ -int32_t lsm6ds3tr_c_write_reg(stmdev_ctx_t* ctx, uint8_t reg, uint8_t* data, uint16_t len) { - int32_t ret; - - ret = ctx->write_reg(ctx->handle, reg, data, len); - - return ret; -} - -/** - * @} - * - */ - -/** - * @defgroup LSM6DS3TR_C_Sensitivity - * @brief These functions convert raw-data into engineering units. - * @{ - * - */ - -float_t lsm6ds3tr_c_from_fs2g_to_mg(int16_t lsb) { - return ((float_t)lsb * 0.061f); -} - -float_t lsm6ds3tr_c_from_fs4g_to_mg(int16_t lsb) { - return ((float_t)lsb * 0.122f); -} - -float_t lsm6ds3tr_c_from_fs8g_to_mg(int16_t lsb) { - return ((float_t)lsb * 0.244f); -} - -float_t lsm6ds3tr_c_from_fs16g_to_mg(int16_t lsb) { - return ((float_t)lsb * 0.488f); -} - -float_t lsm6ds3tr_c_from_fs125dps_to_mdps(int16_t lsb) { - return ((float_t)lsb * 4.375f); -} - -float_t lsm6ds3tr_c_from_fs250dps_to_mdps(int16_t lsb) { - return ((float_t)lsb * 8.750f); -} - -float_t lsm6ds3tr_c_from_fs500dps_to_mdps(int16_t lsb) { - return ((float_t)lsb * 17.50f); -} - -float_t lsm6ds3tr_c_from_fs1000dps_to_mdps(int16_t lsb) { - return ((float_t)lsb * 35.0f); -} - -float_t lsm6ds3tr_c_from_fs2000dps_to_mdps(int16_t lsb) { - return ((float_t)lsb * 70.0f); -} - -float_t lsm6ds3tr_c_from_lsb_to_celsius(int16_t lsb) { - return (((float_t)lsb / 256.0f) + 25.0f); -} - -/** - * @} - * - */ - -/** - * @defgroup LSM6DS3TR_C_data_generation - * @brief This section groups all the functions concerning data - * generation - * @{ - * - */ - -/** - * @brief Accelerometer full-scale selection.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of fs_xl in reg CTRL1_XL - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_xl_full_scale_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_fs_xl_t val) { - lsm6ds3tr_c_ctrl1_xl_t ctrl1_xl; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL1_XL, (uint8_t*)&ctrl1_xl, 1); - - if(ret == 0) { - ctrl1_xl.fs_xl = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL1_XL, (uint8_t*)&ctrl1_xl, 1); - } - - return ret; -} - -/** - * @brief Accelerometer full-scale selection.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of fs_xl in reg CTRL1_XL - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_xl_full_scale_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_fs_xl_t* val) { - lsm6ds3tr_c_ctrl1_xl_t ctrl1_xl; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL1_XL, (uint8_t*)&ctrl1_xl, 1); - - switch(ctrl1_xl.fs_xl) { - case LSM6DS3TR_C_2g: - *val = LSM6DS3TR_C_2g; - break; - - case LSM6DS3TR_C_16g: - *val = LSM6DS3TR_C_16g; - break; - - case LSM6DS3TR_C_4g: - *val = LSM6DS3TR_C_4g; - break; - - case LSM6DS3TR_C_8g: - *val = LSM6DS3TR_C_8g; - break; - - default: - *val = LSM6DS3TR_C_XL_FS_ND; - break; - } - - return ret; -} - -/** - * @brief Accelerometer data rate selection.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of odr_xl in reg CTRL1_XL - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_xl_data_rate_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_odr_xl_t val) { - lsm6ds3tr_c_ctrl1_xl_t ctrl1_xl; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL1_XL, (uint8_t*)&ctrl1_xl, 1); - - if(ret == 0) { - ctrl1_xl.odr_xl = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL1_XL, (uint8_t*)&ctrl1_xl, 1); - } - - return ret; -} - -/** - * @brief Accelerometer data rate selection.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of odr_xl in reg CTRL1_XL - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_xl_data_rate_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_odr_xl_t* val) { - lsm6ds3tr_c_ctrl1_xl_t ctrl1_xl; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL1_XL, (uint8_t*)&ctrl1_xl, 1); - - switch(ctrl1_xl.odr_xl) { - case LSM6DS3TR_C_XL_ODR_OFF: - *val = LSM6DS3TR_C_XL_ODR_OFF; - break; - - case LSM6DS3TR_C_XL_ODR_12Hz5: - *val = LSM6DS3TR_C_XL_ODR_12Hz5; - break; - - case LSM6DS3TR_C_XL_ODR_26Hz: - *val = LSM6DS3TR_C_XL_ODR_26Hz; - break; - - case LSM6DS3TR_C_XL_ODR_52Hz: - *val = LSM6DS3TR_C_XL_ODR_52Hz; - break; - - case LSM6DS3TR_C_XL_ODR_104Hz: - *val = LSM6DS3TR_C_XL_ODR_104Hz; - break; - - case LSM6DS3TR_C_XL_ODR_208Hz: - *val = LSM6DS3TR_C_XL_ODR_208Hz; - break; - - case LSM6DS3TR_C_XL_ODR_416Hz: - *val = LSM6DS3TR_C_XL_ODR_416Hz; - break; - - case LSM6DS3TR_C_XL_ODR_833Hz: - *val = LSM6DS3TR_C_XL_ODR_833Hz; - break; - - case LSM6DS3TR_C_XL_ODR_1k66Hz: - *val = LSM6DS3TR_C_XL_ODR_1k66Hz; - break; - - case LSM6DS3TR_C_XL_ODR_3k33Hz: - *val = LSM6DS3TR_C_XL_ODR_3k33Hz; - break; - - case LSM6DS3TR_C_XL_ODR_6k66Hz: - *val = LSM6DS3TR_C_XL_ODR_6k66Hz; - break; - - case LSM6DS3TR_C_XL_ODR_1Hz6: - *val = LSM6DS3TR_C_XL_ODR_1Hz6; - break; - - default: - *val = LSM6DS3TR_C_XL_ODR_ND; - break; - } - - return ret; -} - -/** - * @brief Gyroscope chain full-scale selection.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of fs_g in reg CTRL2_G - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_gy_full_scale_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_fs_g_t val) { - lsm6ds3tr_c_ctrl2_g_t ctrl2_g; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL2_G, (uint8_t*)&ctrl2_g, 1); - - if(ret == 0) { - ctrl2_g.fs_g = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL2_G, (uint8_t*)&ctrl2_g, 1); - } - - return ret; -} - -/** - * @brief Gyroscope chain full-scale selection.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of fs_g in reg CTRL2_G - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_gy_full_scale_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_fs_g_t* val) { - lsm6ds3tr_c_ctrl2_g_t ctrl2_g; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL2_G, (uint8_t*)&ctrl2_g, 1); - - switch(ctrl2_g.fs_g) { - case LSM6DS3TR_C_250dps: - *val = LSM6DS3TR_C_250dps; - break; - - case LSM6DS3TR_C_125dps: - *val = LSM6DS3TR_C_125dps; - break; - - case LSM6DS3TR_C_500dps: - *val = LSM6DS3TR_C_500dps; - break; - - case LSM6DS3TR_C_1000dps: - *val = LSM6DS3TR_C_1000dps; - break; - - case LSM6DS3TR_C_2000dps: - *val = LSM6DS3TR_C_2000dps; - break; - - default: - *val = LSM6DS3TR_C_GY_FS_ND; - break; - } - - return ret; -} - -/** - * @brief Gyroscope data rate selection.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of odr_g in reg CTRL2_G - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_gy_data_rate_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_odr_g_t val) { - lsm6ds3tr_c_ctrl2_g_t ctrl2_g; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL2_G, (uint8_t*)&ctrl2_g, 1); - - if(ret == 0) { - ctrl2_g.odr_g = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL2_G, (uint8_t*)&ctrl2_g, 1); - } - - return ret; -} - -/** - * @brief Gyroscope data rate selection.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of odr_g in reg CTRL2_G - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_gy_data_rate_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_odr_g_t* val) { - lsm6ds3tr_c_ctrl2_g_t ctrl2_g; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL2_G, (uint8_t*)&ctrl2_g, 1); - - switch(ctrl2_g.odr_g) { - case LSM6DS3TR_C_GY_ODR_OFF: - *val = LSM6DS3TR_C_GY_ODR_OFF; - break; - - case LSM6DS3TR_C_GY_ODR_12Hz5: - *val = LSM6DS3TR_C_GY_ODR_12Hz5; - break; - - case LSM6DS3TR_C_GY_ODR_26Hz: - *val = LSM6DS3TR_C_GY_ODR_26Hz; - break; - - case LSM6DS3TR_C_GY_ODR_52Hz: - *val = LSM6DS3TR_C_GY_ODR_52Hz; - break; - - case LSM6DS3TR_C_GY_ODR_104Hz: - *val = LSM6DS3TR_C_GY_ODR_104Hz; - break; - - case LSM6DS3TR_C_GY_ODR_208Hz: - *val = LSM6DS3TR_C_GY_ODR_208Hz; - break; - - case LSM6DS3TR_C_GY_ODR_416Hz: - *val = LSM6DS3TR_C_GY_ODR_416Hz; - break; - - case LSM6DS3TR_C_GY_ODR_833Hz: - *val = LSM6DS3TR_C_GY_ODR_833Hz; - break; - - case LSM6DS3TR_C_GY_ODR_1k66Hz: - *val = LSM6DS3TR_C_GY_ODR_1k66Hz; - break; - - case LSM6DS3TR_C_GY_ODR_3k33Hz: - *val = LSM6DS3TR_C_GY_ODR_3k33Hz; - break; - - case LSM6DS3TR_C_GY_ODR_6k66Hz: - *val = LSM6DS3TR_C_GY_ODR_6k66Hz; - break; - - default: - *val = LSM6DS3TR_C_GY_ODR_ND; - break; - } - - return ret; -} - -/** - * @brief Block data update.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of bdu in reg CTRL3_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_block_data_update_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_ctrl3_c_t ctrl3_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, (uint8_t*)&ctrl3_c, 1); - - if(ret == 0) { - ctrl3_c.bdu = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL3_C, (uint8_t*)&ctrl3_c, 1); - } - - return ret; -} - -/** - * @brief Block data update.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of bdu in reg CTRL3_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_block_data_update_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_ctrl3_c_t ctrl3_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, (uint8_t*)&ctrl3_c, 1); - *val = ctrl3_c.bdu; - - return ret; -} - -/** - * @brief Weight of XL user offset bits of registers - * X_OFS_USR(73h), Y_OFS_USR(74h), Z_OFS_USR(75h).[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of usr_off_w in reg CTRL6_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_xl_offset_weight_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_usr_off_w_t val) { - lsm6ds3tr_c_ctrl6_c_t ctrl6_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL6_C, (uint8_t*)&ctrl6_c, 1); - - if(ret == 0) { - ctrl6_c.usr_off_w = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL6_C, (uint8_t*)&ctrl6_c, 1); - } - - return ret; -} - -/** - * @brief Weight of XL user offset bits of registers - * X_OFS_USR(73h), Y_OFS_USR(74h), Z_OFS_USR(75h).[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of usr_off_w in reg CTRL6_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_xl_offset_weight_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_usr_off_w_t* val) { - lsm6ds3tr_c_ctrl6_c_t ctrl6_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL6_C, (uint8_t*)&ctrl6_c, 1); - - switch(ctrl6_c.usr_off_w) { - case LSM6DS3TR_C_LSb_1mg: - *val = LSM6DS3TR_C_LSb_1mg; - break; - - case LSM6DS3TR_C_LSb_16mg: - *val = LSM6DS3TR_C_LSb_16mg; - break; - - default: - *val = LSM6DS3TR_C_WEIGHT_ND; - break; - } - - return ret; -} - -/** - * @brief High-performance operating mode for accelerometer[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of xl_hm_mode in reg CTRL6_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_xl_power_mode_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_xl_hm_mode_t val) { - lsm6ds3tr_c_ctrl6_c_t ctrl6_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL6_C, (uint8_t*)&ctrl6_c, 1); - - if(ret == 0) { - ctrl6_c.xl_hm_mode = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL6_C, (uint8_t*)&ctrl6_c, 1); - } - - return ret; -} - -/** - * @brief High-performance operating mode for accelerometer.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of xl_hm_mode in reg CTRL6_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_xl_power_mode_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_xl_hm_mode_t* val) { - lsm6ds3tr_c_ctrl6_c_t ctrl6_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL6_C, (uint8_t*)&ctrl6_c, 1); - - switch(ctrl6_c.xl_hm_mode) { - case LSM6DS3TR_C_XL_HIGH_PERFORMANCE: - *val = LSM6DS3TR_C_XL_HIGH_PERFORMANCE; - break; - - case LSM6DS3TR_C_XL_NORMAL: - *val = LSM6DS3TR_C_XL_NORMAL; - break; - - default: - *val = LSM6DS3TR_C_XL_PW_MODE_ND; - break; - } - - return ret; -} - -/** - * @brief Source register rounding function on WAKE_UP_SRC (1Bh), - * TAP_SRC (1Ch), D6D_SRC (1Dh), STATUS_REG (1Eh) and - * FUNC_SRC1 (53h) registers in the primary interface.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of rounding_status in reg CTRL7_G - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_rounding_on_status_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_rounding_status_t val) { - lsm6ds3tr_c_ctrl7_g_t ctrl7_g; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL7_G, (uint8_t*)&ctrl7_g, 1); - - if(ret == 0) { - ctrl7_g.rounding_status = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL7_G, (uint8_t*)&ctrl7_g, 1); - } - - return ret; -} - -/** - * @brief Source register rounding function on WAKE_UP_SRC (1Bh), - * TAP_SRC (1Ch), D6D_SRC (1Dh), STATUS_REG (1Eh) and - * FUNC_SRC1 (53h) registers in the primary interface.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of rounding_status in reg CTRL7_G - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_rounding_on_status_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_rounding_status_t* val) { - lsm6ds3tr_c_ctrl7_g_t ctrl7_g; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL7_G, (uint8_t*)&ctrl7_g, 1); - - switch(ctrl7_g.rounding_status) { - case LSM6DS3TR_C_STAT_RND_DISABLE: - *val = LSM6DS3TR_C_STAT_RND_DISABLE; - break; - - case LSM6DS3TR_C_STAT_RND_ENABLE: - *val = LSM6DS3TR_C_STAT_RND_ENABLE; - break; - - default: - *val = LSM6DS3TR_C_STAT_RND_ND; - break; - } - - return ret; -} - -/** - * @brief High-performance operating mode disable for gyroscope.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of g_hm_mode in reg CTRL7_G - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_gy_power_mode_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_g_hm_mode_t val) { - lsm6ds3tr_c_ctrl7_g_t ctrl7_g; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL7_G, (uint8_t*)&ctrl7_g, 1); - - if(ret == 0) { - ctrl7_g.g_hm_mode = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL7_G, (uint8_t*)&ctrl7_g, 1); - } - - return ret; -} - -/** - * @brief High-performance operating mode disable for gyroscope.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of g_hm_mode in reg CTRL7_G - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_gy_power_mode_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_g_hm_mode_t* val) { - lsm6ds3tr_c_ctrl7_g_t ctrl7_g; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL7_G, (uint8_t*)&ctrl7_g, 1); - - switch(ctrl7_g.g_hm_mode) { - case LSM6DS3TR_C_GY_HIGH_PERFORMANCE: - *val = LSM6DS3TR_C_GY_HIGH_PERFORMANCE; - break; - - case LSM6DS3TR_C_GY_NORMAL: - *val = LSM6DS3TR_C_GY_NORMAL; - break; - - default: - *val = LSM6DS3TR_C_GY_PW_MODE_ND; - break; - } - - return ret; -} - -/** - * @brief Read all the interrupt/status flag of the device.[get] - * - * @param ctx Read / write interface definitions - * @param val WAKE_UP_SRC, TAP_SRC, D6D_SRC, STATUS_REG, - * FUNC_SRC1, FUNC_SRC2, WRIST_TILT_IA, A_WRIST_TILT_Mask - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_all_sources_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_all_sources_t* val) { - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_SRC, (uint8_t*)&(val->wake_up_src), 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_SRC, (uint8_t*)&(val->tap_src), 1); - } - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_D6D_SRC, (uint8_t*)&(val->d6d_src), 1); - } - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_STATUS_REG, (uint8_t*)&(val->status_reg), 1); - } - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FUNC_SRC1, (uint8_t*)&(val->func_src1), 1); - } - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FUNC_SRC2, (uint8_t*)&(val->func_src2), 1); - } - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg( - ctx, LSM6DS3TR_C_WRIST_TILT_IA, (uint8_t*)&(val->wrist_tilt_ia), 1); - } - - if(ret == 0) { - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_B); - } - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg( - ctx, LSM6DS3TR_C_A_WRIST_TILT_MASK, (uint8_t*)&(val->a_wrist_tilt_mask), 1); - } - - if(ret == 0) { - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - - return ret; -} -/** - * @brief The STATUS_REG register is read by the primary interface[get] - * - * @param ctx Read / write interface definitions - * @param val Registers STATUS_REG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_status_reg_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_status_reg_t* val) { - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_STATUS_REG, (uint8_t*)val, 1); - - return ret; -} - -/** - * @brief Accelerometer new data available.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of xlda in reg STATUS_REG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_xl_flag_data_ready_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_status_reg_t status_reg; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_STATUS_REG, (uint8_t*)&status_reg, 1); - *val = status_reg.xlda; - - return ret; -} - -/** - * @brief Gyroscope new data available.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of gda in reg STATUS_REG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_gy_flag_data_ready_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_status_reg_t status_reg; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_STATUS_REG, (uint8_t*)&status_reg, 1); - *val = status_reg.gda; - - return ret; -} - -/** - * @brief Temperature new data available.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of tda in reg STATUS_REG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_temp_flag_data_ready_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_status_reg_t status_reg; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_STATUS_REG, (uint8_t*)&status_reg, 1); - *val = status_reg.tda; - - return ret; -} - -/** - * @brief Accelerometer axis user offset correction expressed in two’s - * complement, weight depends on USR_OFF_W in CTRL6_C. - * The value must be in the range [-127 127].[set] - * - * @param ctx Read / write interface definitions - * @param buff Buffer that contains data to write - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_xl_usr_offset_set(stmdev_ctx_t* ctx, uint8_t* buff) { - int32_t ret; - - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_X_OFS_USR, buff, 3); - - return ret; -} - -/** - * @brief Accelerometer axis user offset correction xpressed in two’s - * complement, weight depends on USR_OFF_W in CTRL6_C. - * The value must be in the range [-127 127].[get] - * - * @param ctx Read / write interface definitions - * @param buff Buffer that stores data read - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_xl_usr_offset_get(stmdev_ctx_t* ctx, uint8_t* buff) { - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_X_OFS_USR, buff, 3); - - return ret; -} - -/** - * @} - * - */ - -/** - * @defgroup LSM6DS3TR_C_Timestamp - * @brief This section groups all the functions that manage the - * timestamp generation. - * @{ - * - */ - -/** - * @brief Enable timestamp count. The count is saved in TIMESTAMP0_REG (40h), - * TIMESTAMP1_REG (41h) and TIMESTAMP2_REG (42h).[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of timer_en in reg CTRL10_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_timestamp_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_ctrl10_c_t ctrl10_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C, (uint8_t*)&ctrl10_c, 1); - - if(ret == 0) { - ctrl10_c.timer_en = val; - - if(val != 0x00U) { - ctrl10_c.func_en = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL10_C, (uint8_t*)&ctrl10_c, 1); - } - } - - return ret; -} - -/** - * @brief Enable timestamp count. The count is saved in TIMESTAMP0_REG (40h), - * TIMESTAMP1_REG (41h) and TIMESTAMP2_REG (42h).[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of timer_en in reg CTRL10_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_timestamp_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_ctrl10_c_t ctrl10_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C, (uint8_t*)&ctrl10_c, 1); - *val = ctrl10_c.timer_en; - - return ret; -} - -/** - * @brief Timestamp register resolution setting. - * Configuration of this bit affects - * TIMESTAMP0_REG(40h), TIMESTAMP1_REG(41h), - * TIMESTAMP2_REG(42h), STEP_TIMESTAMP_L(49h), - * STEP_TIMESTAMP_H(4Ah) and - * STEP_COUNT_DELTA(15h) registers.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of timer_hr in reg WAKE_UP_DUR - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_timestamp_res_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_timer_hr_t val) { - lsm6ds3tr_c_wake_up_dur_t wake_up_dur; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR, (uint8_t*)&wake_up_dur, 1); - - if(ret == 0) { - wake_up_dur.timer_hr = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR, (uint8_t*)&wake_up_dur, 1); - } - - return ret; -} - -/** - * @brief Timestamp register resolution setting. - * Configuration of this bit affects - * TIMESTAMP0_REG(40h), TIMESTAMP1_REG(41h), - * TIMESTAMP2_REG(42h), STEP_TIMESTAMP_L(49h), - * STEP_TIMESTAMP_H(4Ah) and - * STEP_COUNT_DELTA(15h) registers.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of timer_hr in reg WAKE_UP_DUR - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_timestamp_res_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_timer_hr_t* val) { - lsm6ds3tr_c_wake_up_dur_t wake_up_dur; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR, (uint8_t*)&wake_up_dur, 1); - - switch(wake_up_dur.timer_hr) { - case LSM6DS3TR_C_LSB_6ms4: - *val = LSM6DS3TR_C_LSB_6ms4; - break; - - case LSM6DS3TR_C_LSB_25us: - *val = LSM6DS3TR_C_LSB_25us; - break; - - default: - *val = LSM6DS3TR_C_TS_RES_ND; - break; - } - - return ret; -} - -/** - * @} - * - */ - -/** - * @defgroup LSM6DS3TR_C_Dataoutput - * @brief This section groups all the data output functions. - * @{ - * - */ - -/** - * @brief Circular burst-mode (rounding) read from output registers - * through the primary interface.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of rounding in reg CTRL5_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_rounding_mode_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_rounding_t val) { - lsm6ds3tr_c_ctrl5_c_t ctrl5_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL5_C, (uint8_t*)&ctrl5_c, 1); - - if(ret == 0) { - ctrl5_c.rounding = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL5_C, (uint8_t*)&ctrl5_c, 1); - } - - return ret; -} - -/** - * @brief Circular burst-mode (rounding) read from output registers - * through the primary interface.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of rounding in reg CTRL5_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_rounding_mode_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_rounding_t* val) { - lsm6ds3tr_c_ctrl5_c_t ctrl5_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL5_C, (uint8_t*)&ctrl5_c, 1); - - switch(ctrl5_c.rounding) { - case LSM6DS3TR_C_ROUND_DISABLE: - *val = LSM6DS3TR_C_ROUND_DISABLE; - break; - - case LSM6DS3TR_C_ROUND_XL: - *val = LSM6DS3TR_C_ROUND_XL; - break; - - case LSM6DS3TR_C_ROUND_GY: - *val = LSM6DS3TR_C_ROUND_GY; - break; - - case LSM6DS3TR_C_ROUND_GY_XL: - *val = LSM6DS3TR_C_ROUND_GY_XL; - break; - - case LSM6DS3TR_C_ROUND_SH1_TO_SH6: - *val = LSM6DS3TR_C_ROUND_SH1_TO_SH6; - break; - - case LSM6DS3TR_C_ROUND_XL_SH1_TO_SH6: - *val = LSM6DS3TR_C_ROUND_XL_SH1_TO_SH6; - break; - - case LSM6DS3TR_C_ROUND_GY_XL_SH1_TO_SH12: - *val = LSM6DS3TR_C_ROUND_GY_XL_SH1_TO_SH12; - break; - - case LSM6DS3TR_C_ROUND_GY_XL_SH1_TO_SH6: - *val = LSM6DS3TR_C_ROUND_GY_XL_SH1_TO_SH6; - break; - - default: - *val = LSM6DS3TR_C_ROUND_OUT_ND; - break; - } - - return ret; -} - -/** - * @brief Temperature data output register (r). L and H registers together - * express a 16-bit word in two’s complement.[get] - * - * @param ctx Read / write interface definitions - * @param buff Buffer that stores data read - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_temperature_raw_get(stmdev_ctx_t* ctx, int16_t* val) { - uint8_t buff[2]; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_OUT_TEMP_L, buff, 2); - *val = (int16_t)buff[1]; - *val = (*val * 256) + (int16_t)buff[0]; - - return ret; -} - -/** - * @brief Angular rate sensor. The value is expressed as a 16-bit word in - * two’s complement.[get] - * - * @param ctx Read / write interface definitions - * @param buff Buffer that stores data read - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_angular_rate_raw_get(stmdev_ctx_t* ctx, int16_t* val) { - uint8_t buff[6]; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_OUTX_L_G, buff, 6); - val[0] = (int16_t)buff[1]; - val[0] = (val[0] * 256) + (int16_t)buff[0]; - val[1] = (int16_t)buff[3]; - val[1] = (val[1] * 256) + (int16_t)buff[2]; - val[2] = (int16_t)buff[5]; - val[2] = (val[2] * 256) + (int16_t)buff[4]; - - return ret; -} - -/** - * @brief Linear acceleration output register. The value is expressed - * as a 16-bit word in two’s complement.[get] - * - * @param ctx Read / write interface definitions - * @param buff Buffer that stores data read - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_acceleration_raw_get(stmdev_ctx_t* ctx, int16_t* val) { - uint8_t buff[6]; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_OUTX_L_XL, buff, 6); - val[0] = (int16_t)buff[1]; - val[0] = (val[0] * 256) + (int16_t)buff[0]; - val[1] = (int16_t)buff[3]; - val[1] = (val[1] * 256) + (int16_t)buff[2]; - val[2] = (int16_t)buff[5]; - val[2] = (val[2] * 256) + (int16_t)buff[4]; - - return ret; -} - -/** - * @brief External magnetometer raw data.[get] - * - * @param ctx Read / write interface definitions - * @param buff Buffer that stores data read - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_mag_calibrated_raw_get(stmdev_ctx_t* ctx, int16_t* val) { - uint8_t buff[6]; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_OUT_MAG_RAW_X_L, buff, 6); - val[0] = (int16_t)buff[1]; - val[0] = (val[0] * 256) + (int16_t)buff[0]; - val[1] = (int16_t)buff[3]; - val[1] = (val[1] * 256) + (int16_t)buff[2]; - val[2] = (int16_t)buff[5]; - val[2] = (val[2] * 256) + (int16_t)buff[4]; - - return ret; -} - -/** - * @brief Read data in FIFO.[get] - * - * @param ctx Read / write interface definitions - * @param buffer Data buffer to store FIFO data. - * @param len Number of data to read from FIFO. - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_fifo_raw_data_get(stmdev_ctx_t* ctx, uint8_t* buffer, uint8_t len) { - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_DATA_OUT_L, buffer, len); - - return ret; -} - -/** - * @} - * - */ - -/** - * @defgroup LSM6DS3TR_C_common - * @brief This section groups common useful functions. - * @{ - * - */ - -/** - * @brief Enable access to the embedded functions/sensor hub - * configuration registers[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of func_cfg_en in reg FUNC_CFG_ACCESS - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_mem_bank_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_func_cfg_en_t val) { - lsm6ds3tr_c_func_cfg_access_t func_cfg_access; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FUNC_CFG_ACCESS, (uint8_t*)&func_cfg_access, 1); - - if(ret == 0) { - func_cfg_access.func_cfg_en = (uint8_t)val; - ret = - lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FUNC_CFG_ACCESS, (uint8_t*)&func_cfg_access, 1); - } - - return ret; -} - -/** - * @brief Enable access to the embedded functions/sensor hub configuration - * registers[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of func_cfg_en in reg FUNC_CFG_ACCESS - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_mem_bank_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_func_cfg_en_t* val) { - lsm6ds3tr_c_func_cfg_access_t func_cfg_access; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FUNC_CFG_ACCESS, (uint8_t*)&func_cfg_access, 1); - - switch(func_cfg_access.func_cfg_en) { - case LSM6DS3TR_C_USER_BANK: - *val = LSM6DS3TR_C_USER_BANK; - break; - - case LSM6DS3TR_C_BANK_B: - *val = LSM6DS3TR_C_BANK_B; - break; - - default: - *val = LSM6DS3TR_C_BANK_ND; - break; - } - - return ret; -} - -/** - * @brief Data-ready pulsed / letched mode[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of drdy_pulsed in reg DRDY_PULSE_CFG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_data_ready_mode_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_drdy_pulsed_g_t val) { - lsm6ds3tr_c_drdy_pulse_cfg_g_t drdy_pulse_cfg_g; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_DRDY_PULSE_CFG_G, (uint8_t*)&drdy_pulse_cfg_g, 1); - - if(ret == 0) { - drdy_pulse_cfg_g.drdy_pulsed = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg( - ctx, LSM6DS3TR_C_DRDY_PULSE_CFG_G, (uint8_t*)&drdy_pulse_cfg_g, 1); - } - - return ret; -} - -/** - * @brief Data-ready pulsed / letched mode[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of drdy_pulsed in reg DRDY_PULSE_CFG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_data_ready_mode_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_drdy_pulsed_g_t* val) { - lsm6ds3tr_c_drdy_pulse_cfg_g_t drdy_pulse_cfg_g; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_DRDY_PULSE_CFG_G, (uint8_t*)&drdy_pulse_cfg_g, 1); - - switch(drdy_pulse_cfg_g.drdy_pulsed) { - case LSM6DS3TR_C_DRDY_LATCHED: - *val = LSM6DS3TR_C_DRDY_LATCHED; - break; - - case LSM6DS3TR_C_DRDY_PULSED: - *val = LSM6DS3TR_C_DRDY_PULSED; - break; - - default: - *val = LSM6DS3TR_C_DRDY_ND; - break; - } - - return ret; -} - -/** - * @brief DeviceWhoamI.[get] - * - * @param ctx Read / write interface definitions - * @param buff Buffer that stores data read - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_device_id_get(stmdev_ctx_t* ctx, uint8_t* buff) { - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WHO_AM_I, buff, 1); - - return ret; -} - -/** - * @brief Software reset. Restore the default values in user registers[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of sw_reset in reg CTRL3_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_reset_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_ctrl3_c_t ctrl3_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, (uint8_t*)&ctrl3_c, 1); - - if(ret == 0) { - ctrl3_c.sw_reset = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL3_C, (uint8_t*)&ctrl3_c, 1); - } - - return ret; -} - -/** - * @brief Software reset. Restore the default values in user registers[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of sw_reset in reg CTRL3_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_reset_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_ctrl3_c_t ctrl3_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, (uint8_t*)&ctrl3_c, 1); - *val = ctrl3_c.sw_reset; - - return ret; -} - -/** - * @brief Big/Little Endian Data selection.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of ble in reg CTRL3_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_data_format_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_ble_t val) { - lsm6ds3tr_c_ctrl3_c_t ctrl3_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, (uint8_t*)&ctrl3_c, 1); - - if(ret == 0) { - ctrl3_c.ble = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL3_C, (uint8_t*)&ctrl3_c, 1); - } - - return ret; -} - -/** - * @brief Big/Little Endian Data selection.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of ble in reg CTRL3_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_data_format_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_ble_t* val) { - lsm6ds3tr_c_ctrl3_c_t ctrl3_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, (uint8_t*)&ctrl3_c, 1); - - switch(ctrl3_c.ble) { - case LSM6DS3TR_C_LSB_AT_LOW_ADD: - *val = LSM6DS3TR_C_LSB_AT_LOW_ADD; - break; - - case LSM6DS3TR_C_MSB_AT_LOW_ADD: - *val = LSM6DS3TR_C_MSB_AT_LOW_ADD; - break; - - default: - *val = LSM6DS3TR_C_DATA_FMT_ND; - break; - } - - return ret; -} - -/** - * @brief Register address automatically incremented during a multiple byte - * access with a serial interface.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of if_inc in reg CTRL3_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_auto_increment_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_ctrl3_c_t ctrl3_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, (uint8_t*)&ctrl3_c, 1); - - if(ret == 0) { - ctrl3_c.if_inc = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL3_C, (uint8_t*)&ctrl3_c, 1); - } - - return ret; -} - -/** - * @brief Register address automatically incremented during a multiple byte - * access with a serial interface.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of if_inc in reg CTRL3_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_auto_increment_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_ctrl3_c_t ctrl3_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, (uint8_t*)&ctrl3_c, 1); - *val = ctrl3_c.if_inc; - - return ret; -} - -/** - * @brief Reboot memory content. Reload the calibration parameters.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of boot in reg CTRL3_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_boot_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_ctrl3_c_t ctrl3_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, (uint8_t*)&ctrl3_c, 1); - - if(ret == 0) { - ctrl3_c.boot = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL3_C, (uint8_t*)&ctrl3_c, 1); - } - - return ret; -} - -/** - * @brief Reboot memory content. Reload the calibration parameters.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of boot in reg CTRL3_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_boot_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_ctrl3_c_t ctrl3_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, (uint8_t*)&ctrl3_c, 1); - *val = ctrl3_c.boot; - - return ret; -} - -/** - * @brief Linear acceleration sensor self-test enable.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of st_xl in reg CTRL5_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_xl_self_test_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_st_xl_t val) { - lsm6ds3tr_c_ctrl5_c_t ctrl5_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL5_C, (uint8_t*)&ctrl5_c, 1); - - if(ret == 0) { - ctrl5_c.st_xl = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL5_C, (uint8_t*)&ctrl5_c, 1); - } - - return ret; -} - -/** - * @brief Linear acceleration sensor self-test enable.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of st_xl in reg CTRL5_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_xl_self_test_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_st_xl_t* val) { - lsm6ds3tr_c_ctrl5_c_t ctrl5_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL5_C, (uint8_t*)&ctrl5_c, 1); - - switch(ctrl5_c.st_xl) { - case LSM6DS3TR_C_XL_ST_DISABLE: - *val = LSM6DS3TR_C_XL_ST_DISABLE; - break; - - case LSM6DS3TR_C_XL_ST_POSITIVE: - *val = LSM6DS3TR_C_XL_ST_POSITIVE; - break; - - case LSM6DS3TR_C_XL_ST_NEGATIVE: - *val = LSM6DS3TR_C_XL_ST_NEGATIVE; - break; - - default: - *val = LSM6DS3TR_C_XL_ST_ND; - break; - } - - return ret; -} - -/** - * @brief Angular rate sensor self-test enable.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of st_g in reg CTRL5_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_gy_self_test_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_st_g_t val) { - lsm6ds3tr_c_ctrl5_c_t ctrl5_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL5_C, (uint8_t*)&ctrl5_c, 1); - - if(ret == 0) { - ctrl5_c.st_g = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL5_C, (uint8_t*)&ctrl5_c, 1); - } - - return ret; -} - -/** - * @brief Angular rate sensor self-test enable.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of st_g in reg CTRL5_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_gy_self_test_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_st_g_t* val) { - lsm6ds3tr_c_ctrl5_c_t ctrl5_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL5_C, (uint8_t*)&ctrl5_c, 1); - - switch(ctrl5_c.st_g) { - case LSM6DS3TR_C_GY_ST_DISABLE: - *val = LSM6DS3TR_C_GY_ST_DISABLE; - break; - - case LSM6DS3TR_C_GY_ST_POSITIVE: - *val = LSM6DS3TR_C_GY_ST_POSITIVE; - break; - - case LSM6DS3TR_C_GY_ST_NEGATIVE: - *val = LSM6DS3TR_C_GY_ST_NEGATIVE; - break; - - default: - *val = LSM6DS3TR_C_GY_ST_ND; - break; - } - - return ret; -} - -/** - * @} - * - */ - -/** - * @defgroup LSM6DS3TR_C_filters - * @brief This section group all the functions concerning the filters - * configuration that impact both accelerometer and gyro. - * @{ - * - */ - -/** - * @brief Mask DRDY on pin (both XL & Gyro) until filter settling ends - * (XL and Gyro independently masked).[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of drdy_mask in reg CTRL4_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_filter_settling_mask_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_ctrl4_c_t ctrl4_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C, (uint8_t*)&ctrl4_c, 1); - - if(ret == 0) { - ctrl4_c.drdy_mask = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL4_C, (uint8_t*)&ctrl4_c, 1); - } - - return ret; -} - -/** - * @brief Mask DRDY on pin (both XL & Gyro) until filter settling ends - * (XL and Gyro independently masked).[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of drdy_mask in reg CTRL4_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_filter_settling_mask_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_ctrl4_c_t ctrl4_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C, (uint8_t*)&ctrl4_c, 1); - *val = ctrl4_c.drdy_mask; - - return ret; -} - -/** - * @brief HPF or SLOPE filter selection on wake-up and Activity/Inactivity - * functions.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of slope_fds in reg TAP_CFG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_xl_hp_path_internal_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_slope_fds_t val) { - lsm6ds3tr_c_tap_cfg_t tap_cfg; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG, (uint8_t*)&tap_cfg, 1); - - if(ret == 0) { - tap_cfg.slope_fds = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_CFG, (uint8_t*)&tap_cfg, 1); - } - - return ret; -} - -/** - * @brief HPF or SLOPE filter selection on wake-up and Activity/Inactivity - * functions.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of slope_fds in reg TAP_CFG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_xl_hp_path_internal_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_slope_fds_t* val) { - lsm6ds3tr_c_tap_cfg_t tap_cfg; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG, (uint8_t*)&tap_cfg, 1); - - switch(tap_cfg.slope_fds) { - case LSM6DS3TR_C_USE_SLOPE: - *val = LSM6DS3TR_C_USE_SLOPE; - break; - - case LSM6DS3TR_C_USE_HPF: - *val = LSM6DS3TR_C_USE_HPF; - break; - - default: - *val = LSM6DS3TR_C_HP_PATH_ND; - break; - } - - return ret; -} - -/** - * @} - * - */ - -/** - * @defgroup LSM6DS3TR_C_accelerometer_filters - * @brief This section group all the functions concerning the filters - * configuration that impact accelerometer in every mode. - * @{ - * - */ - -/** - * @brief Accelerometer analog chain bandwidth selection (only for - * accelerometer ODR ≥ 1.67 kHz).[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of bw0_xl in reg CTRL1_XL - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_xl_filter_analog_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_bw0_xl_t val) { - lsm6ds3tr_c_ctrl1_xl_t ctrl1_xl; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL1_XL, (uint8_t*)&ctrl1_xl, 1); - - if(ret == 0) { - ctrl1_xl.bw0_xl = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL1_XL, (uint8_t*)&ctrl1_xl, 1); - } - - return ret; -} - -/** - * @brief Accelerometer analog chain bandwidth selection (only for - * accelerometer ODR ≥ 1.67 kHz).[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of bw0_xl in reg CTRL1_XL - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_xl_filter_analog_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_bw0_xl_t* val) { - lsm6ds3tr_c_ctrl1_xl_t ctrl1_xl; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL1_XL, (uint8_t*)&ctrl1_xl, 1); - - switch(ctrl1_xl.bw0_xl) { - case LSM6DS3TR_C_XL_ANA_BW_1k5Hz: - *val = LSM6DS3TR_C_XL_ANA_BW_1k5Hz; - break; - - case LSM6DS3TR_C_XL_ANA_BW_400Hz: - *val = LSM6DS3TR_C_XL_ANA_BW_400Hz; - break; - - default: - *val = LSM6DS3TR_C_XL_ANA_BW_ND; - break; - } - - return ret; -} - -/** - * @} - * - */ - -/** - * @defgroup LSM6DS3TR_C_accelerometer_filters - * @brief This section group all the functions concerning the filters - * configuration that impact accelerometer. - * @{ - * - */ - -/** - * @brief Accelerometer digital LPF (LPF1) bandwidth selection LPF2 is - * not used.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of lpf1_bw_sel in reg CTRL1_XL - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_xl_lp1_bandwidth_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_lpf1_bw_sel_t val) { - lsm6ds3tr_c_ctrl1_xl_t ctrl1_xl; - lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL1_XL, (uint8_t*)&ctrl1_xl, 1); - - if(ret == 0) { - ctrl1_xl.lpf1_bw_sel = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL1_XL, (uint8_t*)&ctrl1_xl, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL8_XL, (uint8_t*)&ctrl8_xl, 1); - - if(ret == 0) { - ctrl8_xl.lpf2_xl_en = 0; - ctrl8_xl.hp_slope_xl_en = 0; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL8_XL, (uint8_t*)&ctrl8_xl, 1); - } - } - } - - return ret; -} - -/** - * @brief Accelerometer digital LPF (LPF1) bandwidth selection LPF2 - * is not used.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of lpf1_bw_sel in reg CTRL1_XL - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_xl_lp1_bandwidth_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_lpf1_bw_sel_t* val) { - lsm6ds3tr_c_ctrl1_xl_t ctrl1_xl; - lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL8_XL, (uint8_t*)&ctrl8_xl, 1); - - if(ret == 0) { - if((ctrl8_xl.lpf2_xl_en != 0x00U) || (ctrl8_xl.hp_slope_xl_en != 0x00U)) { - *val = LSM6DS3TR_C_XL_LP1_NA; - } - - else { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL1_XL, (uint8_t*)&ctrl1_xl, 1); - - switch(ctrl1_xl.lpf1_bw_sel) { - case LSM6DS3TR_C_XL_LP1_ODR_DIV_2: - *val = LSM6DS3TR_C_XL_LP1_ODR_DIV_2; - break; - - case LSM6DS3TR_C_XL_LP1_ODR_DIV_4: - *val = LSM6DS3TR_C_XL_LP1_ODR_DIV_4; - break; - - default: - *val = LSM6DS3TR_C_XL_LP1_NA; - break; - } - } - } - - return ret; -} - -/** - * @brief LPF2 on outputs[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of input_composite in reg CTRL8_XL - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_xl_lp2_bandwidth_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_input_composite_t val) { - lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL8_XL, (uint8_t*)&ctrl8_xl, 1); - - if(ret == 0) { - ctrl8_xl.input_composite = ((uint8_t)val & 0x10U) >> 4; - ctrl8_xl.hpcf_xl = (uint8_t)val & 0x03U; - ctrl8_xl.lpf2_xl_en = 1; - ctrl8_xl.hp_slope_xl_en = 0; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL8_XL, (uint8_t*)&ctrl8_xl, 1); - } - - return ret; -} - -/** - * @brief LPF2 on outputs[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of input_composite in reg CTRL8_XL - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_xl_lp2_bandwidth_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_input_composite_t* val) { - lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL8_XL, (uint8_t*)&ctrl8_xl, 1); - - if(ret == 0) { - if((ctrl8_xl.lpf2_xl_en == 0x00U) || (ctrl8_xl.hp_slope_xl_en != 0x00U)) { - *val = LSM6DS3TR_C_XL_LP_NA; - } - - else { - switch((ctrl8_xl.input_composite << 4) + ctrl8_xl.hpcf_xl) { - case LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_50: - *val = LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_50; - break; - - case LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_100: - *val = LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_100; - break; - - case LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_9: - *val = LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_9; - break; - - case LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_400: - *val = LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_400; - break; - - case LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_50: - *val = LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_50; - break; - - case LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_100: - *val = LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_100; - break; - - case LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_9: - *val = LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_9; - break; - - case LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_400: - *val = LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_400; - break; - - default: - *val = LSM6DS3TR_C_XL_LP_NA; - break; - } - } - } - - return ret; -} - -/** - * @brief Enable HP filter reference mode.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of hp_ref_mode in reg CTRL8_XL - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_xl_reference_mode_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL8_XL, (uint8_t*)&ctrl8_xl, 1); - - if(ret == 0) { - ctrl8_xl.hp_ref_mode = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL8_XL, (uint8_t*)&ctrl8_xl, 1); - } - - return ret; -} - -/** - * @brief Enable HP filter reference mode.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of hp_ref_mode in reg CTRL8_XL - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_xl_reference_mode_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL8_XL, (uint8_t*)&ctrl8_xl, 1); - *val = ctrl8_xl.hp_ref_mode; - - return ret; -} - -/** - * @brief High pass/Slope on outputs.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of hpcf_xl in reg CTRL8_XL - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_xl_hp_bandwidth_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_hpcf_xl_t val) { - lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL8_XL, (uint8_t*)&ctrl8_xl, 1); - - if(ret == 0) { - ctrl8_xl.input_composite = 0; - ctrl8_xl.hpcf_xl = (uint8_t)val & 0x03U; - ctrl8_xl.hp_slope_xl_en = 1; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL8_XL, (uint8_t*)&ctrl8_xl, 1); - } - - return ret; -} - -/** - * @brief High pass/Slope on outputs.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of hpcf_xl in reg CTRL8_XL - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_xl_hp_bandwidth_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_hpcf_xl_t* val) { - lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL8_XL, (uint8_t*)&ctrl8_xl, 1); - - if(ctrl8_xl.hp_slope_xl_en == 0x00U) { - *val = LSM6DS3TR_C_XL_HP_NA; - } - - switch(ctrl8_xl.hpcf_xl) { - case LSM6DS3TR_C_XL_HP_ODR_DIV_4: - *val = LSM6DS3TR_C_XL_HP_ODR_DIV_4; - break; - - case LSM6DS3TR_C_XL_HP_ODR_DIV_100: - *val = LSM6DS3TR_C_XL_HP_ODR_DIV_100; - break; - - case LSM6DS3TR_C_XL_HP_ODR_DIV_9: - *val = LSM6DS3TR_C_XL_HP_ODR_DIV_9; - break; - - case LSM6DS3TR_C_XL_HP_ODR_DIV_400: - *val = LSM6DS3TR_C_XL_HP_ODR_DIV_400; - break; - - default: - *val = LSM6DS3TR_C_XL_HP_NA; - break; - } - - return ret; -} - -/** - * @} - * - */ - -/** - * @defgroup LSM6DS3TR_C_gyroscope_filters - * @brief This section group all the functions concerning the filters - * configuration that impact gyroscope. - * @{ - * - */ - -/** - * @brief Gyroscope low pass path bandwidth.[set] - * - * @param ctx Read / write interface definitions - * @param val gyroscope filtering chain configuration. - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_gy_band_pass_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_lpf1_sel_g_t val) { - lsm6ds3tr_c_ctrl4_c_t ctrl4_c; - lsm6ds3tr_c_ctrl6_c_t ctrl6_c; - lsm6ds3tr_c_ctrl7_g_t ctrl7_g; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL7_G, (uint8_t*)&ctrl7_g, 1); - - if(ret == 0) { - ctrl7_g.hpm_g = ((uint8_t)val & 0x30U) >> 4; - ctrl7_g.hp_en_g = ((uint8_t)val & 0x80U) >> 7; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL7_G, (uint8_t*)&ctrl7_g, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL6_C, (uint8_t*)&ctrl6_c, 1); - - if(ret == 0) { - ctrl6_c.ftype = (uint8_t)val & 0x03U; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL6_C, (uint8_t*)&ctrl6_c, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C, (uint8_t*)&ctrl4_c, 1); - - if(ret == 0) { - ctrl4_c.lpf1_sel_g = ((uint8_t)val & 0x08U) >> 3; - ret = - lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL4_C, (uint8_t*)&ctrl4_c, 1); - } - } - } - } - } - - return ret; -} - -/** - * @brief Gyroscope low pass path bandwidth.[get] - * - * @param ctx Read / write interface definitions - * @param val gyroscope filtering chain - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_gy_band_pass_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_lpf1_sel_g_t* val) { - lsm6ds3tr_c_ctrl4_c_t ctrl4_c; - lsm6ds3tr_c_ctrl6_c_t ctrl6_c; - lsm6ds3tr_c_ctrl7_g_t ctrl7_g; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL6_C, (uint8_t*)&ctrl6_c, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C, (uint8_t*)&ctrl4_c, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL7_G, (uint8_t*)&ctrl7_g, 1); - - switch((ctrl7_g.hp_en_g << 7) + (ctrl7_g.hpm_g << 4) + (ctrl4_c.lpf1_sel_g << 3) + - ctrl6_c.ftype) { - case LSM6DS3TR_C_HP_16mHz_LP2: - *val = LSM6DS3TR_C_HP_16mHz_LP2; - break; - - case LSM6DS3TR_C_HP_65mHz_LP2: - *val = LSM6DS3TR_C_HP_65mHz_LP2; - break; - - case LSM6DS3TR_C_HP_260mHz_LP2: - *val = LSM6DS3TR_C_HP_260mHz_LP2; - break; - - case LSM6DS3TR_C_HP_1Hz04_LP2: - *val = LSM6DS3TR_C_HP_1Hz04_LP2; - break; - - case LSM6DS3TR_C_HP_DISABLE_LP1_LIGHT: - *val = LSM6DS3TR_C_HP_DISABLE_LP1_LIGHT; - break; - - case LSM6DS3TR_C_HP_DISABLE_LP1_NORMAL: - *val = LSM6DS3TR_C_HP_DISABLE_LP1_NORMAL; - break; - - case LSM6DS3TR_C_HP_DISABLE_LP_STRONG: - *val = LSM6DS3TR_C_HP_DISABLE_LP_STRONG; - break; - - case LSM6DS3TR_C_HP_DISABLE_LP1_AGGRESSIVE: - *val = LSM6DS3TR_C_HP_DISABLE_LP1_AGGRESSIVE; - break; - - case LSM6DS3TR_C_HP_16mHz_LP1_LIGHT: - *val = LSM6DS3TR_C_HP_16mHz_LP1_LIGHT; - break; - - case LSM6DS3TR_C_HP_65mHz_LP1_NORMAL: - *val = LSM6DS3TR_C_HP_65mHz_LP1_NORMAL; - break; - - case LSM6DS3TR_C_HP_260mHz_LP1_STRONG: - *val = LSM6DS3TR_C_HP_260mHz_LP1_STRONG; - break; - - case LSM6DS3TR_C_HP_1Hz04_LP1_AGGRESSIVE: - *val = LSM6DS3TR_C_HP_1Hz04_LP1_AGGRESSIVE; - break; - - default: - *val = LSM6DS3TR_C_HP_GY_BAND_NA; - break; - } - } - } - - return ret; -} - -/** - * @} - * - */ - -/** - * @defgroup LSM6DS3TR_C_serial_interface - * @brief This section groups all the functions concerning serial - * interface management - * @{ - * - */ - -/** - * @brief SPI Serial Interface Mode selection.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of sim in reg CTRL3_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_spi_mode_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_sim_t val) { - lsm6ds3tr_c_ctrl3_c_t ctrl3_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, (uint8_t*)&ctrl3_c, 1); - - if(ret == 0) { - ctrl3_c.sim = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL3_C, (uint8_t*)&ctrl3_c, 1); - } - - return ret; -} - -/** - * @brief SPI Serial Interface Mode selection.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of sim in reg CTRL3_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_spi_mode_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_sim_t* val) { - lsm6ds3tr_c_ctrl3_c_t ctrl3_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, (uint8_t*)&ctrl3_c, 1); - - switch(ctrl3_c.sim) { - case LSM6DS3TR_C_SPI_4_WIRE: - *val = LSM6DS3TR_C_SPI_4_WIRE; - break; - - case LSM6DS3TR_C_SPI_3_WIRE: - *val = LSM6DS3TR_C_SPI_3_WIRE; - break; - - default: - *val = LSM6DS3TR_C_SPI_MODE_ND; - break; - } - - return ret; -} - -/** - * @brief Disable / Enable I2C interface.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of i2c_disable in reg CTRL4_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_i2c_interface_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_i2c_disable_t val) { - lsm6ds3tr_c_ctrl4_c_t ctrl4_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C, (uint8_t*)&ctrl4_c, 1); - - if(ret == 0) { - ctrl4_c.i2c_disable = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL4_C, (uint8_t*)&ctrl4_c, 1); - } - - return ret; -} - -/** - * @brief Disable / Enable I2C interface.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of i2c_disable in reg CTRL4_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_i2c_interface_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_i2c_disable_t* val) { - lsm6ds3tr_c_ctrl4_c_t ctrl4_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C, (uint8_t*)&ctrl4_c, 1); - - switch(ctrl4_c.i2c_disable) { - case LSM6DS3TR_C_I2C_ENABLE: - *val = LSM6DS3TR_C_I2C_ENABLE; - break; - - case LSM6DS3TR_C_I2C_DISABLE: - *val = LSM6DS3TR_C_I2C_DISABLE; - break; - - default: - *val = LSM6DS3TR_C_I2C_MODE_ND; - break; - } - - return ret; -} - -/** - * @} - * - */ - -/** - * @defgroup LSM6DS3TR_C_interrupt_pins - * @brief This section groups all the functions that manage - * interrupt pins - * @{ - * - */ - -/** - * @brief Select the signal that need to route on int1 pad[set] - * - * @param ctx Read / write interface definitions - * @param val configure INT1_CTRL, MD1_CFG, CTRL4_C(den_drdy_int1), - * MASTER_CONFIG(drdy_on_int1) - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_pin_int1_route_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_int1_route_t val) { - lsm6ds3tr_c_master_config_t master_config; - lsm6ds3tr_c_int1_ctrl_t int1_ctrl; - lsm6ds3tr_c_md1_cfg_t md1_cfg; - lsm6ds3tr_c_md2_cfg_t md2_cfg; - lsm6ds3tr_c_ctrl4_c_t ctrl4_c; - lsm6ds3tr_c_tap_cfg_t tap_cfg; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_INT1_CTRL, (uint8_t*)&int1_ctrl, 1); - - if(ret == 0) { - int1_ctrl.int1_drdy_xl = val.int1_drdy_xl; - int1_ctrl.int1_drdy_g = val.int1_drdy_g; - int1_ctrl.int1_boot = val.int1_boot; - int1_ctrl.int1_fth = val.int1_fth; - int1_ctrl.int1_fifo_ovr = val.int1_fifo_ovr; - int1_ctrl.int1_full_flag = val.int1_full_flag; - int1_ctrl.int1_sign_mot = val.int1_sign_mot; - int1_ctrl.int1_step_detector = val.int1_step_detector; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_INT1_CTRL, (uint8_t*)&int1_ctrl, 1); - } - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MD1_CFG, (uint8_t*)&md1_cfg, 1); - } - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MD2_CFG, (uint8_t*)&md2_cfg, 1); - } - - if(ret == 0) { - md1_cfg.int1_timer = val.int1_timer; - md1_cfg.int1_tilt = val.int1_tilt; - md1_cfg.int1_6d = val.int1_6d; - md1_cfg.int1_double_tap = val.int1_double_tap; - md1_cfg.int1_ff = val.int1_ff; - md1_cfg.int1_wu = val.int1_wu; - md1_cfg.int1_single_tap = val.int1_single_tap; - md1_cfg.int1_inact_state = val.int1_inact_state; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MD1_CFG, (uint8_t*)&md1_cfg, 1); - } - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C, (uint8_t*)&ctrl4_c, 1); - } - - if(ret == 0) { - ctrl4_c.den_drdy_int1 = val.den_drdy_int1; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL4_C, (uint8_t*)&ctrl4_c, 1); - } - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, (uint8_t*)&master_config, 1); - } - - if(ret == 0) { - master_config.drdy_on_int1 = val.den_drdy_int1; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, (uint8_t*)&master_config, 1); - } - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG, (uint8_t*)&tap_cfg, 1); - - if((val.int1_6d != 0x00U) || (val.int1_ff != 0x00U) || (val.int1_wu != 0x00U) || - (val.int1_single_tap != 0x00U) || (val.int1_double_tap != 0x00U) || - (val.int1_inact_state != 0x00U) || (md2_cfg.int2_6d != 0x00U) || - (md2_cfg.int2_ff != 0x00U) || (md2_cfg.int2_wu != 0x00U) || - (md2_cfg.int2_single_tap != 0x00U) || (md2_cfg.int2_double_tap != 0x00U) || - (md2_cfg.int2_inact_state != 0x00U)) { - tap_cfg.interrupts_enable = PROPERTY_ENABLE; - } - - else { - tap_cfg.interrupts_enable = PROPERTY_DISABLE; - } - } - - if(ret == 0) { - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_CFG, (uint8_t*)&tap_cfg, 1); - } - - return ret; -} - -/** - * @brief Select the signal that need to route on int1 pad[get] - * - * @param ctx Read / write interface definitions - * @param val read INT1_CTRL, MD1_CFG, CTRL4_C(den_drdy_int1), - * MASTER_CONFIG(drdy_on_int1) - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_pin_int1_route_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_int1_route_t* val) { - lsm6ds3tr_c_master_config_t master_config; - lsm6ds3tr_c_int1_ctrl_t int1_ctrl; - lsm6ds3tr_c_md1_cfg_t md1_cfg; - lsm6ds3tr_c_ctrl4_c_t ctrl4_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_INT1_CTRL, (uint8_t*)&int1_ctrl, 1); - - if(ret == 0) { - val->int1_drdy_xl = int1_ctrl.int1_drdy_xl; - val->int1_drdy_g = int1_ctrl.int1_drdy_g; - val->int1_boot = int1_ctrl.int1_boot; - val->int1_fth = int1_ctrl.int1_fth; - val->int1_fifo_ovr = int1_ctrl.int1_fifo_ovr; - val->int1_full_flag = int1_ctrl.int1_full_flag; - val->int1_sign_mot = int1_ctrl.int1_sign_mot; - val->int1_step_detector = int1_ctrl.int1_step_detector; - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MD1_CFG, (uint8_t*)&md1_cfg, 1); - - if(ret == 0) { - val->int1_timer = md1_cfg.int1_timer; - val->int1_tilt = md1_cfg.int1_tilt; - val->int1_6d = md1_cfg.int1_6d; - val->int1_double_tap = md1_cfg.int1_double_tap; - val->int1_ff = md1_cfg.int1_ff; - val->int1_wu = md1_cfg.int1_wu; - val->int1_single_tap = md1_cfg.int1_single_tap; - val->int1_inact_state = md1_cfg.int1_inact_state; - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C, (uint8_t*)&ctrl4_c, 1); - - if(ret == 0) { - val->den_drdy_int1 = ctrl4_c.den_drdy_int1; - ret = lsm6ds3tr_c_read_reg( - ctx, LSM6DS3TR_C_MASTER_CONFIG, (uint8_t*)&master_config, 1); - val->den_drdy_int1 = master_config.drdy_on_int1; - } - } - } - - return ret; -} - -/** - * @brief Select the signal that need to route on int2 pad[set] - * - * @param ctx Read / write interface definitions - * @param val INT2_CTRL, DRDY_PULSE_CFG(int2_wrist_tilt), MD2_CFG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_pin_int2_route_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_int2_route_t val) { - lsm6ds3tr_c_int2_ctrl_t int2_ctrl; - lsm6ds3tr_c_md1_cfg_t md1_cfg; - lsm6ds3tr_c_md2_cfg_t md2_cfg; - lsm6ds3tr_c_drdy_pulse_cfg_g_t drdy_pulse_cfg_g; - lsm6ds3tr_c_tap_cfg_t tap_cfg; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_INT2_CTRL, (uint8_t*)&int2_ctrl, 1); - - if(ret == 0) { - int2_ctrl.int2_drdy_xl = val.int2_drdy_xl; - int2_ctrl.int2_drdy_g = val.int2_drdy_g; - int2_ctrl.int2_drdy_temp = val.int2_drdy_temp; - int2_ctrl.int2_fth = val.int2_fth; - int2_ctrl.int2_fifo_ovr = val.int2_fifo_ovr; - int2_ctrl.int2_full_flag = val.int2_full_flag; - int2_ctrl.int2_step_count_ov = val.int2_step_count_ov; - int2_ctrl.int2_step_delta = val.int2_step_delta; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_INT2_CTRL, (uint8_t*)&int2_ctrl, 1); - } - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MD1_CFG, (uint8_t*)&md1_cfg, 1); - } - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MD2_CFG, (uint8_t*)&md2_cfg, 1); - } - - if(ret == 0) { - md2_cfg.int2_iron = val.int2_iron; - md2_cfg.int2_tilt = val.int2_tilt; - md2_cfg.int2_6d = val.int2_6d; - md2_cfg.int2_double_tap = val.int2_double_tap; - md2_cfg.int2_ff = val.int2_ff; - md2_cfg.int2_wu = val.int2_wu; - md2_cfg.int2_single_tap = val.int2_single_tap; - md2_cfg.int2_inact_state = val.int2_inact_state; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MD2_CFG, (uint8_t*)&md2_cfg, 1); - } - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg( - ctx, LSM6DS3TR_C_DRDY_PULSE_CFG_G, (uint8_t*)&drdy_pulse_cfg_g, 1); - } - - if(ret == 0) { - drdy_pulse_cfg_g.int2_wrist_tilt = val.int2_wrist_tilt; - ret = lsm6ds3tr_c_write_reg( - ctx, LSM6DS3TR_C_DRDY_PULSE_CFG_G, (uint8_t*)&drdy_pulse_cfg_g, 1); - } - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG, (uint8_t*)&tap_cfg, 1); - - if((md1_cfg.int1_6d != 0x00U) || (md1_cfg.int1_ff != 0x00U) || - (md1_cfg.int1_wu != 0x00U) || (md1_cfg.int1_single_tap != 0x00U) || - (md1_cfg.int1_double_tap != 0x00U) || (md1_cfg.int1_inact_state != 0x00U) || - (val.int2_6d != 0x00U) || (val.int2_ff != 0x00U) || (val.int2_wu != 0x00U) || - (val.int2_single_tap != 0x00U) || (val.int2_double_tap != 0x00U) || - (val.int2_inact_state != 0x00U)) { - tap_cfg.interrupts_enable = PROPERTY_ENABLE; - } - - else { - tap_cfg.interrupts_enable = PROPERTY_DISABLE; - } - } - - if(ret == 0) { - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_CFG, (uint8_t*)&tap_cfg, 1); - } - - return ret; -} - -/** - * @brief Select the signal that need to route on int2 pad[get] - * - * @param ctx Read / write interface definitions - * @param val INT2_CTRL, DRDY_PULSE_CFG(int2_wrist_tilt), MD2_CFG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_pin_int2_route_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_int2_route_t* val) { - lsm6ds3tr_c_int2_ctrl_t int2_ctrl; - lsm6ds3tr_c_md2_cfg_t md2_cfg; - lsm6ds3tr_c_drdy_pulse_cfg_g_t drdy_pulse_cfg_g; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_INT2_CTRL, (uint8_t*)&int2_ctrl, 1); - - if(ret == 0) { - val->int2_drdy_xl = int2_ctrl.int2_drdy_xl; - val->int2_drdy_g = int2_ctrl.int2_drdy_g; - val->int2_drdy_temp = int2_ctrl.int2_drdy_temp; - val->int2_fth = int2_ctrl.int2_fth; - val->int2_fifo_ovr = int2_ctrl.int2_fifo_ovr; - val->int2_full_flag = int2_ctrl.int2_full_flag; - val->int2_step_count_ov = int2_ctrl.int2_step_count_ov; - val->int2_step_delta = int2_ctrl.int2_step_delta; - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MD2_CFG, (uint8_t*)&md2_cfg, 1); - - if(ret == 0) { - val->int2_iron = md2_cfg.int2_iron; - val->int2_tilt = md2_cfg.int2_tilt; - val->int2_6d = md2_cfg.int2_6d; - val->int2_double_tap = md2_cfg.int2_double_tap; - val->int2_ff = md2_cfg.int2_ff; - val->int2_wu = md2_cfg.int2_wu; - val->int2_single_tap = md2_cfg.int2_single_tap; - val->int2_inact_state = md2_cfg.int2_inact_state; - ret = lsm6ds3tr_c_read_reg( - ctx, LSM6DS3TR_C_DRDY_PULSE_CFG_G, (uint8_t*)&drdy_pulse_cfg_g, 1); - val->int2_wrist_tilt = drdy_pulse_cfg_g.int2_wrist_tilt; - } - } - - return ret; -} - -/** - * @brief Push-pull/open drain selection on interrupt pads.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of pp_od in reg CTRL3_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_pin_mode_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_pp_od_t val) { - lsm6ds3tr_c_ctrl3_c_t ctrl3_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, (uint8_t*)&ctrl3_c, 1); - - if(ret == 0) { - ctrl3_c.pp_od = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL3_C, (uint8_t*)&ctrl3_c, 1); - } - - return ret; -} - -/** - * @brief Push-pull/open drain selection on interrupt pads.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of pp_od in reg CTRL3_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_pin_mode_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_pp_od_t* val) { - lsm6ds3tr_c_ctrl3_c_t ctrl3_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, (uint8_t*)&ctrl3_c, 1); - - switch(ctrl3_c.pp_od) { - case LSM6DS3TR_C_PUSH_PULL: - *val = LSM6DS3TR_C_PUSH_PULL; - break; - - case LSM6DS3TR_C_OPEN_DRAIN: - *val = LSM6DS3TR_C_OPEN_DRAIN; - break; - - default: - *val = LSM6DS3TR_C_PIN_MODE_ND; - break; - } - - return ret; -} - -/** - * @brief Interrupt active-high/low.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of h_lactive in reg CTRL3_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_pin_polarity_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_h_lactive_t val) { - lsm6ds3tr_c_ctrl3_c_t ctrl3_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, (uint8_t*)&ctrl3_c, 1); - - if(ret == 0) { - ctrl3_c.h_lactive = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL3_C, (uint8_t*)&ctrl3_c, 1); - } - - return ret; -} - -/** - * @brief Interrupt active-high/low.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of h_lactive in reg CTRL3_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_pin_polarity_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_h_lactive_t* val) { - lsm6ds3tr_c_ctrl3_c_t ctrl3_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL3_C, (uint8_t*)&ctrl3_c, 1); - - switch(ctrl3_c.h_lactive) { - case LSM6DS3TR_C_ACTIVE_HIGH: - *val = LSM6DS3TR_C_ACTIVE_HIGH; - break; - - case LSM6DS3TR_C_ACTIVE_LOW: - *val = LSM6DS3TR_C_ACTIVE_LOW; - break; - - default: - *val = LSM6DS3TR_C_POLARITY_ND; - break; - } - - return ret; -} - -/** - * @brief All interrupt signals become available on INT1 pin.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of int2_on_int1 in reg CTRL4_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_all_on_int1_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_ctrl4_c_t ctrl4_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C, (uint8_t*)&ctrl4_c, 1); - - if(ret == 0) { - ctrl4_c.int2_on_int1 = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL4_C, (uint8_t*)&ctrl4_c, 1); - } - - return ret; -} - -/** - * @brief All interrupt signals become available on INT1 pin.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of int2_on_int1 in reg CTRL4_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_all_on_int1_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_ctrl4_c_t ctrl4_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C, (uint8_t*)&ctrl4_c, 1); - *val = ctrl4_c.int2_on_int1; - - return ret; -} - -/** - * @brief Latched/pulsed interrupt.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of lir in reg TAP_CFG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_int_notification_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_lir_t val) { - lsm6ds3tr_c_tap_cfg_t tap_cfg; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG, (uint8_t*)&tap_cfg, 1); - - if(ret == 0) { - tap_cfg.lir = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_CFG, (uint8_t*)&tap_cfg, 1); - } - - return ret; -} - -/** - * @brief Latched/pulsed interrupt.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of lir in reg TAP_CFG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_int_notification_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_lir_t* val) { - lsm6ds3tr_c_tap_cfg_t tap_cfg; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG, (uint8_t*)&tap_cfg, 1); - - switch(tap_cfg.lir) { - case LSM6DS3TR_C_INT_PULSED: - *val = LSM6DS3TR_C_INT_PULSED; - break; - - case LSM6DS3TR_C_INT_LATCHED: - *val = LSM6DS3TR_C_INT_LATCHED; - break; - - default: - *val = LSM6DS3TR_C_INT_MODE; - break; - } - - return ret; -} - -/** - * @} - * - */ - -/** - * @defgroup LSM6DS3TR_C_Wake_Up_event - * @brief This section groups all the functions that manage the - * Wake Up event generation. - * @{ - * - */ - -/** - * @brief Threshold for wakeup.1 LSB = FS_XL / 64.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of wk_ths in reg WAKE_UP_THS - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_wkup_threshold_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_wake_up_ths_t wake_up_ths; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_THS, (uint8_t*)&wake_up_ths, 1); - - if(ret == 0) { - wake_up_ths.wk_ths = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_WAKE_UP_THS, (uint8_t*)&wake_up_ths, 1); - } - - return ret; -} - -/** - * @brief Threshold for wakeup.1 LSB = FS_XL / 64.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of wk_ths in reg WAKE_UP_THS - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_wkup_threshold_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_wake_up_ths_t wake_up_ths; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_THS, (uint8_t*)&wake_up_ths, 1); - *val = wake_up_ths.wk_ths; - - return ret; -} - -/** - * @brief Wake up duration event.1LSb = 1 / ODR[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of wake_dur in reg WAKE_UP_DUR - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_wkup_dur_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_wake_up_dur_t wake_up_dur; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR, (uint8_t*)&wake_up_dur, 1); - - if(ret == 0) { - wake_up_dur.wake_dur = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR, (uint8_t*)&wake_up_dur, 1); - } - - return ret; -} - -/** - * @brief Wake up duration event.1LSb = 1 / ODR[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of wake_dur in reg WAKE_UP_DUR - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_wkup_dur_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_wake_up_dur_t wake_up_dur; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR, (uint8_t*)&wake_up_dur, 1); - *val = wake_up_dur.wake_dur; - - return ret; -} - -/** - * @} - * - */ - -/** - * @defgroup LSM6DS3TR_C_Activity/Inactivity_detection - * @brief This section groups all the functions concerning - * activity/inactivity detection. - * @{ - * - */ - -/** - * @brief Enables gyroscope Sleep mode.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of sleep in reg CTRL4_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_gy_sleep_mode_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_ctrl4_c_t ctrl4_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C, (uint8_t*)&ctrl4_c, 1); - - if(ret == 0) { - ctrl4_c.sleep = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL4_C, (uint8_t*)&ctrl4_c, 1); - } - - return ret; -} - -/** - * @brief Enables gyroscope Sleep mode.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of sleep in reg CTRL4_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_gy_sleep_mode_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_ctrl4_c_t ctrl4_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C, (uint8_t*)&ctrl4_c, 1); - *val = ctrl4_c.sleep; - - return ret; -} - -/** - * @brief Enable inactivity function.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of inact_en in reg TAP_CFG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_act_mode_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_inact_en_t val) { - lsm6ds3tr_c_tap_cfg_t tap_cfg; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG, (uint8_t*)&tap_cfg, 1); - - if(ret == 0) { - tap_cfg.inact_en = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_CFG, (uint8_t*)&tap_cfg, 1); - } - - return ret; -} - -/** - * @brief Enable inactivity function.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of inact_en in reg TAP_CFG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_act_mode_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_inact_en_t* val) { - lsm6ds3tr_c_tap_cfg_t tap_cfg; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG, (uint8_t*)&tap_cfg, 1); - - switch(tap_cfg.inact_en) { - case LSM6DS3TR_C_PROPERTY_DISABLE: - *val = LSM6DS3TR_C_PROPERTY_DISABLE; - break; - - case LSM6DS3TR_C_XL_12Hz5_GY_NOT_AFFECTED: - *val = LSM6DS3TR_C_XL_12Hz5_GY_NOT_AFFECTED; - break; - - case LSM6DS3TR_C_XL_12Hz5_GY_SLEEP: - *val = LSM6DS3TR_C_XL_12Hz5_GY_SLEEP; - break; - - case LSM6DS3TR_C_XL_12Hz5_GY_PD: - *val = LSM6DS3TR_C_XL_12Hz5_GY_PD; - break; - - default: - *val = LSM6DS3TR_C_ACT_MODE_ND; - break; - } - - return ret; -} - -/** - * @brief Duration to go in sleep mode.1 LSb = 512 / ODR[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of sleep_dur in reg WAKE_UP_DUR - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_act_sleep_dur_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_wake_up_dur_t wake_up_dur; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR, (uint8_t*)&wake_up_dur, 1); - - if(ret == 0) { - wake_up_dur.sleep_dur = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR, (uint8_t*)&wake_up_dur, 1); - } - - return ret; -} - -/** - * @brief Duration to go in sleep mode. 1 LSb = 512 / ODR[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of sleep_dur in reg WAKE_UP_DUR - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_act_sleep_dur_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_wake_up_dur_t wake_up_dur; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR, (uint8_t*)&wake_up_dur, 1); - *val = wake_up_dur.sleep_dur; - - return ret; -} - -/** - * @} - * - */ - -/** - * @defgroup LSM6DS3TR_C_tap_generator - * @brief This section groups all the functions that manage the - * tap and double tap event generation. - * @{ - * - */ - -/** - * @brief Read the tap / double tap source register.[get] - * - * @param ctx Read / write interface definitions - * @param val Structure of registers from TAP_SRC - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_tap_src_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_tap_src_t* val) { - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_SRC, (uint8_t*)val, 1); - - return ret; -} - -/** - * @brief Enable Z direction in tap recognition.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of tap_z_en in reg TAP_CFG - * - */ -int32_t lsm6ds3tr_c_tap_detection_on_z_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_tap_cfg_t tap_cfg; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG, (uint8_t*)&tap_cfg, 1); - - if(ret == 0) { - tap_cfg.tap_z_en = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_CFG, (uint8_t*)&tap_cfg, 1); - } - - return ret; -} - -/** - * @brief Enable Z direction in tap recognition.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of tap_z_en in reg TAP_CFG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_tap_detection_on_z_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_tap_cfg_t tap_cfg; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG, (uint8_t*)&tap_cfg, 1); - *val = tap_cfg.tap_z_en; - - return ret; -} - -/** - * @brief Enable Y direction in tap recognition.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of tap_y_en in reg TAP_CFG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_tap_detection_on_y_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_tap_cfg_t tap_cfg; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG, (uint8_t*)&tap_cfg, 1); - - if(ret == 0) { - tap_cfg.tap_y_en = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_CFG, (uint8_t*)&tap_cfg, 1); - } - - return ret; -} - -/** - * @brief Enable Y direction in tap recognition.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of tap_y_en in reg TAP_CFG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_tap_detection_on_y_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_tap_cfg_t tap_cfg; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG, (uint8_t*)&tap_cfg, 1); - *val = tap_cfg.tap_y_en; - - return ret; -} - -/** - * @brief Enable X direction in tap recognition.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of tap_x_en in reg TAP_CFG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_tap_detection_on_x_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_tap_cfg_t tap_cfg; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG, (uint8_t*)&tap_cfg, 1); - - if(ret == 0) { - tap_cfg.tap_x_en = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_CFG, (uint8_t*)&tap_cfg, 1); - } - - return ret; -} - -/** - * @brief Enable X direction in tap recognition.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of tap_x_en in reg TAP_CFG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_tap_detection_on_x_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_tap_cfg_t tap_cfg; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_CFG, (uint8_t*)&tap_cfg, 1); - *val = tap_cfg.tap_x_en; - - return ret; -} - -/** - * @brief Threshold for tap recognition.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of tap_ths in reg TAP_THS_6D - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_tap_threshold_x_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_tap_ths_6d_t tap_ths_6d; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_THS_6D, (uint8_t*)&tap_ths_6d, 1); - - if(ret == 0) { - tap_ths_6d.tap_ths = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_THS_6D, (uint8_t*)&tap_ths_6d, 1); - } - - return ret; -} - -/** - * @brief Threshold for tap recognition.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of tap_ths in reg TAP_THS_6D - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_tap_threshold_x_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_tap_ths_6d_t tap_ths_6d; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_THS_6D, (uint8_t*)&tap_ths_6d, 1); - *val = tap_ths_6d.tap_ths; - - return ret; -} - -/** - * @brief Maximum duration is the maximum time of an overthreshold signal - * detection to be recognized as a tap event. - * The default value of these bits is 00b which corresponds to - * 4*ODR_XL time. - * If the SHOCK[1:0] bits are set to a different - * value, 1LSB corresponds to 8*ODR_XL time.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of shock in reg INT_DUR2 - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_tap_shock_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_int_dur2_t int_dur2; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_INT_DUR2, (uint8_t*)&int_dur2, 1); - - if(ret == 0) { - int_dur2.shock = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_INT_DUR2, (uint8_t*)&int_dur2, 1); - } - - return ret; -} - -/** - * @brief Maximum duration is the maximum time of an overthreshold signal - * detection to be recognized as a tap event. - * The default value of these bits is 00b which corresponds to - * 4*ODR_XL time. - * If the SHOCK[1:0] bits are set to a different value, 1LSB - * corresponds to 8*ODR_XL time.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of shock in reg INT_DUR2 - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_tap_shock_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_int_dur2_t int_dur2; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_INT_DUR2, (uint8_t*)&int_dur2, 1); - *val = int_dur2.shock; - - return ret; -} - -/** - * @brief Quiet time is the time after the first detected tap in which there - * must not be any overthreshold event. - * The default value of these bits is 00b which corresponds to - * 2*ODR_XL time. - * If the QUIET[1:0] bits are set to a different value, 1LSB - * corresponds to 4*ODR_XL time.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of quiet in reg INT_DUR2 - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_tap_quiet_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_int_dur2_t int_dur2; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_INT_DUR2, (uint8_t*)&int_dur2, 1); - - if(ret == 0) { - int_dur2.quiet = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_INT_DUR2, (uint8_t*)&int_dur2, 1); - } - - return ret; -} - -/** - * @brief Quiet time is the time after the first detected tap in which there - * must not be any overthreshold event. - * The default value of these bits is 00b which corresponds to - * 2*ODR_XL time. - * If the QUIET[1:0] bits are set to a different value, 1LSB - * corresponds to 4*ODR_XL time.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of quiet in reg INT_DUR2 - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_tap_quiet_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_int_dur2_t int_dur2; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_INT_DUR2, (uint8_t*)&int_dur2, 1); - *val = int_dur2.quiet; - - return ret; -} - -/** - * @brief When double tap recognition is enabled, this register expresses the - * maximum time between two consecutive detected taps to determine a - * double tap event. - * The default value of these bits is 0000b which corresponds to - * 16*ODR_XL time. - * If the DUR[3:0] bits are set to a different value,1LSB corresponds - * to 32*ODR_XL time.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of dur in reg INT_DUR2 - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_tap_dur_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_int_dur2_t int_dur2; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_INT_DUR2, (uint8_t*)&int_dur2, 1); - - if(ret == 0) { - int_dur2.dur = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_INT_DUR2, (uint8_t*)&int_dur2, 1); - } - - return ret; -} - -/** - * @brief When double tap recognition is enabled, this register expresses the - * maximum time between two consecutive detected taps to determine a - * double tap event. - * The default value of these bits is 0000b which corresponds to - * 16*ODR_XL time. - * If the DUR[3:0] bits are set to a different value,1LSB corresponds - * to 32*ODR_XL time.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of dur in reg INT_DUR2 - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_tap_dur_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_int_dur2_t int_dur2; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_INT_DUR2, (uint8_t*)&int_dur2, 1); - *val = int_dur2.dur; - - return ret; -} - -/** - * @brief Single/double-tap event enable/disable.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of - * single_double_tap in reg WAKE_UP_THS - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_tap_mode_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_single_double_tap_t val) { - lsm6ds3tr_c_wake_up_ths_t wake_up_ths; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_THS, (uint8_t*)&wake_up_ths, 1); - - if(ret == 0) { - wake_up_ths.single_double_tap = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_WAKE_UP_THS, (uint8_t*)&wake_up_ths, 1); - } - - return ret; -} - -/** - * @brief Single/double-tap event enable/disable.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of single_double_tap - * in reg WAKE_UP_THS - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_tap_mode_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_single_double_tap_t* val) { - lsm6ds3tr_c_wake_up_ths_t wake_up_ths; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_THS, (uint8_t*)&wake_up_ths, 1); - - switch(wake_up_ths.single_double_tap) { - case LSM6DS3TR_C_ONLY_SINGLE: - *val = LSM6DS3TR_C_ONLY_SINGLE; - break; - - case LSM6DS3TR_C_BOTH_SINGLE_DOUBLE: - *val = LSM6DS3TR_C_BOTH_SINGLE_DOUBLE; - break; - - default: - *val = LSM6DS3TR_C_TAP_MODE_ND; - break; - } - - return ret; -} - -/** - * @} - * - */ - -/** - * @defgroup LSM6DS3TR_C_ Six_position_detection(6D/4D) - * @brief This section groups all the functions concerning six - * position detection (6D). - * @{ - * - */ - -/** - * @brief LPF2 feed 6D function selection.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of low_pass_on_6d in - * reg CTRL8_XL - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_6d_feed_data_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_low_pass_on_6d_t val) { - lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL8_XL, (uint8_t*)&ctrl8_xl, 1); - - if(ret == 0) { - ctrl8_xl.low_pass_on_6d = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL8_XL, (uint8_t*)&ctrl8_xl, 1); - } - - return ret; -} - -/** - * @brief LPF2 feed 6D function selection.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of low_pass_on_6d in reg CTRL8_XL - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_6d_feed_data_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_low_pass_on_6d_t* val) { - lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL8_XL, (uint8_t*)&ctrl8_xl, 1); - - switch(ctrl8_xl.low_pass_on_6d) { - case LSM6DS3TR_C_ODR_DIV_2_FEED: - *val = LSM6DS3TR_C_ODR_DIV_2_FEED; - break; - - case LSM6DS3TR_C_LPF2_FEED: - *val = LSM6DS3TR_C_LPF2_FEED; - break; - - default: - *val = LSM6DS3TR_C_6D_FEED_ND; - break; - } - - return ret; -} - -/** - * @brief Threshold for 4D/6D function.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of sixd_ths in reg TAP_THS_6D - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_6d_threshold_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_sixd_ths_t val) { - lsm6ds3tr_c_tap_ths_6d_t tap_ths_6d; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_THS_6D, (uint8_t*)&tap_ths_6d, 1); - - if(ret == 0) { - tap_ths_6d.sixd_ths = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_THS_6D, (uint8_t*)&tap_ths_6d, 1); - } - - return ret; -} - -/** - * @brief Threshold for 4D/6D function.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of sixd_ths in reg TAP_THS_6D - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_6d_threshold_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_sixd_ths_t* val) { - lsm6ds3tr_c_tap_ths_6d_t tap_ths_6d; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_THS_6D, (uint8_t*)&tap_ths_6d, 1); - - switch(tap_ths_6d.sixd_ths) { - case LSM6DS3TR_C_DEG_80: - *val = LSM6DS3TR_C_DEG_80; - break; - - case LSM6DS3TR_C_DEG_70: - *val = LSM6DS3TR_C_DEG_70; - break; - - case LSM6DS3TR_C_DEG_60: - *val = LSM6DS3TR_C_DEG_60; - break; - - case LSM6DS3TR_C_DEG_50: - *val = LSM6DS3TR_C_DEG_50; - break; - - default: - *val = LSM6DS3TR_C_6D_TH_ND; - break; - } - - return ret; -} - -/** - * @brief 4D orientation detection enable.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of d4d_en in reg TAP_THS_6D - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_4d_mode_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_tap_ths_6d_t tap_ths_6d; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_THS_6D, (uint8_t*)&tap_ths_6d, 1); - - if(ret == 0) { - tap_ths_6d.d4d_en = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_TAP_THS_6D, (uint8_t*)&tap_ths_6d, 1); - } - - return ret; -} - -/** - * @brief 4D orientation detection enable.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of d4d_en in reg TAP_THS_6D - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_4d_mode_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_tap_ths_6d_t tap_ths_6d; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_TAP_THS_6D, (uint8_t*)&tap_ths_6d, 1); - *val = tap_ths_6d.d4d_en; - - return ret; -} - -/** - * @} - * - */ - -/** - * @defgroup LSM6DS3TR_C_free_fall - * @brief This section group all the functions concerning the free - * fall detection. - * @{ - * - */ - -/** - * @brief Free-fall duration event. 1LSb = 1 / ODR[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of ff_dur in reg WAKE_UP_DUR - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_ff_dur_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_wake_up_dur_t wake_up_dur; - lsm6ds3tr_c_free_fall_t free_fall; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FREE_FALL, (uint8_t*)&free_fall, 1); - - if(ret == 0) { - free_fall.ff_dur = (val & 0x1FU); - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FREE_FALL, (uint8_t*)&free_fall, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR, (uint8_t*)&wake_up_dur, 1); - - if(ret == 0) { - wake_up_dur.ff_dur = (val & 0x20U) >> 5; - ret = - lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR, (uint8_t*)&wake_up_dur, 1); - } - } - } - - return ret; -} - -/** - * @brief Free-fall duration event. 1LSb = 1 / ODR[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of ff_dur in reg WAKE_UP_DUR - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_ff_dur_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_wake_up_dur_t wake_up_dur; - lsm6ds3tr_c_free_fall_t free_fall; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_WAKE_UP_DUR, (uint8_t*)&wake_up_dur, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FREE_FALL, (uint8_t*)&free_fall, 1); - } - - *val = (wake_up_dur.ff_dur << 5) + free_fall.ff_dur; - - return ret; -} - -/** - * @brief Free fall threshold setting.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of ff_ths in reg FREE_FALL - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_ff_threshold_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_ff_ths_t val) { - lsm6ds3tr_c_free_fall_t free_fall; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FREE_FALL, (uint8_t*)&free_fall, 1); - - if(ret == 0) { - free_fall.ff_ths = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FREE_FALL, (uint8_t*)&free_fall, 1); - } - - return ret; -} - -/** - * @brief Free fall threshold setting.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of ff_ths in reg FREE_FALL - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_ff_threshold_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_ff_ths_t* val) { - lsm6ds3tr_c_free_fall_t free_fall; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FREE_FALL, (uint8_t*)&free_fall, 1); - - switch(free_fall.ff_ths) { - case LSM6DS3TR_C_FF_TSH_156mg: - *val = LSM6DS3TR_C_FF_TSH_156mg; - break; - - case LSM6DS3TR_C_FF_TSH_219mg: - *val = LSM6DS3TR_C_FF_TSH_219mg; - break; - - case LSM6DS3TR_C_FF_TSH_250mg: - *val = LSM6DS3TR_C_FF_TSH_250mg; - break; - - case LSM6DS3TR_C_FF_TSH_312mg: - *val = LSM6DS3TR_C_FF_TSH_312mg; - break; - - case LSM6DS3TR_C_FF_TSH_344mg: - *val = LSM6DS3TR_C_FF_TSH_344mg; - break; - - case LSM6DS3TR_C_FF_TSH_406mg: - *val = LSM6DS3TR_C_FF_TSH_406mg; - break; - - case LSM6DS3TR_C_FF_TSH_469mg: - *val = LSM6DS3TR_C_FF_TSH_469mg; - break; - - case LSM6DS3TR_C_FF_TSH_500mg: - *val = LSM6DS3TR_C_FF_TSH_500mg; - break; - - default: - *val = LSM6DS3TR_C_FF_TSH_ND; - break; - } - - return ret; -} - -/** - * @} - * - */ - -/** - * @defgroup LSM6DS3TR_C_fifo - * @brief This section group all the functions concerning the - * fifo usage - * @{ - * - */ - -/** - * @brief FIFO watermark level selection.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of fth in reg FIFO_CTRL1 - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_fifo_watermark_set(stmdev_ctx_t* ctx, uint16_t val) { - lsm6ds3tr_c_fifo_ctrl1_t fifo_ctrl1; - lsm6ds3tr_c_fifo_ctrl2_t fifo_ctrl2; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2, (uint8_t*)&fifo_ctrl2, 1); - - if(ret == 0) { - fifo_ctrl1.fth = (uint8_t)(0x00FFU & val); - fifo_ctrl2.fth = (uint8_t)((0x0700U & val) >> 8); - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL1, (uint8_t*)&fifo_ctrl1, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2, (uint8_t*)&fifo_ctrl2, 1); - } - } - - return ret; -} - -/** - * @brief FIFO watermark level selection.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of fth in reg FIFO_CTRL1 - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_fifo_watermark_get(stmdev_ctx_t* ctx, uint16_t* val) { - lsm6ds3tr_c_fifo_ctrl1_t fifo_ctrl1; - lsm6ds3tr_c_fifo_ctrl2_t fifo_ctrl2; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL1, (uint8_t*)&fifo_ctrl1, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2, (uint8_t*)&fifo_ctrl2, 1); - } - - *val = ((uint16_t)fifo_ctrl2.fth << 8) + (uint16_t)fifo_ctrl1.fth; - - return ret; -} - -/** - * @brief FIFO data level.[get] - * - * @param ctx Read / write interface definitions - * @param val get the values of diff_fifo in reg FIFO_STATUS1 and - * FIFO_STATUS2(diff_fifo), it is recommended to set the - * BDU bit. - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_fifo_data_level_get(stmdev_ctx_t* ctx, uint16_t* val) { - lsm6ds3tr_c_fifo_status1_t fifo_status1; - lsm6ds3tr_c_fifo_status2_t fifo_status2; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_STATUS1, (uint8_t*)&fifo_status1, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_STATUS2, (uint8_t*)&fifo_status2, 1); - *val = ((uint16_t)fifo_status2.diff_fifo << 8) + (uint16_t)fifo_status1.diff_fifo; - } - - return ret; -} - -/** - * @brief FIFO watermark.[get] - * - * @param ctx Read / write interface definitions - * @param val get the values of watermark in reg FIFO_STATUS2 and - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_fifo_wtm_flag_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_fifo_status2_t fifo_status2; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_STATUS2, (uint8_t*)&fifo_status2, 1); - *val = fifo_status2.waterm; - - return ret; -} - -/** - * @brief FIFO pattern.[get] - * - * @param ctx Read / write interface definitions - * @param val get the values of fifo_pattern in reg FIFO_STATUS3 and - * FIFO_STATUS4, it is recommended to set the BDU bit - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_fifo_pattern_get(stmdev_ctx_t* ctx, uint16_t* val) { - lsm6ds3tr_c_fifo_status3_t fifo_status3; - lsm6ds3tr_c_fifo_status4_t fifo_status4; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_STATUS3, (uint8_t*)&fifo_status3, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_STATUS4, (uint8_t*)&fifo_status4, 1); - *val = ((uint16_t)fifo_status4.fifo_pattern << 8) + fifo_status3.fifo_pattern; - } - - return ret; -} - -/** - * @brief Batching of temperature data[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of fifo_temp_en in reg FIFO_CTRL2 - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_fifo_temp_batch_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_fifo_ctrl2_t fifo_ctrl2; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2, (uint8_t*)&fifo_ctrl2, 1); - - if(ret == 0) { - fifo_ctrl2.fifo_temp_en = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2, (uint8_t*)&fifo_ctrl2, 1); - } - - return ret; -} - -/** - * @brief Batching of temperature data[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of fifo_temp_en in reg FIFO_CTRL2 - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_fifo_temp_batch_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_fifo_ctrl2_t fifo_ctrl2; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2, (uint8_t*)&fifo_ctrl2, 1); - *val = fifo_ctrl2.fifo_temp_en; - - return ret; -} - -/** - * @brief Trigger signal for FIFO write operation.[set] - * - * @param ctx Read / write interface definitions - * @param val act on FIFO_CTRL2(timer_pedo_fifo_drdy) - * and MASTER_CONFIG(data_valid_sel_fifo) - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_fifo_write_trigger_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_trigger_fifo_t val) { - lsm6ds3tr_c_fifo_ctrl2_t fifo_ctrl2; - lsm6ds3tr_c_master_config_t master_config; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2, (uint8_t*)&fifo_ctrl2, 1); - - if(ret == 0) { - fifo_ctrl2.timer_pedo_fifo_drdy = (uint8_t)val & 0x01U; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2, (uint8_t*)&fifo_ctrl2, 1); - - if(ret == 0) { - ret = - lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, (uint8_t*)&master_config, 1); - - if(ret == 0) { - master_config.data_valid_sel_fifo = (((uint8_t)val & 0x02U) >> 1); - ret = lsm6ds3tr_c_write_reg( - ctx, LSM6DS3TR_C_MASTER_CONFIG, (uint8_t*)&master_config, 1); - } - } - } - - return ret; -} - -/** - * @brief Trigger signal for FIFO write operation.[get] - * - * @param ctx Read / write interface definitions - * @param val act on FIFO_CTRL2(timer_pedo_fifo_drdy) - * and MASTER_CONFIG(data_valid_sel_fifo) - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_fifo_write_trigger_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_trigger_fifo_t* val) { - lsm6ds3tr_c_fifo_ctrl2_t fifo_ctrl2; - lsm6ds3tr_c_master_config_t master_config; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2, (uint8_t*)&fifo_ctrl2, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, (uint8_t*)&master_config, 1); - - switch((fifo_ctrl2.timer_pedo_fifo_drdy << 1) + fifo_ctrl2.timer_pedo_fifo_drdy) { - case LSM6DS3TR_C_TRG_XL_GY_DRDY: - *val = LSM6DS3TR_C_TRG_XL_GY_DRDY; - break; - - case LSM6DS3TR_C_TRG_STEP_DETECT: - *val = LSM6DS3TR_C_TRG_STEP_DETECT; - break; - - case LSM6DS3TR_C_TRG_SH_DRDY: - *val = LSM6DS3TR_C_TRG_SH_DRDY; - break; - - default: - *val = LSM6DS3TR_C_TRG_SH_ND; - break; - } - } - - return ret; -} - -/** - * @brief Enable pedometer step counter and timestamp as 4th - * FIFO data set.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of timer_pedo_fifo_en in reg FIFO_CTRL2 - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_fifo_pedo_and_timestamp_batch_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_fifo_ctrl2_t fifo_ctrl2; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2, (uint8_t*)&fifo_ctrl2, 1); - - if(ret == 0) { - fifo_ctrl2.timer_pedo_fifo_en = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2, (uint8_t*)&fifo_ctrl2, 1); - } - - return ret; -} - -/** - * @brief Enable pedometer step counter and timestamp as 4th - * FIFO data set.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of timer_pedo_fifo_en in reg FIFO_CTRL2 - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_fifo_pedo_and_timestamp_batch_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_fifo_ctrl2_t fifo_ctrl2; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL2, (uint8_t*)&fifo_ctrl2, 1); - *val = fifo_ctrl2.timer_pedo_fifo_en; - - return ret; -} - -/** - * @brief Selects Batching Data Rate (writing frequency in FIFO) for - * accelerometer data.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of dec_fifo_xl in reg FIFO_CTRL3 - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_fifo_xl_batch_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_dec_fifo_xl_t val) { - lsm6ds3tr_c_fifo_ctrl3_t fifo_ctrl3; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL3, (uint8_t*)&fifo_ctrl3, 1); - - if(ret == 0) { - fifo_ctrl3.dec_fifo_xl = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL3, (uint8_t*)&fifo_ctrl3, 1); - } - - return ret; -} - -/** - * @brief Selects Batching Data Rate (writing frequency in FIFO) for - * accelerometer data.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of dec_fifo_xl in reg FIFO_CTRL3 - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_fifo_xl_batch_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_dec_fifo_xl_t* val) { - lsm6ds3tr_c_fifo_ctrl3_t fifo_ctrl3; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL3, (uint8_t*)&fifo_ctrl3, 1); - - switch(fifo_ctrl3.dec_fifo_xl) { - case LSM6DS3TR_C_FIFO_XL_DISABLE: - *val = LSM6DS3TR_C_FIFO_XL_DISABLE; - break; - - case LSM6DS3TR_C_FIFO_XL_NO_DEC: - *val = LSM6DS3TR_C_FIFO_XL_NO_DEC; - break; - - case LSM6DS3TR_C_FIFO_XL_DEC_2: - *val = LSM6DS3TR_C_FIFO_XL_DEC_2; - break; - - case LSM6DS3TR_C_FIFO_XL_DEC_3: - *val = LSM6DS3TR_C_FIFO_XL_DEC_3; - break; - - case LSM6DS3TR_C_FIFO_XL_DEC_4: - *val = LSM6DS3TR_C_FIFO_XL_DEC_4; - break; - - case LSM6DS3TR_C_FIFO_XL_DEC_8: - *val = LSM6DS3TR_C_FIFO_XL_DEC_8; - break; - - case LSM6DS3TR_C_FIFO_XL_DEC_16: - *val = LSM6DS3TR_C_FIFO_XL_DEC_16; - break; - - case LSM6DS3TR_C_FIFO_XL_DEC_32: - *val = LSM6DS3TR_C_FIFO_XL_DEC_32; - break; - - default: - *val = LSM6DS3TR_C_FIFO_XL_DEC_ND; - break; - } - - return ret; -} - -/** - * @brief Selects Batching Data Rate (writing frequency in FIFO) - * for gyroscope data.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of dec_fifo_gyro in reg FIFO_CTRL3 - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_fifo_gy_batch_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_dec_fifo_gyro_t val) { - lsm6ds3tr_c_fifo_ctrl3_t fifo_ctrl3; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL3, (uint8_t*)&fifo_ctrl3, 1); - - if(ret == 0) { - fifo_ctrl3.dec_fifo_gyro = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL3, (uint8_t*)&fifo_ctrl3, 1); - } - - return ret; -} - -/** - * @brief Selects Batching Data Rate (writing frequency in FIFO) - * for gyroscope data.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of dec_fifo_gyro in reg FIFO_CTRL3 - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_fifo_gy_batch_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_dec_fifo_gyro_t* val) { - lsm6ds3tr_c_fifo_ctrl3_t fifo_ctrl3; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL3, (uint8_t*)&fifo_ctrl3, 1); - - switch(fifo_ctrl3.dec_fifo_gyro) { - case LSM6DS3TR_C_FIFO_GY_DISABLE: - *val = LSM6DS3TR_C_FIFO_GY_DISABLE; - break; - - case LSM6DS3TR_C_FIFO_GY_NO_DEC: - *val = LSM6DS3TR_C_FIFO_GY_NO_DEC; - break; - - case LSM6DS3TR_C_FIFO_GY_DEC_2: - *val = LSM6DS3TR_C_FIFO_GY_DEC_2; - break; - - case LSM6DS3TR_C_FIFO_GY_DEC_3: - *val = LSM6DS3TR_C_FIFO_GY_DEC_3; - break; - - case LSM6DS3TR_C_FIFO_GY_DEC_4: - *val = LSM6DS3TR_C_FIFO_GY_DEC_4; - break; - - case LSM6DS3TR_C_FIFO_GY_DEC_8: - *val = LSM6DS3TR_C_FIFO_GY_DEC_8; - break; - - case LSM6DS3TR_C_FIFO_GY_DEC_16: - *val = LSM6DS3TR_C_FIFO_GY_DEC_16; - break; - - case LSM6DS3TR_C_FIFO_GY_DEC_32: - *val = LSM6DS3TR_C_FIFO_GY_DEC_32; - break; - - default: - *val = LSM6DS3TR_C_FIFO_GY_DEC_ND; - break; - } - - return ret; -} - -/** - * @brief Selects Batching Data Rate (writing frequency in FIFO) - * for third data set.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of dec_ds3_fifo in reg FIFO_CTRL4 - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_fifo_dataset_3_batch_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_dec_ds3_fifo_t val) { - lsm6ds3tr_c_fifo_ctrl4_t fifo_ctrl4; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4, (uint8_t*)&fifo_ctrl4, 1); - - if(ret == 0) { - fifo_ctrl4.dec_ds3_fifo = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4, (uint8_t*)&fifo_ctrl4, 1); - } - - return ret; -} - -/** - * @brief Selects Batching Data Rate (writing frequency in FIFO) - * for third data set.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of dec_ds3_fifo in reg FIFO_CTRL4 - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_fifo_dataset_3_batch_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_dec_ds3_fifo_t* val) { - lsm6ds3tr_c_fifo_ctrl4_t fifo_ctrl4; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4, (uint8_t*)&fifo_ctrl4, 1); - - switch(fifo_ctrl4.dec_ds3_fifo) { - case LSM6DS3TR_C_FIFO_DS3_DISABLE: - *val = LSM6DS3TR_C_FIFO_DS3_DISABLE; - break; - - case LSM6DS3TR_C_FIFO_DS3_NO_DEC: - *val = LSM6DS3TR_C_FIFO_DS3_NO_DEC; - break; - - case LSM6DS3TR_C_FIFO_DS3_DEC_2: - *val = LSM6DS3TR_C_FIFO_DS3_DEC_2; - break; - - case LSM6DS3TR_C_FIFO_DS3_DEC_3: - *val = LSM6DS3TR_C_FIFO_DS3_DEC_3; - break; - - case LSM6DS3TR_C_FIFO_DS3_DEC_4: - *val = LSM6DS3TR_C_FIFO_DS3_DEC_4; - break; - - case LSM6DS3TR_C_FIFO_DS3_DEC_8: - *val = LSM6DS3TR_C_FIFO_DS3_DEC_8; - break; - - case LSM6DS3TR_C_FIFO_DS3_DEC_16: - *val = LSM6DS3TR_C_FIFO_DS3_DEC_16; - break; - - case LSM6DS3TR_C_FIFO_DS3_DEC_32: - *val = LSM6DS3TR_C_FIFO_DS3_DEC_32; - break; - - default: - *val = LSM6DS3TR_C_FIFO_DS3_DEC_ND; - break; - } - - return ret; -} - -/** - * @brief Selects Batching Data Rate (writing frequency in FIFO) - * for fourth data set.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of dec_ds4_fifo in reg FIFO_CTRL4 - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_fifo_dataset_4_batch_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_dec_ds4_fifo_t val) { - lsm6ds3tr_c_fifo_ctrl4_t fifo_ctrl4; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4, (uint8_t*)&fifo_ctrl4, 1); - - if(ret == 0) { - fifo_ctrl4.dec_ds4_fifo = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4, (uint8_t*)&fifo_ctrl4, 1); - } - - return ret; -} - -/** - * @brief Selects Batching Data Rate (writing frequency in FIFO) for - * fourth data set.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of dec_ds4_fifo in reg FIFO_CTRL4 - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_fifo_dataset_4_batch_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_dec_ds4_fifo_t* val) { - lsm6ds3tr_c_fifo_ctrl4_t fifo_ctrl4; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4, (uint8_t*)&fifo_ctrl4, 1); - - switch(fifo_ctrl4.dec_ds4_fifo) { - case LSM6DS3TR_C_FIFO_DS4_DISABLE: - *val = LSM6DS3TR_C_FIFO_DS4_DISABLE; - break; - - case LSM6DS3TR_C_FIFO_DS4_NO_DEC: - *val = LSM6DS3TR_C_FIFO_DS4_NO_DEC; - break; - - case LSM6DS3TR_C_FIFO_DS4_DEC_2: - *val = LSM6DS3TR_C_FIFO_DS4_DEC_2; - break; - - case LSM6DS3TR_C_FIFO_DS4_DEC_3: - *val = LSM6DS3TR_C_FIFO_DS4_DEC_3; - break; - - case LSM6DS3TR_C_FIFO_DS4_DEC_4: - *val = LSM6DS3TR_C_FIFO_DS4_DEC_4; - break; - - case LSM6DS3TR_C_FIFO_DS4_DEC_8: - *val = LSM6DS3TR_C_FIFO_DS4_DEC_8; - break; - - case LSM6DS3TR_C_FIFO_DS4_DEC_16: - *val = LSM6DS3TR_C_FIFO_DS4_DEC_16; - break; - - case LSM6DS3TR_C_FIFO_DS4_DEC_32: - *val = LSM6DS3TR_C_FIFO_DS4_DEC_32; - break; - - default: - *val = LSM6DS3TR_C_FIFO_DS4_DEC_ND; - break; - } - - return ret; -} - -/** - * @brief 8-bit data storage in FIFO.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of only_high_data in reg FIFO_CTRL4 - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_fifo_xl_gy_8bit_format_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_fifo_ctrl4_t fifo_ctrl4; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4, (uint8_t*)&fifo_ctrl4, 1); - - if(ret == 0) { - fifo_ctrl4.only_high_data = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4, (uint8_t*)&fifo_ctrl4, 1); - } - - return ret; -} - -/** - * @brief 8-bit data storage in FIFO.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of only_high_data in reg FIFO_CTRL4 - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_fifo_xl_gy_8bit_format_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_fifo_ctrl4_t fifo_ctrl4; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4, (uint8_t*)&fifo_ctrl4, 1); - *val = fifo_ctrl4.only_high_data; - - return ret; -} - -/** - * @brief Sensing chain FIFO stop values memorization at threshold - * level.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of stop_on_fth in reg FIFO_CTRL4 - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_fifo_stop_on_wtm_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_fifo_ctrl4_t fifo_ctrl4; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4, (uint8_t*)&fifo_ctrl4, 1); - - if(ret == 0) { - fifo_ctrl4.stop_on_fth = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4, (uint8_t*)&fifo_ctrl4, 1); - } - - return ret; -} - -/** - * @brief Sensing chain FIFO stop values memorization at threshold - * level.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of stop_on_fth in reg FIFO_CTRL4 - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_fifo_stop_on_wtm_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_fifo_ctrl4_t fifo_ctrl4; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL4, (uint8_t*)&fifo_ctrl4, 1); - *val = fifo_ctrl4.stop_on_fth; - - return ret; -} - -/** - * @brief FIFO mode selection.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of fifo_mode in reg FIFO_CTRL5 - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_fifo_mode_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_fifo_mode_t val) { - lsm6ds3tr_c_fifo_ctrl5_t fifo_ctrl5; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL5, (uint8_t*)&fifo_ctrl5, 1); - - if(ret == 0) { - fifo_ctrl5.fifo_mode = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL5, (uint8_t*)&fifo_ctrl5, 1); - } - - return ret; -} - -/** - * @brief FIFO mode selection.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of fifo_mode in reg FIFO_CTRL5 - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_fifo_mode_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_fifo_mode_t* val) { - lsm6ds3tr_c_fifo_ctrl5_t fifo_ctrl5; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL5, (uint8_t*)&fifo_ctrl5, 1); - - switch(fifo_ctrl5.fifo_mode) { - case LSM6DS3TR_C_BYPASS_MODE: - *val = LSM6DS3TR_C_BYPASS_MODE; - break; - - case LSM6DS3TR_C_FIFO_MODE: - *val = LSM6DS3TR_C_FIFO_MODE; - break; - - case LSM6DS3TR_C_STREAM_TO_FIFO_MODE: - *val = LSM6DS3TR_C_STREAM_TO_FIFO_MODE; - break; - - case LSM6DS3TR_C_BYPASS_TO_STREAM_MODE: - *val = LSM6DS3TR_C_BYPASS_TO_STREAM_MODE; - break; - - case LSM6DS3TR_C_STREAM_MODE: - *val = LSM6DS3TR_C_STREAM_MODE; - break; - - default: - *val = LSM6DS3TR_C_FIFO_MODE_ND; - break; - } - - return ret; -} - -/** - * @brief FIFO ODR selection, setting FIFO_MODE also.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of odr_fifo in reg FIFO_CTRL5 - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_fifo_data_rate_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_odr_fifo_t val) { - lsm6ds3tr_c_fifo_ctrl5_t fifo_ctrl5; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL5, (uint8_t*)&fifo_ctrl5, 1); - - if(ret == 0) { - fifo_ctrl5.odr_fifo = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_FIFO_CTRL5, (uint8_t*)&fifo_ctrl5, 1); - } - - return ret; -} - -/** - * @brief FIFO ODR selection, setting FIFO_MODE also.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of odr_fifo in reg FIFO_CTRL5 - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_fifo_data_rate_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_odr_fifo_t* val) { - lsm6ds3tr_c_fifo_ctrl5_t fifo_ctrl5; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_FIFO_CTRL5, (uint8_t*)&fifo_ctrl5, 1); - - switch(fifo_ctrl5.odr_fifo) { - case LSM6DS3TR_C_FIFO_DISABLE: - *val = LSM6DS3TR_C_FIFO_DISABLE; - break; - - case LSM6DS3TR_C_FIFO_12Hz5: - *val = LSM6DS3TR_C_FIFO_12Hz5; - break; - - case LSM6DS3TR_C_FIFO_26Hz: - *val = LSM6DS3TR_C_FIFO_26Hz; - break; - - case LSM6DS3TR_C_FIFO_52Hz: - *val = LSM6DS3TR_C_FIFO_52Hz; - break; - - case LSM6DS3TR_C_FIFO_104Hz: - *val = LSM6DS3TR_C_FIFO_104Hz; - break; - - case LSM6DS3TR_C_FIFO_208Hz: - *val = LSM6DS3TR_C_FIFO_208Hz; - break; - - case LSM6DS3TR_C_FIFO_416Hz: - *val = LSM6DS3TR_C_FIFO_416Hz; - break; - - case LSM6DS3TR_C_FIFO_833Hz: - *val = LSM6DS3TR_C_FIFO_833Hz; - break; - - case LSM6DS3TR_C_FIFO_1k66Hz: - *val = LSM6DS3TR_C_FIFO_1k66Hz; - break; - - case LSM6DS3TR_C_FIFO_3k33Hz: - *val = LSM6DS3TR_C_FIFO_3k33Hz; - break; - - case LSM6DS3TR_C_FIFO_6k66Hz: - *val = LSM6DS3TR_C_FIFO_6k66Hz; - break; - - default: - *val = LSM6DS3TR_C_FIFO_RATE_ND; - break; - } - - return ret; -} - -/** - * @} - * - */ - -/** - * @defgroup LSM6DS3TR_C_DEN_functionality - * @brief This section groups all the functions concerning DEN - * functionality. - * @{ - * - */ - -/** - * @brief DEN active level configuration.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of den_lh in reg CTRL5_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_den_polarity_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_den_lh_t val) { - lsm6ds3tr_c_ctrl5_c_t ctrl5_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL5_C, (uint8_t*)&ctrl5_c, 1); - - if(ret == 0) { - ctrl5_c.den_lh = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL5_C, (uint8_t*)&ctrl5_c, 1); - } - - return ret; -} - -/** - * @brief DEN active level configuration.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of den_lh in reg CTRL5_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_den_polarity_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_den_lh_t* val) { - lsm6ds3tr_c_ctrl5_c_t ctrl5_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL5_C, (uint8_t*)&ctrl5_c, 1); - - switch(ctrl5_c.den_lh) { - case LSM6DS3TR_C_DEN_ACT_LOW: - *val = LSM6DS3TR_C_DEN_ACT_LOW; - break; - - case LSM6DS3TR_C_DEN_ACT_HIGH: - *val = LSM6DS3TR_C_DEN_ACT_HIGH; - break; - - default: - *val = LSM6DS3TR_C_DEN_POL_ND; - break; - } - - return ret; -} - -/** - * @brief DEN functionality marking mode[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of den_mode in reg CTRL6_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_den_mode_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_den_mode_t val) { - lsm6ds3tr_c_ctrl6_c_t ctrl6_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL6_C, (uint8_t*)&ctrl6_c, 1); - - if(ret == 0) { - ctrl6_c.den_mode = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL6_C, (uint8_t*)&ctrl6_c, 1); - } - - return ret; -} - -/** - * @brief DEN functionality marking mode[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of den_mode in reg CTRL6_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_den_mode_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_den_mode_t* val) { - lsm6ds3tr_c_ctrl6_c_t ctrl6_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL6_C, (uint8_t*)&ctrl6_c, 1); - - switch(ctrl6_c.den_mode) { - case LSM6DS3TR_C_DEN_DISABLE: - *val = LSM6DS3TR_C_DEN_DISABLE; - break; - - case LSM6DS3TR_C_LEVEL_LETCHED: - *val = LSM6DS3TR_C_LEVEL_LETCHED; - break; - - case LSM6DS3TR_C_LEVEL_TRIGGER: - *val = LSM6DS3TR_C_LEVEL_TRIGGER; - break; - - case LSM6DS3TR_C_EDGE_TRIGGER: - *val = LSM6DS3TR_C_EDGE_TRIGGER; - break; - - default: - *val = LSM6DS3TR_C_DEN_MODE_ND; - break; - } - - return ret; -} - -/** - * @brief Extend DEN functionality to accelerometer sensor.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of den_xl_g in reg CTRL9_XL - * and den_xl_en in CTRL4_C. - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_den_enable_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_den_xl_en_t val) { - lsm6ds3tr_c_ctrl4_c_t ctrl4_c; - lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL9_XL, (uint8_t*)&ctrl9_xl, 1); - - if(ret == 0) { - ctrl9_xl.den_xl_g = (uint8_t)val & 0x01U; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL9_XL, (uint8_t*)&ctrl9_xl, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C, (uint8_t*)&ctrl4_c, 1); - - if(ret == 0) { - ctrl4_c.den_xl_en = (uint8_t)val & 0x02U; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL4_C, (uint8_t*)&ctrl4_c, 1); - } - } - } - - return ret; -} - -/** - * @brief Extend DEN functionality to accelerometer sensor. [get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of den_xl_g in reg CTRL9_XL - * and den_xl_en in CTRL4_C. - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_den_enable_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_den_xl_en_t* val) { - lsm6ds3tr_c_ctrl4_c_t ctrl4_c; - lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL4_C, (uint8_t*)&ctrl4_c, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL9_XL, (uint8_t*)&ctrl9_xl, 1); - - switch((ctrl4_c.den_xl_en << 1) + ctrl9_xl.den_xl_g) { - case LSM6DS3TR_C_STAMP_IN_GY_DATA: - *val = LSM6DS3TR_C_STAMP_IN_GY_DATA; - break; - - case LSM6DS3TR_C_STAMP_IN_XL_DATA: - *val = LSM6DS3TR_C_STAMP_IN_XL_DATA; - break; - - case LSM6DS3TR_C_STAMP_IN_GY_XL_DATA: - *val = LSM6DS3TR_C_STAMP_IN_GY_XL_DATA; - break; - - default: - *val = LSM6DS3TR_C_DEN_STAMP_ND; - break; - } - } - - return ret; -} - -/** - * @brief DEN value stored in LSB of Z-axis.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of den_z in reg CTRL9_XL - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_den_mark_axis_z_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL9_XL, (uint8_t*)&ctrl9_xl, 1); - - if(ret == 0) { - ctrl9_xl.den_z = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL9_XL, (uint8_t*)&ctrl9_xl, 1); - } - - return ret; -} - -/** - * @brief DEN value stored in LSB of Z-axis.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of den_z in reg CTRL9_XL - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_den_mark_axis_z_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL9_XL, (uint8_t*)&ctrl9_xl, 1); - *val = ctrl9_xl.den_z; - - return ret; -} - -/** - * @brief DEN value stored in LSB of Y-axis.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of den_y in reg CTRL9_XL - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_den_mark_axis_y_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL9_XL, (uint8_t*)&ctrl9_xl, 1); - - if(ret == 0) { - ctrl9_xl.den_y = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL9_XL, (uint8_t*)&ctrl9_xl, 1); - } - - return ret; -} - -/** - * @brief DEN value stored in LSB of Y-axis.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of den_y in reg CTRL9_XL - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_den_mark_axis_y_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL9_XL, (uint8_t*)&ctrl9_xl, 1); - *val = ctrl9_xl.den_y; - - return ret; -} - -/** - * @brief DEN value stored in LSB of X-axis.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of den_x in reg CTRL9_XL - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_den_mark_axis_x_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL9_XL, (uint8_t*)&ctrl9_xl, 1); - - if(ret == 0) { - ctrl9_xl.den_x = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL9_XL, (uint8_t*)&ctrl9_xl, 1); - } - - return ret; -} - -/** - * @brief DEN value stored in LSB of X-axis.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of den_x in reg CTRL9_XL - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_den_mark_axis_x_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL9_XL, (uint8_t*)&ctrl9_xl, 1); - *val = ctrl9_xl.den_x; - - return ret; -} - -/** - * @} - * - */ - -/** - * @defgroup LSM6DS3TR_C_Pedometer - * @brief This section groups all the functions that manage pedometer. - * @{ - * - */ - -/** - * @brief Reset pedometer step counter.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of pedo_rst_step in reg CTRL10_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_pedo_step_reset_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_ctrl10_c_t ctrl10_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C, (uint8_t*)&ctrl10_c, 1); - - if(ret == 0) { - ctrl10_c.pedo_rst_step = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL10_C, (uint8_t*)&ctrl10_c, 1); - } - - return ret; -} - -/** - * @brief Reset pedometer step counter.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of pedo_rst_step in reg CTRL10_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_pedo_step_reset_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_ctrl10_c_t ctrl10_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C, (uint8_t*)&ctrl10_c, 1); - *val = ctrl10_c.pedo_rst_step; - - return ret; -} - -/** - * @brief Enable pedometer algorithm.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of pedo_en in reg CTRL10_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_pedo_sens_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_ctrl10_c_t ctrl10_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C, (uint8_t*)&ctrl10_c, 1); - - if(ret == 0) { - ctrl10_c.pedo_en = val; - - if(val != 0x00U) { - ctrl10_c.func_en = val; - } - - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL10_C, (uint8_t*)&ctrl10_c, 1); - } - - return ret; -} - -/** - * @brief pedo_sens: Enable pedometer algorithm.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of pedo_en in reg CTRL10_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_pedo_sens_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_ctrl10_c_t ctrl10_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C, (uint8_t*)&ctrl10_c, 1); - *val = ctrl10_c.pedo_en; - - return ret; -} - -/** - * @brief Minimum threshold to detect a peak. Default is 10h.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of ths_min in reg - * CONFIG_PEDO_THS_MIN - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_pedo_threshold_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_config_pedo_ths_min_t config_pedo_ths_min; - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg( - ctx, LSM6DS3TR_C_CONFIG_PEDO_THS_MIN, (uint8_t*)&config_pedo_ths_min, 1); - - if(ret == 0) { - config_pedo_ths_min.ths_min = val; - ret = lsm6ds3tr_c_write_reg( - ctx, LSM6DS3TR_C_CONFIG_PEDO_THS_MIN, (uint8_t*)&config_pedo_ths_min, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - } - - return ret; -} - -/** - * @brief Minimum threshold to detect a peak. Default is 10h.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of ths_min in reg CONFIG_PEDO_THS_MIN - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_pedo_threshold_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_config_pedo_ths_min_t config_pedo_ths_min; - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg( - ctx, LSM6DS3TR_C_CONFIG_PEDO_THS_MIN, (uint8_t*)&config_pedo_ths_min, 1); - - if(ret == 0) { - *val = config_pedo_ths_min.ths_min; - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - - return ret; -} - -/** - * @brief pedo_full_scale: Pedometer data range.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of pedo_fs in - * reg CONFIG_PEDO_THS_MIN - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_pedo_full_scale_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_pedo_fs_t val) { - lsm6ds3tr_c_config_pedo_ths_min_t config_pedo_ths_min; - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg( - ctx, LSM6DS3TR_C_CONFIG_PEDO_THS_MIN, (uint8_t*)&config_pedo_ths_min, 1); - - if(ret == 0) { - config_pedo_ths_min.pedo_fs = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg( - ctx, LSM6DS3TR_C_CONFIG_PEDO_THS_MIN, (uint8_t*)&config_pedo_ths_min, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - } - - return ret; -} - -/** - * @brief Pedometer data range.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of pedo_fs in - * reg CONFIG_PEDO_THS_MIN - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_pedo_full_scale_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_pedo_fs_t* val) { - lsm6ds3tr_c_config_pedo_ths_min_t config_pedo_ths_min; - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg( - ctx, LSM6DS3TR_C_CONFIG_PEDO_THS_MIN, (uint8_t*)&config_pedo_ths_min, 1); - - if(ret == 0) { - switch(config_pedo_ths_min.pedo_fs) { - case LSM6DS3TR_C_PEDO_AT_2g: - *val = LSM6DS3TR_C_PEDO_AT_2g; - break; - - case LSM6DS3TR_C_PEDO_AT_4g: - *val = LSM6DS3TR_C_PEDO_AT_4g; - break; - - default: - *val = LSM6DS3TR_C_PEDO_FS_ND; - break; - } - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - - return ret; -} - -/** - * @brief Pedometer debounce configuration register (r/w).[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of deb_step in reg PEDO_DEB_REG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_pedo_debounce_steps_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_pedo_deb_reg_t pedo_deb_reg; - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_PEDO_DEB_REG, (uint8_t*)&pedo_deb_reg, 1); - - if(ret == 0) { - pedo_deb_reg.deb_step = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_PEDO_DEB_REG, (uint8_t*)&pedo_deb_reg, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - } - - return ret; -} - -/** - * @brief Pedometer debounce configuration register (r/w).[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of deb_step in reg PEDO_DEB_REG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_pedo_debounce_steps_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_pedo_deb_reg_t pedo_deb_reg; - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_PEDO_DEB_REG, (uint8_t*)&pedo_deb_reg, 1); - - if(ret == 0) { - *val = pedo_deb_reg.deb_step; - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - - return ret; -} - -/** - * @brief Debounce time. If the time between two consecutive steps is - * greater than DEB_TIME*80ms, the debouncer is reactivated. - * Default value: 01101[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of deb_time in reg PEDO_DEB_REG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_pedo_timeout_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_pedo_deb_reg_t pedo_deb_reg; - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_PEDO_DEB_REG, (uint8_t*)&pedo_deb_reg, 1); - - if(ret == 0) { - pedo_deb_reg.deb_time = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_PEDO_DEB_REG, (uint8_t*)&pedo_deb_reg, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - } - - return ret; -} - -/** - * @brief Debounce time. If the time between two consecutive steps is - * greater than DEB_TIME*80ms, the debouncer is reactivated. - * Default value: 01101[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of deb_time in reg PEDO_DEB_REG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_pedo_timeout_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_pedo_deb_reg_t pedo_deb_reg; - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_PEDO_DEB_REG, (uint8_t*)&pedo_deb_reg, 1); - - if(ret == 0) { - *val = pedo_deb_reg.deb_time; - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - - return ret; -} - -/** - * @brief Time period register for step detection on delta time (r/w).[set] - * - * @param ctx Read / write interface definitions - * @param buff Buffer that contains data to write - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_pedo_steps_period_set(stmdev_ctx_t* ctx, uint8_t* buff) { - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_STEP_COUNT_DELTA, buff, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - - return ret; -} - -/** - * @brief Time period register for step detection on delta time (r/w).[get] - * - * @param ctx Read / write interface definitions - * @param buff Buffer that stores data read - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_pedo_steps_period_get(stmdev_ctx_t* ctx, uint8_t* buff) { - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_STEP_COUNT_DELTA, buff, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - - return ret; -} - -/** - * @} - * - */ - -/** - * @defgroup LSM6DS3TR_C_significant_motion - * @brief This section groups all the functions that manage the - * significant motion detection. - * @{ - * - */ - -/** - * @brief Enable significant motion detection function.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of sign_motion_en in reg CTRL10_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_motion_sens_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_ctrl10_c_t ctrl10_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C, (uint8_t*)&ctrl10_c, 1); - - if(ret == 0) { - ctrl10_c.sign_motion_en = val; - - if(val != 0x00U) { - ctrl10_c.func_en = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL10_C, (uint8_t*)&ctrl10_c, 1); - } - } - - return ret; -} - -/** - * @brief Enable significant motion detection function.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of sign_motion_en in reg CTRL10_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_motion_sens_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_ctrl10_c_t ctrl10_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C, (uint8_t*)&ctrl10_c, 1); - *val = ctrl10_c.sign_motion_en; - - return ret; -} - -/** - * @brief Significant motion threshold.[set] - * - * @param ctx Read / write interface definitions - * @param buff Buffer that store significant motion threshold. - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_motion_threshold_set(stmdev_ctx_t* ctx, uint8_t* buff) { - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SM_THS, buff, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - - return ret; -} - -/** - * @brief Significant motion threshold.[get] - * - * @param ctx Read / write interface definitions - * @param buff Buffer that store significant motion threshold. - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_motion_threshold_get(stmdev_ctx_t* ctx, uint8_t* buff) { - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SM_THS, buff, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - - return ret; -} - -/** - * @} - * - */ - -/** - * @defgroup LSM6DS3TR_C_tilt_detection - * @brief This section groups all the functions that manage the tilt - * event detection. - * @{ - * - */ - -/** - * @brief Enable tilt calculation.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of tilt_en in reg CTRL10_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_tilt_sens_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_ctrl10_c_t ctrl10_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C, (uint8_t*)&ctrl10_c, 1); - - if(ret == 0) { - ctrl10_c.tilt_en = val; - - if(val != 0x00U) { - ctrl10_c.func_en = val; - } - - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL10_C, (uint8_t*)&ctrl10_c, 1); - } - - return ret; -} - -/** - * @brief Enable tilt calculation.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of tilt_en in reg CTRL10_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_tilt_sens_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_ctrl10_c_t ctrl10_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C, (uint8_t*)&ctrl10_c, 1); - *val = ctrl10_c.tilt_en; - - return ret; -} - -/** - * @brief Enable tilt calculation.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of tilt_en in reg CTRL10_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_wrist_tilt_sens_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_ctrl10_c_t ctrl10_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C, (uint8_t*)&ctrl10_c, 1); - - if(ret == 0) { - ctrl10_c.wrist_tilt_en = val; - - if(val != 0x00U) { - ctrl10_c.func_en = val; - } - - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL10_C, (uint8_t*)&ctrl10_c, 1); - } - - return ret; -} - -/** - * @brief Enable tilt calculation.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of tilt_en in reg CTRL10_C - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_wrist_tilt_sens_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_ctrl10_c_t ctrl10_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C, (uint8_t*)&ctrl10_c, 1); - *val = ctrl10_c.wrist_tilt_en; - - return ret; -} - -/** - * @brief Absolute Wrist Tilt latency register (r/w). - * Absolute wrist tilt latency parameters. - * 1 LSB = 40 ms. Default value: 0Fh (600 ms).[set] - * - * @param ctx Read / write interface definitions - * @param buff Buffer that contains data to write - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_tilt_latency_set(stmdev_ctx_t* ctx, uint8_t* buff) { - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_B); - - if(ret == 0) { - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_A_WRIST_TILT_LAT, buff, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - - return ret; -} - -/** - * @brief Absolute Wrist Tilt latency register (r/w). - * Absolute wrist tilt latency parameters. - * 1 LSB = 40 ms. Default value: 0Fh (600 ms).[get] - * - * @param ctx Read / write interface definitions - * @param buff Buffer that stores data read - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_tilt_latency_get(stmdev_ctx_t* ctx, uint8_t* buff) { - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_B); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_A_WRIST_TILT_LAT, buff, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - - return ret; -} - -/** - * @brief Absolute Wrist Tilt threshold register(r/w). - * Absolute wrist tilt threshold parameters. - * 1 LSB = 15.625 mg.Default value: 20h (500 mg).[set] - * - * @param ctx Read / write interface definitions - * @param buff Buffer that contains data to write - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_tilt_threshold_set(stmdev_ctx_t* ctx, uint8_t* buff) { - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_B); - - if(ret == 0) { - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_A_WRIST_TILT_THS, buff, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - - return ret; -} - -/** - * @brief Absolute Wrist Tilt threshold register(r/w). - * Absolute wrist tilt threshold parameters. - * 1 LSB = 15.625 mg.Default value: 20h (500 mg).[get] - * - * @param ctx Read / write interface definitions - * @param buff Buffer that stores data read - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_tilt_threshold_get(stmdev_ctx_t* ctx, uint8_t* buff) { - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_B); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_A_WRIST_TILT_THS, buff, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - - return ret; -} - -/** - * @brief Absolute Wrist Tilt mask register (r/w).[set] - * - * @param ctx Read / write interface definitions - * @param val Registers A_WRIST_TILT_MASK - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_tilt_src_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_a_wrist_tilt_mask_t* val) { - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_B); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_A_WRIST_TILT_MASK, (uint8_t*)val, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - - return ret; -} - -/** - * @brief Absolute Wrist Tilt mask register (r/w).[get] - * - * @param ctx Read / write interface definitions - * @param val Registers A_WRIST_TILT_MASK - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_tilt_src_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_a_wrist_tilt_mask_t* val) { - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_B); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_A_WRIST_TILT_MASK, (uint8_t*)val, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - - return ret; -} - -/** - * @} - * - */ - -/** - * @defgroup LSM6DS3TR_C_ magnetometer_sensor - * @brief This section groups all the functions that manage additional - * magnetometer sensor. - * @{ - * - */ - -/** - * @brief Enable soft-iron correction algorithm for magnetometer.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of soft_en in reg CTRL9_XL - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_mag_soft_iron_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL9_XL, (uint8_t*)&ctrl9_xl, 1); - - if(ret == 0) { - ctrl9_xl.soft_en = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL9_XL, (uint8_t*)&ctrl9_xl, 1); - } - - return ret; -} - -/** - * @brief Enable soft-iron correction algorithm for magnetometer.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of soft_en in reg CTRL9_XL - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_mag_soft_iron_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL9_XL, (uint8_t*)&ctrl9_xl, 1); - *val = ctrl9_xl.soft_en; - - return ret; -} - -/** - * @brief Enable hard-iron correction algorithm for magnetometer.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of iron_en in reg MASTER_CONFIG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_mag_hard_iron_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_master_config_t master_config; - lsm6ds3tr_c_ctrl10_c_t ctrl10_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, (uint8_t*)&master_config, 1); - - if(ret == 0) { - master_config.iron_en = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, (uint8_t*)&master_config, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C, (uint8_t*)&ctrl10_c, 1); - - if(ret == 0) { - if(val != 0x00U) { - ctrl10_c.func_en = val; - } - - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL10_C, (uint8_t*)&ctrl10_c, 1); - } - } - } - - return ret; -} - -/** - * @brief Enable hard-iron correction algorithm for magnetometer.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of iron_en in reg MASTER_CONFIG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_mag_hard_iron_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_master_config_t master_config; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, (uint8_t*)&master_config, 1); - *val = master_config.iron_en; - - return ret; -} - -/** - * @brief Soft iron 3x3 matrix. Value are expressed in sign-module format. - * (Es. SVVVVVVVb where S is the sign 0/+1/- and V is the value).[set] - * - * @param ctx Read / write interface definitions - * @param buff Buffer that contains data to write - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_mag_soft_iron_mat_set(stmdev_ctx_t* ctx, uint8_t* buff) { - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MAG_SI_XX, buff, 9); - - if(ret == 0) { - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - - return ret; -} - -/** - * @brief Soft iron 3x3 matrix. Value are expressed in sign-module format. - * (Es. SVVVVVVVb where S is the sign 0/+1/- and V is the value).[get] - * - * @param ctx Read / write interface definitions - * @param buff Buffer that stores data read - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_mag_soft_iron_mat_get(stmdev_ctx_t* ctx, uint8_t* buff) { - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MAG_SI_XX, buff, 9); - - if(ret == 0) { - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - - return ret; -} - -/** - * @brief Offset for hard-iron compensation register (r/w). The value is - * expressed as a 16-bit word in two’s complement.[set] - * - * @param ctx Read / write interface definitions - * @param buff Buffer that contains data to write - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_mag_offset_set(stmdev_ctx_t* ctx, int16_t* val) { - uint8_t buff[6]; - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - buff[1] = (uint8_t)((uint16_t)val[0] / 256U); - buff[0] = (uint8_t)((uint16_t)val[0] - (buff[1] * 256U)); - buff[3] = (uint8_t)((uint16_t)val[1] / 256U); - buff[2] = (uint8_t)((uint16_t)val[1] - (buff[3] * 256U)); - buff[5] = (uint8_t)((uint16_t)val[2] / 256U); - buff[4] = (uint8_t)((uint16_t)val[2] - (buff[5] * 256U)); - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MAG_OFFX_L, buff, 6); - - if(ret == 0) { - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - - return ret; -} - -/** - * @brief Offset for hard-iron compensation register(r/w). - * The value is expressed as a 16-bit word in two’s complement.[get] - * - * @param ctx Read / write interface definitions - * @param buff Buffer that stores data read - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_mag_offset_get(stmdev_ctx_t* ctx, int16_t* val) { - uint8_t buff[6]; - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MAG_OFFX_L, buff, 6); - - if(ret == 0) { - val[0] = (int16_t)buff[1]; - val[0] = (val[0] * 256) + (int16_t)buff[0]; - val[1] = (int16_t)buff[3]; - val[1] = (val[1] * 256) + (int16_t)buff[2]; - val[2] = (int16_t)buff[5]; - val[2] = (val[2] * 256) + (int16_t)buff[4]; - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - - return ret; -} - -/** - * @} - * - */ - -/** - * @defgroup LSM6DS3TR_C_Sensor_hub - * @brief This section groups all the functions that manage the sensor - * hub functionality. - * @{ - * - */ - -/** - * @brief Enable function.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values func_en - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_func_en_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_ctrl10_c_t ctrl10_c; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_CTRL10_C, (uint8_t*)&ctrl10_c, 1); - - if(ret == 0) { - ctrl10_c.func_en = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_CTRL10_C, (uint8_t*)&ctrl10_c, 1); - } - - return ret; -} - -/** - * @brief Sensor synchronization time frame with the step of 500 ms and - * full range of 5s. Unsigned 8-bit.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of tph in reg SENSOR_SYNC_TIME_FRAME - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_sync_sens_frame_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_sensor_sync_time_frame_t sensor_sync_time_frame; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg( - ctx, LSM6DS3TR_C_SENSOR_SYNC_TIME_FRAME, (uint8_t*)&sensor_sync_time_frame, 1); - - if(ret == 0) { - sensor_sync_time_frame.tph = val; - ret = lsm6ds3tr_c_write_reg( - ctx, LSM6DS3TR_C_SENSOR_SYNC_TIME_FRAME, (uint8_t*)&sensor_sync_time_frame, 1); - } - - return ret; -} - -/** - * @brief Sensor synchronization time frame with the step of 500 ms and - * full range of 5s. Unsigned 8-bit.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of tph in reg SENSOR_SYNC_TIME_FRAME - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_sync_sens_frame_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_sensor_sync_time_frame_t sensor_sync_time_frame; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg( - ctx, LSM6DS3TR_C_SENSOR_SYNC_TIME_FRAME, (uint8_t*)&sensor_sync_time_frame, 1); - *val = sensor_sync_time_frame.tph; - - return ret; -} - -/** - * @brief Resolution ratio of error code for sensor synchronization.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of rr in reg SENSOR_SYNC_RES_RATIO - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_sync_sens_ratio_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_rr_t val) { - lsm6ds3tr_c_sensor_sync_res_ratio_t sensor_sync_res_ratio; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg( - ctx, LSM6DS3TR_C_SENSOR_SYNC_RES_RATIO, (uint8_t*)&sensor_sync_res_ratio, 1); - - if(ret == 0) { - sensor_sync_res_ratio.rr = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg( - ctx, LSM6DS3TR_C_SENSOR_SYNC_RES_RATIO, (uint8_t*)&sensor_sync_res_ratio, 1); - } - - return ret; -} - -/** - * @brief Resolution ratio of error code for sensor synchronization.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of rr in reg SENSOR_SYNC_RES_RATIO - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_sync_sens_ratio_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_rr_t* val) { - lsm6ds3tr_c_sensor_sync_res_ratio_t sensor_sync_res_ratio; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg( - ctx, LSM6DS3TR_C_SENSOR_SYNC_RES_RATIO, (uint8_t*)&sensor_sync_res_ratio, 1); - - switch(sensor_sync_res_ratio.rr) { - case LSM6DS3TR_C_RES_RATIO_2_11: - *val = LSM6DS3TR_C_RES_RATIO_2_11; - break; - - case LSM6DS3TR_C_RES_RATIO_2_12: - *val = LSM6DS3TR_C_RES_RATIO_2_12; - break; - - case LSM6DS3TR_C_RES_RATIO_2_13: - *val = LSM6DS3TR_C_RES_RATIO_2_13; - break; - - case LSM6DS3TR_C_RES_RATIO_2_14: - *val = LSM6DS3TR_C_RES_RATIO_2_14; - break; - - default: - *val = LSM6DS3TR_C_RES_RATIO_ND; - break; - } - - return ret; -} - -/** - * @brief Sensor hub I2C master enable.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of master_on in reg MASTER_CONFIG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_master_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_master_config_t master_config; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, (uint8_t*)&master_config, 1); - - if(ret == 0) { - master_config.master_on = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, (uint8_t*)&master_config, 1); - } - - return ret; -} - -/** - * @brief Sensor hub I2C master enable.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of master_on in reg MASTER_CONFIG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_master_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_master_config_t master_config; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, (uint8_t*)&master_config, 1); - *val = master_config.master_on; - - return ret; -} - -/** - * @brief I2C interface pass-through.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of pass_through_mode in reg MASTER_CONFIG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_pass_through_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_master_config_t master_config; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, (uint8_t*)&master_config, 1); - - if(ret == 0) { - master_config.pass_through_mode = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, (uint8_t*)&master_config, 1); - } - - return ret; -} - -/** - * @brief I2C interface pass-through.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of pass_through_mode in reg MASTER_CONFIG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_pass_through_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_master_config_t master_config; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, (uint8_t*)&master_config, 1); - *val = master_config.pass_through_mode; - - return ret; -} - -/** - * @brief Master I2C pull-up enable/disable.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of pull_up_en in reg MASTER_CONFIG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_pin_mode_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_pull_up_en_t val) { - lsm6ds3tr_c_master_config_t master_config; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, (uint8_t*)&master_config, 1); - - if(ret == 0) { - master_config.pull_up_en = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, (uint8_t*)&master_config, 1); - } - - return ret; -} - -/** - * @brief Master I2C pull-up enable/disable.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of pull_up_en in reg MASTER_CONFIG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_pin_mode_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_pull_up_en_t* val) { - lsm6ds3tr_c_master_config_t master_config; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, (uint8_t*)&master_config, 1); - - switch(master_config.pull_up_en) { - case LSM6DS3TR_C_EXT_PULL_UP: - *val = LSM6DS3TR_C_EXT_PULL_UP; - break; - - case LSM6DS3TR_C_INTERNAL_PULL_UP: - *val = LSM6DS3TR_C_INTERNAL_PULL_UP; - break; - - default: - *val = LSM6DS3TR_C_SH_PIN_MODE; - break; - } - - return ret; -} - -/** - * @brief Sensor hub trigger signal selection.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of start_config in reg MASTER_CONFIG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_syncro_mode_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_start_config_t val) { - lsm6ds3tr_c_master_config_t master_config; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, (uint8_t*)&master_config, 1); - - if(ret == 0) { - master_config.start_config = (uint8_t)val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, (uint8_t*)&master_config, 1); - } - - return ret; -} - -/** - * @brief Sensor hub trigger signal selection.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of start_config in reg MASTER_CONFIG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_syncro_mode_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_start_config_t* val) { - lsm6ds3tr_c_master_config_t master_config; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, (uint8_t*)&master_config, 1); - - switch(master_config.start_config) { - case LSM6DS3TR_C_XL_GY_DRDY: - *val = LSM6DS3TR_C_XL_GY_DRDY; - break; - - case LSM6DS3TR_C_EXT_ON_INT2_PIN: - *val = LSM6DS3TR_C_EXT_ON_INT2_PIN; - break; - - default: - *val = LSM6DS3TR_C_SH_SYNCRO_ND; - break; - } - - return ret; -} - -/** - * @brief Manage the Master DRDY signal on INT1 pad.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of drdy_on_int1 in reg MASTER_CONFIG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_drdy_on_int1_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_master_config_t master_config; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, (uint8_t*)&master_config, 1); - - if(ret == 0) { - master_config.drdy_on_int1 = val; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, (uint8_t*)&master_config, 1); - } - - return ret; -} - -/** - * @brief Manage the Master DRDY signal on INT1 pad.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of drdy_on_int1 in reg MASTER_CONFIG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_drdy_on_int1_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_master_config_t master_config; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CONFIG, (uint8_t*)&master_config, 1); - *val = master_config.drdy_on_int1; - - return ret; -} - -/** - * @brief Sensor hub output registers.[get] - * - * @param ctx Read / write interface definitions - * @param val Structure of registers from SENSORHUB1_REG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_read_data_raw_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_emb_sh_read_t* val) { - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SENSORHUB1_REG, (uint8_t*)&(val->sh_byte_1), 12); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg( - ctx, LSM6DS3TR_C_SENSORHUB13_REG, (uint8_t*)&(val->sh_byte_13), 6); - } - - return ret; -} - -/** - * @brief Master command code used for stamping for sensor sync.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of master_cmd_code in - * reg MASTER_CMD_CODE - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_cmd_sens_sync_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_master_cmd_code_t master_cmd_code; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CMD_CODE, (uint8_t*)&master_cmd_code, 1); - - if(ret == 0) { - master_cmd_code.master_cmd_code = val; - ret = - lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_MASTER_CMD_CODE, (uint8_t*)&master_cmd_code, 1); - } - - return ret; -} - -/** - * @brief Master command code used for stamping for sensor sync.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of master_cmd_code in - * reg MASTER_CMD_CODE - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_cmd_sens_sync_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_master_cmd_code_t master_cmd_code; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_MASTER_CMD_CODE, (uint8_t*)&master_cmd_code, 1); - *val = master_cmd_code.master_cmd_code; - - return ret; -} - -/** - * @brief Error code used for sensor synchronization.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of error_code in - * reg SENS_SYNC_SPI_ERROR_CODE. - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_spi_sync_error_set(stmdev_ctx_t* ctx, uint8_t val) { - lsm6ds3tr_c_sens_sync_spi_error_code_t sens_sync_spi_error_code; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg( - ctx, LSM6DS3TR_C_SENS_SYNC_SPI_ERROR_CODE, (uint8_t*)&sens_sync_spi_error_code, 1); - - if(ret == 0) { - sens_sync_spi_error_code.error_code = val; - ret = lsm6ds3tr_c_write_reg( - ctx, LSM6DS3TR_C_SENS_SYNC_SPI_ERROR_CODE, (uint8_t*)&sens_sync_spi_error_code, 1); - } - - return ret; -} - -/** - * @brief Error code used for sensor synchronization.[get] - * - * @param ctx Read / write interface definitions - * @param val Change the values of error_code in - * reg SENS_SYNC_SPI_ERROR_CODE. - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_spi_sync_error_get(stmdev_ctx_t* ctx, uint8_t* val) { - lsm6ds3tr_c_sens_sync_spi_error_code_t sens_sync_spi_error_code; - int32_t ret; - - ret = lsm6ds3tr_c_read_reg( - ctx, LSM6DS3TR_C_SENS_SYNC_SPI_ERROR_CODE, (uint8_t*)&sens_sync_spi_error_code, 1); - *val = sens_sync_spi_error_code.error_code; - - return ret; -} - -/** - * @brief Number of external sensors to be read by the sensor hub.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of aux_sens_on in reg SLAVE0_CONFIG. - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_num_of_dev_connected_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_aux_sens_on_t val) { - lsm6ds3tr_c_slave0_config_t slave0_config; - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE0_CONFIG, (uint8_t*)&slave0_config, 1); - - if(ret == 0) { - slave0_config.aux_sens_on = (uint8_t)val; - ret = - lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLAVE0_CONFIG, (uint8_t*)&slave0_config, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - } - - return ret; -} - -/** - * @brief Number of external sensors to be read by the sensor hub.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of aux_sens_on in reg SLAVE0_CONFIG. - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t - lsm6ds3tr_c_sh_num_of_dev_connected_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_aux_sens_on_t* val) { - lsm6ds3tr_c_slave0_config_t slave0_config; - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE0_CONFIG, (uint8_t*)&slave0_config, 1); - - if(ret == 0) { - switch(slave0_config.aux_sens_on) { - case LSM6DS3TR_C_SLV_0: - *val = LSM6DS3TR_C_SLV_0; - break; - - case LSM6DS3TR_C_SLV_0_1: - *val = LSM6DS3TR_C_SLV_0_1; - break; - - case LSM6DS3TR_C_SLV_0_1_2: - *val = LSM6DS3TR_C_SLV_0_1_2; - break; - - case LSM6DS3TR_C_SLV_0_1_2_3: - *val = LSM6DS3TR_C_SLV_0_1_2_3; - break; - - default: - *val = LSM6DS3TR_C_SLV_EN_ND; - break; - } - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - - return ret; -} - -/** - * @brief Configure slave 0 for perform a write.[set] - * - * @param ctx Read / write interface definitions - * @param val Structure that contain: - * - uint8_t slv_add; 8 bit i2c device address - * - uint8_t slv_subadd; 8 bit register device address - * - uint8_t slv_data; 8 bit data to write - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_cfg_write(stmdev_ctx_t* ctx, lsm6ds3tr_c_sh_cfg_write_t* val) { - lsm6ds3tr_c_slv0_add_t slv0_add; - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - slv0_add.slave0_add = val->slv0_add; - slv0_add.rw_0 = 0; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLV0_ADD, (uint8_t*)&slv0_add, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLV0_SUBADD, &(val->slv0_subadd), 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_write_reg( - ctx, LSM6DS3TR_C_DATAWRITE_SRC_MODE_SUB_SLV0, &(val->slv0_data), 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - } - } - - return ret; -} - -/** - * @brief Configure slave 0 for perform a read.[get] - * - * @param ctx Read / write interface definitions - * @param val Structure that contain: - * - uint8_t slv_add; 8 bit i2c device address - * - uint8_t slv_subadd; 8 bit register device address - * - uint8_t slv_len; num of bit to read - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_slv0_cfg_read(stmdev_ctx_t* ctx, lsm6ds3tr_c_sh_cfg_read_t* val) { - lsm6ds3tr_c_slave0_config_t slave0_config; - lsm6ds3tr_c_slv0_add_t slv0_add; - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - slv0_add.slave0_add = val->slv_add; - slv0_add.rw_0 = 1; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLV0_ADD, (uint8_t*)&slv0_add, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLV0_SUBADD, &(val->slv_subadd), 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg( - ctx, LSM6DS3TR_C_SLAVE0_CONFIG, (uint8_t*)&slave0_config, 1); - slave0_config.slave0_numop = val->slv_len; - - if(ret == 0) { - ret = lsm6ds3tr_c_write_reg( - ctx, LSM6DS3TR_C_SLAVE0_CONFIG, (uint8_t*)&slave0_config, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - } - } - } - - return ret; -} - -/** - * @brief Configure slave 1 for perform a read.[get] - * - * @param ctx Read / write interface definitions - * @param val Structure that contain: - * - uint8_t slv_add; 8 bit i2c device address - * - uint8_t slv_subadd; 8 bit register device address - * - uint8_t slv_len; num of bit to read - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_slv1_cfg_read(stmdev_ctx_t* ctx, lsm6ds3tr_c_sh_cfg_read_t* val) { - lsm6ds3tr_c_slave1_config_t slave1_config; - lsm6ds3tr_c_slv1_add_t slv1_add; - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - slv1_add.slave1_add = val->slv_add; - slv1_add.r_1 = 1; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLV1_ADD, (uint8_t*)&slv1_add, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLV1_SUBADD, &(val->slv_subadd), 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg( - ctx, LSM6DS3TR_C_SLAVE1_CONFIG, (uint8_t*)&slave1_config, 1); - slave1_config.slave1_numop = val->slv_len; - - if(ret == 0) { - ret = lsm6ds3tr_c_write_reg( - ctx, LSM6DS3TR_C_SLAVE1_CONFIG, (uint8_t*)&slave1_config, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - } - } - } - - return ret; -} - -/** - * @brief Configure slave 2 for perform a read.[get] - * - * @param ctx Read / write interface definitions - * @param val Structure that contain: - * - uint8_t slv_add; 8 bit i2c device address - * - uint8_t slv_subadd; 8 bit register device address - * - uint8_t slv_len; num of bit to read - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_slv2_cfg_read(stmdev_ctx_t* ctx, lsm6ds3tr_c_sh_cfg_read_t* val) { - lsm6ds3tr_c_slv2_add_t slv2_add; - lsm6ds3tr_c_slave2_config_t slave2_config; - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - slv2_add.slave2_add = val->slv_add; - slv2_add.r_2 = 1; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLV2_ADD, (uint8_t*)&slv2_add, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLV2_SUBADD, &(val->slv_subadd), 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg( - ctx, LSM6DS3TR_C_SLAVE2_CONFIG, (uint8_t*)&slave2_config, 1); - - if(ret == 0) { - slave2_config.slave2_numop = val->slv_len; - ret = lsm6ds3tr_c_write_reg( - ctx, LSM6DS3TR_C_SLAVE2_CONFIG, (uint8_t*)&slave2_config, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - } - } - } - - return ret; -} - -/** - * @brief Configure slave 3 for perform a read.[get] - * - * @param ctx Read / write interface definitions - * @param val Structure that contain: - * - uint8_t slv_add; 8 bit i2c device address - * - uint8_t slv_subadd; 8 bit register device address - * - uint8_t slv_len; num of bit to read - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_slv3_cfg_read(stmdev_ctx_t* ctx, lsm6ds3tr_c_sh_cfg_read_t* val) { - lsm6ds3tr_c_slave3_config_t slave3_config; - lsm6ds3tr_c_slv3_add_t slv3_add; - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - slv3_add.slave3_add = val->slv_add; - slv3_add.r_3 = 1; - ret = lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLV3_ADD, (uint8_t*)&slv3_add, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_write_reg( - ctx, LSM6DS3TR_C_SLV3_SUBADD, (uint8_t*)&(val->slv_subadd), 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg( - ctx, LSM6DS3TR_C_SLAVE3_CONFIG, (uint8_t*)&slave3_config, 1); - - if(ret == 0) { - slave3_config.slave3_numop = val->slv_len; - ret = lsm6ds3tr_c_write_reg( - ctx, LSM6DS3TR_C_SLAVE3_CONFIG, (uint8_t*)&slave3_config, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - } - } - } - - return ret; -} - -/** - * @brief Decimation of read operation on Slave 0 starting from the - * sensor hub trigger.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of slave0_rate in reg SLAVE0_CONFIG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_slave_0_dec_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_slave0_rate_t val) { - lsm6ds3tr_c_slave0_config_t slave0_config; - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE0_CONFIG, (uint8_t*)&slave0_config, 1); - - if(ret == 0) { - slave0_config.slave0_rate = (uint8_t)val; - ret = - lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLAVE0_CONFIG, (uint8_t*)&slave0_config, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - } - - return ret; -} - -/** - * @brief Decimation of read operation on Slave 0 starting from the - * sensor hub trigger.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of slave0_rate in reg SLAVE0_CONFIG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_slave_0_dec_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_slave0_rate_t* val) { - lsm6ds3tr_c_slave0_config_t slave0_config; - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE0_CONFIG, (uint8_t*)&slave0_config, 1); - - if(ret == 0) { - switch(slave0_config.slave0_rate) { - case LSM6DS3TR_C_SL0_NO_DEC: - *val = LSM6DS3TR_C_SL0_NO_DEC; - break; - - case LSM6DS3TR_C_SL0_DEC_2: - *val = LSM6DS3TR_C_SL0_DEC_2; - break; - - case LSM6DS3TR_C_SL0_DEC_4: - *val = LSM6DS3TR_C_SL0_DEC_4; - break; - - case LSM6DS3TR_C_SL0_DEC_8: - *val = LSM6DS3TR_C_SL0_DEC_8; - break; - - default: - *val = LSM6DS3TR_C_SL0_DEC_ND; - break; - } - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - - return ret; -} - -/** - * @brief Slave 0 write operation is performed only at the first sensor - * hub cycle. - * This is effective if the Aux_sens_on[1:0] field in - * SLAVE0_CONFIG(04h) is set to a value other than 00.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of write_once in reg SLAVE1_CONFIG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_write_mode_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_write_once_t val) { - lsm6ds3tr_c_slave1_config_t slave1_config; - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE1_CONFIG, (uint8_t*)&slave1_config, 1); - slave1_config.write_once = (uint8_t)val; - - if(ret == 0) { - ret = - lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLAVE1_CONFIG, (uint8_t*)&slave1_config, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - } - - return ret; -} - -/** - * @brief Slave 0 write operation is performed only at the first sensor - * hub cycle. - * This is effective if the Aux_sens_on[1:0] field in - * SLAVE0_CONFIG(04h) is set to a value other than 00.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of write_once in reg SLAVE1_CONFIG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_write_mode_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_write_once_t* val) { - lsm6ds3tr_c_slave1_config_t slave1_config; - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE1_CONFIG, (uint8_t*)&slave1_config, 1); - - if(ret == 0) { - switch(slave1_config.write_once) { - case LSM6DS3TR_C_EACH_SH_CYCLE: - *val = LSM6DS3TR_C_EACH_SH_CYCLE; - break; - - case LSM6DS3TR_C_ONLY_FIRST_CYCLE: - *val = LSM6DS3TR_C_ONLY_FIRST_CYCLE; - break; - - default: - *val = LSM6DS3TR_C_SH_WR_MODE_ND; - break; - } - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - - return ret; -} - -/** - * @brief Decimation of read operation on Slave 1 starting from the - * sensor hub trigger.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of slave1_rate in reg SLAVE1_CONFIG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_slave_1_dec_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_slave1_rate_t val) { - lsm6ds3tr_c_slave1_config_t slave1_config; - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE1_CONFIG, (uint8_t*)&slave1_config, 1); - - if(ret == 0) { - slave1_config.slave1_rate = (uint8_t)val; - ret = - lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLAVE1_CONFIG, (uint8_t*)&slave1_config, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - } - - return ret; -} - -/** - * @brief Decimation of read operation on Slave 1 starting from the - * sensor hub trigger.[get] - * - * @param ctx Read / write interface definitions reg SLAVE1_CONFIG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_slave_1_dec_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_slave1_rate_t* val) { - lsm6ds3tr_c_slave1_config_t slave1_config; - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE1_CONFIG, (uint8_t*)&slave1_config, 1); - - if(ret == 0) { - switch(slave1_config.slave1_rate) { - case LSM6DS3TR_C_SL1_NO_DEC: - *val = LSM6DS3TR_C_SL1_NO_DEC; - break; - - case LSM6DS3TR_C_SL1_DEC_2: - *val = LSM6DS3TR_C_SL1_DEC_2; - break; - - case LSM6DS3TR_C_SL1_DEC_4: - *val = LSM6DS3TR_C_SL1_DEC_4; - break; - - case LSM6DS3TR_C_SL1_DEC_8: - *val = LSM6DS3TR_C_SL1_DEC_8; - break; - - default: - *val = LSM6DS3TR_C_SL1_DEC_ND; - break; - } - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - - return ret; -} - -/** - * @brief Decimation of read operation on Slave 2 starting from the - * sensor hub trigger.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of slave2_rate in reg SLAVE2_CONFIG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_slave_2_dec_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_slave2_rate_t val) { - lsm6ds3tr_c_slave2_config_t slave2_config; - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE2_CONFIG, (uint8_t*)&slave2_config, 1); - - if(ret == 0) { - slave2_config.slave2_rate = (uint8_t)val; - ret = - lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLAVE2_CONFIG, (uint8_t*)&slave2_config, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - } - - return ret; -} - -/** - * @brief Decimation of read operation on Slave 2 starting from the - * sensor hub trigger.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of slave2_rate in reg SLAVE2_CONFIG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_slave_2_dec_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_slave2_rate_t* val) { - lsm6ds3tr_c_slave2_config_t slave2_config; - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE2_CONFIG, (uint8_t*)&slave2_config, 1); - - if(ret == 0) { - switch(slave2_config.slave2_rate) { - case LSM6DS3TR_C_SL2_NO_DEC: - *val = LSM6DS3TR_C_SL2_NO_DEC; - break; - - case LSM6DS3TR_C_SL2_DEC_2: - *val = LSM6DS3TR_C_SL2_DEC_2; - break; - - case LSM6DS3TR_C_SL2_DEC_4: - *val = LSM6DS3TR_C_SL2_DEC_4; - break; - - case LSM6DS3TR_C_SL2_DEC_8: - *val = LSM6DS3TR_C_SL2_DEC_8; - break; - - default: - *val = LSM6DS3TR_C_SL2_DEC_ND; - break; - } - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - - return ret; -} - -/** - * @brief Decimation of read operation on Slave 3 starting from the - * sensor hub trigger.[set] - * - * @param ctx Read / write interface definitions - * @param val Change the values of slave3_rate in reg SLAVE3_CONFIG - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_slave_3_dec_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_slave3_rate_t val) { - lsm6ds3tr_c_slave3_config_t slave3_config; - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE3_CONFIG, (uint8_t*)&slave3_config, 1); - slave3_config.slave3_rate = (uint8_t)val; - - if(ret == 0) { - ret = - lsm6ds3tr_c_write_reg(ctx, LSM6DS3TR_C_SLAVE3_CONFIG, (uint8_t*)&slave3_config, 1); - - if(ret == 0) { - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - } - - return ret; -} - -/** - * @brief Decimation of read operation on Slave 3 starting from the - * sensor hub trigger.[get] - * - * @param ctx Read / write interface definitions - * @param val Get the values of slave3_rate in reg SLAVE3_CONFIG. - * @retval Interface status (MANDATORY: return 0 -> no Error). - * - */ -int32_t lsm6ds3tr_c_sh_slave_3_dec_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_slave3_rate_t* val) { - lsm6ds3tr_c_slave3_config_t slave3_config; - int32_t ret; - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_BANK_A); - - if(ret == 0) { - ret = lsm6ds3tr_c_read_reg(ctx, LSM6DS3TR_C_SLAVE3_CONFIG, (uint8_t*)&slave3_config, 1); - - if(ret == 0) { - switch(slave3_config.slave3_rate) { - case LSM6DS3TR_C_SL3_NO_DEC: - *val = LSM6DS3TR_C_SL3_NO_DEC; - break; - - case LSM6DS3TR_C_SL3_DEC_2: - *val = LSM6DS3TR_C_SL3_DEC_2; - break; - - case LSM6DS3TR_C_SL3_DEC_4: - *val = LSM6DS3TR_C_SL3_DEC_4; - break; - - case LSM6DS3TR_C_SL3_DEC_8: - *val = LSM6DS3TR_C_SL3_DEC_8; - break; - - default: - *val = LSM6DS3TR_C_SL3_DEC_ND; - break; - } - - ret = lsm6ds3tr_c_mem_bank_set(ctx, LSM6DS3TR_C_USER_BANK); - } - } - - return ret; -} - -/** - * @} - * - */ - -/** - * @} - * - */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/airmouse/tracking/imu/lsm6ds3tr_c_reg.h b/airmouse/tracking/imu/lsm6ds3tr_c_reg.h deleted file mode 100644 index 8cb592c0da3..00000000000 --- a/airmouse/tracking/imu/lsm6ds3tr_c_reg.h +++ /dev/null @@ -1,2448 +0,0 @@ -/** - ****************************************************************************** - * @file lsm6ds3tr_c_reg.h - * @author Sensors Software Solution Team - * @brief This file contains all the functions prototypes for the - * lsm6ds3tr_c_reg.c driver. - ****************************************************************************** - * @attention - * - *

© Copyright (c) 2021 STMicroelectronics. - * All rights reserved.

- * - * This software component is licensed by ST under BSD 3-Clause license, - * the "License"; You may not use this file except in compliance with the - * License. You may obtain a copy of the License at: - * opensource.org/licenses/BSD-3-Clause - * - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef LSM6DS3TR_C_DRIVER_H -#define LSM6DS3TR_C_DRIVER_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include -#include -#include - -/** @addtogroup LSM6DS3TR_C - * @{ - * - */ - -/** @defgroup Endianness definitions - * @{ - * - */ - -#ifndef DRV_BYTE_ORDER -#ifndef __BYTE_ORDER__ - -#define DRV_LITTLE_ENDIAN 1234 -#define DRV_BIG_ENDIAN 4321 - -/** if _BYTE_ORDER is not defined, choose the endianness of your architecture - * by uncommenting the define which fits your platform endianness - */ -//#define DRV_BYTE_ORDER DRV_BIG_ENDIAN -#define DRV_BYTE_ORDER DRV_LITTLE_ENDIAN - -#else /* defined __BYTE_ORDER__ */ - -#define DRV_LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__ -#define DRV_BIG_ENDIAN __ORDER_BIG_ENDIAN__ -#define DRV_BYTE_ORDER __BYTE_ORDER__ - -#endif /* __BYTE_ORDER__*/ -#endif /* DRV_BYTE_ORDER */ - -/** - * @} - * - */ - -/** @defgroup STMicroelectronics sensors common types - * @{ - * - */ - -#ifndef MEMS_SHARED_TYPES -#define MEMS_SHARED_TYPES - -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t bit0 : 1; - uint8_t bit1 : 1; - uint8_t bit2 : 1; - uint8_t bit3 : 1; - uint8_t bit4 : 1; - uint8_t bit5 : 1; - uint8_t bit6 : 1; - uint8_t bit7 : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t bit7 : 1; - uint8_t bit6 : 1; - uint8_t bit5 : 1; - uint8_t bit4 : 1; - uint8_t bit3 : 1; - uint8_t bit2 : 1; - uint8_t bit1 : 1; - uint8_t bit0 : 1; -#endif /* DRV_BYTE_ORDER */ -} bitwise_t; - -#define PROPERTY_DISABLE (0U) -#define PROPERTY_ENABLE (1U) - -/** @addtogroup Interfaces_Functions - * @brief This section provide a set of functions used to read and - * write a generic register of the device. - * MANDATORY: return 0 -> no Error. - * @{ - * - */ - -typedef int32_t (*stmdev_write_ptr)(void*, uint8_t, const uint8_t*, uint16_t); -typedef int32_t (*stmdev_read_ptr)(void*, uint8_t, uint8_t*, uint16_t); -typedef void (*stmdev_mdelay_ptr)(uint32_t millisec); - -typedef struct { - /** Component mandatory fields **/ - stmdev_write_ptr write_reg; - stmdev_read_ptr read_reg; - /** Component optional fields **/ - stmdev_mdelay_ptr mdelay; - /** Customizable optional pointer **/ - void* handle; -} stmdev_ctx_t; - -/** - * @} - * - */ - -#endif /* MEMS_SHARED_TYPES */ - -#ifndef MEMS_UCF_SHARED_TYPES -#define MEMS_UCF_SHARED_TYPES - -/** @defgroup Generic address-data structure definition - * @brief This structure is useful to load a predefined configuration - * of a sensor. - * You can create a sensor configuration by your own or using - * Unico / Unicleo tools available on STMicroelectronics - * web site. - * - * @{ - * - */ - -typedef struct { - uint8_t address; - uint8_t data; -} ucf_line_t; - -/** - * @} - * - */ - -#endif /* MEMS_UCF_SHARED_TYPES */ - -/** - * @} - * - */ - -/** @defgroup LSM6DS3TR_C_Infos - * @{ - * - */ - -/** I2C Device Address 8 bit format if SA0=0 -> D5 if SA0=1 -> D7 **/ -#define LSM6DS3TR_C_I2C_ADD_L 0xD5U -#define LSM6DS3TR_C_I2C_ADD_H 0xD7U - -/** Device Identification (Who am I) **/ -#define LSM6DS3TR_C_ID 0x6AU - -/** - * @} - * - */ - -#define LSM6DS3TR_C_FUNC_CFG_ACCESS 0x01U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t not_used_01 : 5; - uint8_t func_cfg_en : 3; /* func_cfg_en + func_cfg_en_b */ -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t func_cfg_en : 3; /* func_cfg_en + func_cfg_en_b */ - uint8_t not_used_01 : 5; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_func_cfg_access_t; - -#define LSM6DS3TR_C_SENSOR_SYNC_TIME_FRAME 0x04U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t tph : 4; - uint8_t not_used_01 : 4; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t not_used_01 : 4; - uint8_t tph : 4; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_sensor_sync_time_frame_t; - -#define LSM6DS3TR_C_SENSOR_SYNC_RES_RATIO 0x05U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t rr : 2; - uint8_t not_used_01 : 6; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t not_used_01 : 6; - uint8_t rr : 2; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_sensor_sync_res_ratio_t; - -#define LSM6DS3TR_C_FIFO_CTRL1 0x06U -typedef struct { - uint8_t fth : 8; /* + FIFO_CTRL2(fth) */ -} lsm6ds3tr_c_fifo_ctrl1_t; - -#define LSM6DS3TR_C_FIFO_CTRL2 0x07U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t fth : 3; /* + FIFO_CTRL1(fth) */ - uint8_t fifo_temp_en : 1; - uint8_t not_used_01 : 2; - uint8_t timer_pedo_fifo_drdy : 1; - uint8_t timer_pedo_fifo_en : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t timer_pedo_fifo_en : 1; - uint8_t timer_pedo_fifo_drdy : 1; - uint8_t not_used_01 : 2; - uint8_t fifo_temp_en : 1; - uint8_t fth : 3; /* + FIFO_CTRL1(fth) */ -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_fifo_ctrl2_t; - -#define LSM6DS3TR_C_FIFO_CTRL3 0x08U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t dec_fifo_xl : 3; - uint8_t dec_fifo_gyro : 3; - uint8_t not_used_01 : 2; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t not_used_01 : 2; - uint8_t dec_fifo_gyro : 3; - uint8_t dec_fifo_xl : 3; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_fifo_ctrl3_t; - -#define LSM6DS3TR_C_FIFO_CTRL4 0x09U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t dec_ds3_fifo : 3; - uint8_t dec_ds4_fifo : 3; - uint8_t only_high_data : 1; - uint8_t stop_on_fth : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t stop_on_fth : 1; - uint8_t only_high_data : 1; - uint8_t dec_ds4_fifo : 3; - uint8_t dec_ds3_fifo : 3; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_fifo_ctrl4_t; - -#define LSM6DS3TR_C_FIFO_CTRL5 0x0AU -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t fifo_mode : 3; - uint8_t odr_fifo : 4; - uint8_t not_used_01 : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t not_used_01 : 1; - uint8_t odr_fifo : 4; - uint8_t fifo_mode : 3; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_fifo_ctrl5_t; - -#define LSM6DS3TR_C_DRDY_PULSE_CFG_G 0x0BU -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t int2_wrist_tilt : 1; - uint8_t not_used_01 : 6; - uint8_t drdy_pulsed : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t drdy_pulsed : 1; - uint8_t not_used_01 : 6; - uint8_t int2_wrist_tilt : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_drdy_pulse_cfg_g_t; - -#define LSM6DS3TR_C_INT1_CTRL 0x0DU -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t int1_drdy_xl : 1; - uint8_t int1_drdy_g : 1; - uint8_t int1_boot : 1; - uint8_t int1_fth : 1; - uint8_t int1_fifo_ovr : 1; - uint8_t int1_full_flag : 1; - uint8_t int1_sign_mot : 1; - uint8_t int1_step_detector : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t int1_step_detector : 1; - uint8_t int1_sign_mot : 1; - uint8_t int1_full_flag : 1; - uint8_t int1_fifo_ovr : 1; - uint8_t int1_fth : 1; - uint8_t int1_boot : 1; - uint8_t int1_drdy_g : 1; - uint8_t int1_drdy_xl : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_int1_ctrl_t; - -#define LSM6DS3TR_C_INT2_CTRL 0x0EU -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t int2_drdy_xl : 1; - uint8_t int2_drdy_g : 1; - uint8_t int2_drdy_temp : 1; - uint8_t int2_fth : 1; - uint8_t int2_fifo_ovr : 1; - uint8_t int2_full_flag : 1; - uint8_t int2_step_count_ov : 1; - uint8_t int2_step_delta : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t int2_step_delta : 1; - uint8_t int2_step_count_ov : 1; - uint8_t int2_full_flag : 1; - uint8_t int2_fifo_ovr : 1; - uint8_t int2_fth : 1; - uint8_t int2_drdy_temp : 1; - uint8_t int2_drdy_g : 1; - uint8_t int2_drdy_xl : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_int2_ctrl_t; - -#define LSM6DS3TR_C_WHO_AM_I 0x0FU -#define LSM6DS3TR_C_CTRL1_XL 0x10U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t bw0_xl : 1; - uint8_t lpf1_bw_sel : 1; - uint8_t fs_xl : 2; - uint8_t odr_xl : 4; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t odr_xl : 4; - uint8_t fs_xl : 2; - uint8_t lpf1_bw_sel : 1; - uint8_t bw0_xl : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_ctrl1_xl_t; - -#define LSM6DS3TR_C_CTRL2_G 0x11U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t not_used_01 : 1; - uint8_t fs_g : 3; /* fs_g + fs_125 */ - uint8_t odr_g : 4; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t odr_g : 4; - uint8_t fs_g : 3; /* fs_g + fs_125 */ - uint8_t not_used_01 : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_ctrl2_g_t; - -#define LSM6DS3TR_C_CTRL3_C 0x12U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t sw_reset : 1; - uint8_t ble : 1; - uint8_t if_inc : 1; - uint8_t sim : 1; - uint8_t pp_od : 1; - uint8_t h_lactive : 1; - uint8_t bdu : 1; - uint8_t boot : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t boot : 1; - uint8_t bdu : 1; - uint8_t h_lactive : 1; - uint8_t pp_od : 1; - uint8_t sim : 1; - uint8_t if_inc : 1; - uint8_t ble : 1; - uint8_t sw_reset : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_ctrl3_c_t; - -#define LSM6DS3TR_C_CTRL4_C 0x13U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t not_used_01 : 1; - uint8_t lpf1_sel_g : 1; - uint8_t i2c_disable : 1; - uint8_t drdy_mask : 1; - uint8_t den_drdy_int1 : 1; - uint8_t int2_on_int1 : 1; - uint8_t sleep : 1; - uint8_t den_xl_en : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t den_xl_en : 1; - uint8_t sleep : 1; - uint8_t int2_on_int1 : 1; - uint8_t den_drdy_int1 : 1; - uint8_t drdy_mask : 1; - uint8_t i2c_disable : 1; - uint8_t lpf1_sel_g : 1; - uint8_t not_used_01 : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_ctrl4_c_t; - -#define LSM6DS3TR_C_CTRL5_C 0x14U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t st_xl : 2; - uint8_t st_g : 2; - uint8_t den_lh : 1; - uint8_t rounding : 3; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t rounding : 3; - uint8_t den_lh : 1; - uint8_t st_g : 2; - uint8_t st_xl : 2; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_ctrl5_c_t; - -#define LSM6DS3TR_C_CTRL6_C 0x15U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t ftype : 2; - uint8_t not_used_01 : 1; - uint8_t usr_off_w : 1; - uint8_t xl_hm_mode : 1; - uint8_t den_mode : 3; /* trig_en + lvl_en + lvl2_en */ -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t den_mode : 3; /* trig_en + lvl_en + lvl2_en */ - uint8_t xl_hm_mode : 1; - uint8_t usr_off_w : 1; - uint8_t not_used_01 : 1; - uint8_t ftype : 2; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_ctrl6_c_t; - -#define LSM6DS3TR_C_CTRL7_G 0x16U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t not_used_01 : 2; - uint8_t rounding_status : 1; - uint8_t not_used_02 : 1; - uint8_t hpm_g : 2; - uint8_t hp_en_g : 1; - uint8_t g_hm_mode : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t g_hm_mode : 1; - uint8_t hp_en_g : 1; - uint8_t hpm_g : 2; - uint8_t not_used_02 : 1; - uint8_t rounding_status : 1; - uint8_t not_used_01 : 2; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_ctrl7_g_t; - -#define LSM6DS3TR_C_CTRL8_XL 0x17U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t low_pass_on_6d : 1; - uint8_t not_used_01 : 1; - uint8_t hp_slope_xl_en : 1; - uint8_t input_composite : 1; - uint8_t hp_ref_mode : 1; - uint8_t hpcf_xl : 2; - uint8_t lpf2_xl_en : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t lpf2_xl_en : 1; - uint8_t hpcf_xl : 2; - uint8_t hp_ref_mode : 1; - uint8_t input_composite : 1; - uint8_t hp_slope_xl_en : 1; - uint8_t not_used_01 : 1; - uint8_t low_pass_on_6d : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_ctrl8_xl_t; - -#define LSM6DS3TR_C_CTRL9_XL 0x18U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t not_used_01 : 2; - uint8_t soft_en : 1; - uint8_t not_used_02 : 1; - uint8_t den_xl_g : 1; - uint8_t den_z : 1; - uint8_t den_y : 1; - uint8_t den_x : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t den_x : 1; - uint8_t den_y : 1; - uint8_t den_z : 1; - uint8_t den_xl_g : 1; - uint8_t not_used_02 : 1; - uint8_t soft_en : 1; - uint8_t not_used_01 : 2; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_ctrl9_xl_t; - -#define LSM6DS3TR_C_CTRL10_C 0x19U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t sign_motion_en : 1; - uint8_t pedo_rst_step : 1; - uint8_t func_en : 1; - uint8_t tilt_en : 1; - uint8_t pedo_en : 1; - uint8_t timer_en : 1; - uint8_t not_used_01 : 1; - uint8_t wrist_tilt_en : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t wrist_tilt_en : 1; - uint8_t not_used_01 : 1; - uint8_t timer_en : 1; - uint8_t pedo_en : 1; - uint8_t tilt_en : 1; - uint8_t func_en : 1; - uint8_t pedo_rst_step : 1; - uint8_t sign_motion_en : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_ctrl10_c_t; - -#define LSM6DS3TR_C_MASTER_CONFIG 0x1AU -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t master_on : 1; - uint8_t iron_en : 1; - uint8_t pass_through_mode : 1; - uint8_t pull_up_en : 1; - uint8_t start_config : 1; - uint8_t not_used_01 : 1; - uint8_t data_valid_sel_fifo : 1; - uint8_t drdy_on_int1 : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t drdy_on_int1 : 1; - uint8_t data_valid_sel_fifo : 1; - uint8_t not_used_01 : 1; - uint8_t start_config : 1; - uint8_t pull_up_en : 1; - uint8_t pass_through_mode : 1; - uint8_t iron_en : 1; - uint8_t master_on : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_master_config_t; - -#define LSM6DS3TR_C_WAKE_UP_SRC 0x1BU -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t z_wu : 1; - uint8_t y_wu : 1; - uint8_t x_wu : 1; - uint8_t wu_ia : 1; - uint8_t sleep_state_ia : 1; - uint8_t ff_ia : 1; - uint8_t not_used_01 : 2; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t not_used_01 : 2; - uint8_t ff_ia : 1; - uint8_t sleep_state_ia : 1; - uint8_t wu_ia : 1; - uint8_t x_wu : 1; - uint8_t y_wu : 1; - uint8_t z_wu : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_wake_up_src_t; - -#define LSM6DS3TR_C_TAP_SRC 0x1CU -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t z_tap : 1; - uint8_t y_tap : 1; - uint8_t x_tap : 1; - uint8_t tap_sign : 1; - uint8_t double_tap : 1; - uint8_t single_tap : 1; - uint8_t tap_ia : 1; - uint8_t not_used_01 : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t not_used_01 : 1; - uint8_t tap_ia : 1; - uint8_t single_tap : 1; - uint8_t double_tap : 1; - uint8_t tap_sign : 1; - uint8_t x_tap : 1; - uint8_t y_tap : 1; - uint8_t z_tap : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_tap_src_t; - -#define LSM6DS3TR_C_D6D_SRC 0x1DU -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t xl : 1; - uint8_t xh : 1; - uint8_t yl : 1; - uint8_t yh : 1; - uint8_t zl : 1; - uint8_t zh : 1; - uint8_t d6d_ia : 1; - uint8_t den_drdy : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t den_drdy : 1; - uint8_t d6d_ia : 1; - uint8_t zh : 1; - uint8_t zl : 1; - uint8_t yh : 1; - uint8_t yl : 1; - uint8_t xh : 1; - uint8_t xl : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_d6d_src_t; - -#define LSM6DS3TR_C_STATUS_REG 0x1EU -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t xlda : 1; - uint8_t gda : 1; - uint8_t tda : 1; - uint8_t not_used_01 : 5; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t not_used_01 : 5; - uint8_t tda : 1; - uint8_t gda : 1; - uint8_t xlda : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_status_reg_t; - -#define LSM6DS3TR_C_OUT_TEMP_L 0x20U -#define LSM6DS3TR_C_OUT_TEMP_H 0x21U -#define LSM6DS3TR_C_OUTX_L_G 0x22U -#define LSM6DS3TR_C_OUTX_H_G 0x23U -#define LSM6DS3TR_C_OUTY_L_G 0x24U -#define LSM6DS3TR_C_OUTY_H_G 0x25U -#define LSM6DS3TR_C_OUTZ_L_G 0x26U -#define LSM6DS3TR_C_OUTZ_H_G 0x27U -#define LSM6DS3TR_C_OUTX_L_XL 0x28U -#define LSM6DS3TR_C_OUTX_H_XL 0x29U -#define LSM6DS3TR_C_OUTY_L_XL 0x2AU -#define LSM6DS3TR_C_OUTY_H_XL 0x2BU -#define LSM6DS3TR_C_OUTZ_L_XL 0x2CU -#define LSM6DS3TR_C_OUTZ_H_XL 0x2DU -#define LSM6DS3TR_C_SENSORHUB1_REG 0x2EU -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t bit0 : 1; - uint8_t bit1 : 1; - uint8_t bit2 : 1; - uint8_t bit3 : 1; - uint8_t bit4 : 1; - uint8_t bit5 : 1; - uint8_t bit6 : 1; - uint8_t bit7 : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t bit7 : 1; - uint8_t bit6 : 1; - uint8_t bit5 : 1; - uint8_t bit4 : 1; - uint8_t bit3 : 1; - uint8_t bit2 : 1; - uint8_t bit1 : 1; - uint8_t bit0 : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_sensorhub1_reg_t; - -#define LSM6DS3TR_C_SENSORHUB2_REG 0x2FU -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t bit0 : 1; - uint8_t bit1 : 1; - uint8_t bit2 : 1; - uint8_t bit3 : 1; - uint8_t bit4 : 1; - uint8_t bit5 : 1; - uint8_t bit6 : 1; - uint8_t bit7 : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t bit7 : 1; - uint8_t bit6 : 1; - uint8_t bit5 : 1; - uint8_t bit4 : 1; - uint8_t bit3 : 1; - uint8_t bit2 : 1; - uint8_t bit1 : 1; - uint8_t bit0 : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_sensorhub2_reg_t; - -#define LSM6DS3TR_C_SENSORHUB3_REG 0x30U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t bit0 : 1; - uint8_t bit1 : 1; - uint8_t bit2 : 1; - uint8_t bit3 : 1; - uint8_t bit4 : 1; - uint8_t bit5 : 1; - uint8_t bit6 : 1; - uint8_t bit7 : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t bit7 : 1; - uint8_t bit6 : 1; - uint8_t bit5 : 1; - uint8_t bit4 : 1; - uint8_t bit3 : 1; - uint8_t bit2 : 1; - uint8_t bit1 : 1; - uint8_t bit0 : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_sensorhub3_reg_t; - -#define LSM6DS3TR_C_SENSORHUB4_REG 0x31U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t bit0 : 1; - uint8_t bit1 : 1; - uint8_t bit2 : 1; - uint8_t bit3 : 1; - uint8_t bit4 : 1; - uint8_t bit5 : 1; - uint8_t bit6 : 1; - uint8_t bit7 : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t bit7 : 1; - uint8_t bit6 : 1; - uint8_t bit5 : 1; - uint8_t bit4 : 1; - uint8_t bit3 : 1; - uint8_t bit2 : 1; - uint8_t bit1 : 1; - uint8_t bit0 : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_sensorhub4_reg_t; - -#define LSM6DS3TR_C_SENSORHUB5_REG 0x32U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t bit0 : 1; - uint8_t bit1 : 1; - uint8_t bit2 : 1; - uint8_t bit3 : 1; - uint8_t bit4 : 1; - uint8_t bit5 : 1; - uint8_t bit6 : 1; - uint8_t bit7 : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t bit7 : 1; - uint8_t bit6 : 1; - uint8_t bit5 : 1; - uint8_t bit4 : 1; - uint8_t bit3 : 1; - uint8_t bit2 : 1; - uint8_t bit1 : 1; - uint8_t bit0 : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_sensorhub5_reg_t; - -#define LSM6DS3TR_C_SENSORHUB6_REG 0x33U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t bit0 : 1; - uint8_t bit1 : 1; - uint8_t bit2 : 1; - uint8_t bit3 : 1; - uint8_t bit4 : 1; - uint8_t bit5 : 1; - uint8_t bit6 : 1; - uint8_t bit7 : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t bit7 : 1; - uint8_t bit6 : 1; - uint8_t bit5 : 1; - uint8_t bit4 : 1; - uint8_t bit3 : 1; - uint8_t bit2 : 1; - uint8_t bit1 : 1; - uint8_t bit0 : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_sensorhub6_reg_t; - -#define LSM6DS3TR_C_SENSORHUB7_REG 0x34U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t bit0 : 1; - uint8_t bit1 : 1; - uint8_t bit2 : 1; - uint8_t bit3 : 1; - uint8_t bit4 : 1; - uint8_t bit5 : 1; - uint8_t bit6 : 1; - uint8_t bit7 : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t bit7 : 1; - uint8_t bit6 : 1; - uint8_t bit5 : 1; - uint8_t bit4 : 1; - uint8_t bit3 : 1; - uint8_t bit2 : 1; - uint8_t bit1 : 1; - uint8_t bit0 : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_sensorhub7_reg_t; - -#define LSM6DS3TR_C_SENSORHUB8_REG 0x35U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t bit0 : 1; - uint8_t bit1 : 1; - uint8_t bit2 : 1; - uint8_t bit3 : 1; - uint8_t bit4 : 1; - uint8_t bit5 : 1; - uint8_t bit6 : 1; - uint8_t bit7 : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t bit7 : 1; - uint8_t bit6 : 1; - uint8_t bit5 : 1; - uint8_t bit4 : 1; - uint8_t bit3 : 1; - uint8_t bit2 : 1; - uint8_t bit1 : 1; - uint8_t bit0 : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_sensorhub8_reg_t; - -#define LSM6DS3TR_C_SENSORHUB9_REG 0x36U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t bit0 : 1; - uint8_t bit1 : 1; - uint8_t bit2 : 1; - uint8_t bit3 : 1; - uint8_t bit4 : 1; - uint8_t bit5 : 1; - uint8_t bit6 : 1; - uint8_t bit7 : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t bit7 : 1; - uint8_t bit6 : 1; - uint8_t bit5 : 1; - uint8_t bit4 : 1; - uint8_t bit3 : 1; - uint8_t bit2 : 1; - uint8_t bit1 : 1; - uint8_t bit0 : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_sensorhub9_reg_t; - -#define LSM6DS3TR_C_SENSORHUB10_REG 0x37U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t bit0 : 1; - uint8_t bit1 : 1; - uint8_t bit2 : 1; - uint8_t bit3 : 1; - uint8_t bit4 : 1; - uint8_t bit5 : 1; - uint8_t bit6 : 1; - uint8_t bit7 : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t bit7 : 1; - uint8_t bit6 : 1; - uint8_t bit5 : 1; - uint8_t bit4 : 1; - uint8_t bit3 : 1; - uint8_t bit2 : 1; - uint8_t bit1 : 1; - uint8_t bit0 : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_sensorhub10_reg_t; - -#define LSM6DS3TR_C_SENSORHUB11_REG 0x38U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t bit0 : 1; - uint8_t bit1 : 1; - uint8_t bit2 : 1; - uint8_t bit3 : 1; - uint8_t bit4 : 1; - uint8_t bit5 : 1; - uint8_t bit6 : 1; - uint8_t bit7 : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t bit7 : 1; - uint8_t bit6 : 1; - uint8_t bit5 : 1; - uint8_t bit4 : 1; - uint8_t bit3 : 1; - uint8_t bit2 : 1; - uint8_t bit1 : 1; - uint8_t bit0 : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_sensorhub11_reg_t; - -#define LSM6DS3TR_C_SENSORHUB12_REG 0x39U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t bit0 : 1; - uint8_t bit1 : 1; - uint8_t bit2 : 1; - uint8_t bit3 : 1; - uint8_t bit4 : 1; - uint8_t bit5 : 1; - uint8_t bit6 : 1; - uint8_t bit7 : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t bit7 : 1; - uint8_t bit6 : 1; - uint8_t bit5 : 1; - uint8_t bit4 : 1; - uint8_t bit3 : 1; - uint8_t bit2 : 1; - uint8_t bit1 : 1; - uint8_t bit0 : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_sensorhub12_reg_t; - -#define LSM6DS3TR_C_FIFO_STATUS1 0x3AU -typedef struct { - uint8_t diff_fifo : 8; /* + FIFO_STATUS2(diff_fifo) */ -} lsm6ds3tr_c_fifo_status1_t; - -#define LSM6DS3TR_C_FIFO_STATUS2 0x3BU -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t diff_fifo : 3; /* + FIFO_STATUS1(diff_fifo) */ - uint8_t not_used_01 : 1; - uint8_t fifo_empty : 1; - uint8_t fifo_full_smart : 1; - uint8_t over_run : 1; - uint8_t waterm : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t waterm : 1; - uint8_t over_run : 1; - uint8_t fifo_full_smart : 1; - uint8_t fifo_empty : 1; - uint8_t not_used_01 : 1; - uint8_t diff_fifo : 3; /* + FIFO_STATUS1(diff_fifo) */ -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_fifo_status2_t; - -#define LSM6DS3TR_C_FIFO_STATUS3 0x3CU -typedef struct { - uint8_t fifo_pattern : 8; /* + FIFO_STATUS4(fifo_pattern) */ -} lsm6ds3tr_c_fifo_status3_t; - -#define LSM6DS3TR_C_FIFO_STATUS4 0x3DU -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t fifo_pattern : 2; /* + FIFO_STATUS3(fifo_pattern) */ - uint8_t not_used_01 : 6; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t not_used_01 : 6; - uint8_t fifo_pattern : 2; /* + FIFO_STATUS3(fifo_pattern) */ -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_fifo_status4_t; - -#define LSM6DS3TR_C_FIFO_DATA_OUT_L 0x3EU -#define LSM6DS3TR_C_FIFO_DATA_OUT_H 0x3FU -#define LSM6DS3TR_C_TIMESTAMP0_REG 0x40U -#define LSM6DS3TR_C_TIMESTAMP1_REG 0x41U -#define LSM6DS3TR_C_TIMESTAMP2_REG 0x42U -#define LSM6DS3TR_C_STEP_TIMESTAMP_L 0x49U -#define LSM6DS3TR_C_STEP_TIMESTAMP_H 0x4AU -#define LSM6DS3TR_C_STEP_COUNTER_L 0x4BU -#define LSM6DS3TR_C_STEP_COUNTER_H 0x4CU - -#define LSM6DS3TR_C_SENSORHUB13_REG 0x4DU -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t bit0 : 1; - uint8_t bit1 : 1; - uint8_t bit2 : 1; - uint8_t bit3 : 1; - uint8_t bit4 : 1; - uint8_t bit5 : 1; - uint8_t bit6 : 1; - uint8_t bit7 : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t bit7 : 1; - uint8_t bit6 : 1; - uint8_t bit5 : 1; - uint8_t bit4 : 1; - uint8_t bit3 : 1; - uint8_t bit2 : 1; - uint8_t bit1 : 1; - uint8_t bit0 : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_sensorhub13_reg_t; - -#define LSM6DS3TR_C_SENSORHUB14_REG 0x4EU -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t bit0 : 1; - uint8_t bit1 : 1; - uint8_t bit2 : 1; - uint8_t bit3 : 1; - uint8_t bit4 : 1; - uint8_t bit5 : 1; - uint8_t bit6 : 1; - uint8_t bit7 : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t bit7 : 1; - uint8_t bit6 : 1; - uint8_t bit5 : 1; - uint8_t bit4 : 1; - uint8_t bit3 : 1; - uint8_t bit2 : 1; - uint8_t bit1 : 1; - uint8_t bit0 : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_sensorhub14_reg_t; - -#define LSM6DS3TR_C_SENSORHUB15_REG 0x4FU -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t bit0 : 1; - uint8_t bit1 : 1; - uint8_t bit2 : 1; - uint8_t bit3 : 1; - uint8_t bit4 : 1; - uint8_t bit5 : 1; - uint8_t bit6 : 1; - uint8_t bit7 : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t bit7 : 1; - uint8_t bit6 : 1; - uint8_t bit5 : 1; - uint8_t bit4 : 1; - uint8_t bit3 : 1; - uint8_t bit2 : 1; - uint8_t bit1 : 1; - uint8_t bit0 : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_sensorhub15_reg_t; - -#define LSM6DS3TR_C_SENSORHUB16_REG 0x50U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t bit0 : 1; - uint8_t bit1 : 1; - uint8_t bit2 : 1; - uint8_t bit3 : 1; - uint8_t bit4 : 1; - uint8_t bit5 : 1; - uint8_t bit6 : 1; - uint8_t bit7 : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t bit7 : 1; - uint8_t bit6 : 1; - uint8_t bit5 : 1; - uint8_t bit4 : 1; - uint8_t bit3 : 1; - uint8_t bit2 : 1; - uint8_t bit1 : 1; - uint8_t bit0 : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_sensorhub16_reg_t; - -#define LSM6DS3TR_C_SENSORHUB17_REG 0x51U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t bit0 : 1; - uint8_t bit1 : 1; - uint8_t bit2 : 1; - uint8_t bit3 : 1; - uint8_t bit4 : 1; - uint8_t bit5 : 1; - uint8_t bit6 : 1; - uint8_t bit7 : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t bit7 : 1; - uint8_t bit6 : 1; - uint8_t bit5 : 1; - uint8_t bit4 : 1; - uint8_t bit3 : 1; - uint8_t bit2 : 1; - uint8_t bit1 : 1; - uint8_t bit0 : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_sensorhub17_reg_t; - -#define LSM6DS3TR_C_SENSORHUB18_REG 0x52U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t bit0 : 1; - uint8_t bit1 : 1; - uint8_t bit2 : 1; - uint8_t bit3 : 1; - uint8_t bit4 : 1; - uint8_t bit5 : 1; - uint8_t bit6 : 1; - uint8_t bit7 : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t bit7 : 1; - uint8_t bit6 : 1; - uint8_t bit5 : 1; - uint8_t bit4 : 1; - uint8_t bit3 : 1; - uint8_t bit2 : 1; - uint8_t bit1 : 1; - uint8_t bit0 : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_sensorhub18_reg_t; - -#define LSM6DS3TR_C_FUNC_SRC1 0x53U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t sensorhub_end_op : 1; - uint8_t si_end_op : 1; - uint8_t hi_fail : 1; - uint8_t step_overflow : 1; - uint8_t step_detected : 1; - uint8_t tilt_ia : 1; - uint8_t sign_motion_ia : 1; - uint8_t step_count_delta_ia : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t step_count_delta_ia : 1; - uint8_t sign_motion_ia : 1; - uint8_t tilt_ia : 1; - uint8_t step_detected : 1; - uint8_t step_overflow : 1; - uint8_t hi_fail : 1; - uint8_t si_end_op : 1; - uint8_t sensorhub_end_op : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_func_src1_t; - -#define LSM6DS3TR_C_FUNC_SRC2 0x54U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t wrist_tilt_ia : 1; - uint8_t not_used_01 : 2; - uint8_t slave0_nack : 1; - uint8_t slave1_nack : 1; - uint8_t slave2_nack : 1; - uint8_t slave3_nack : 1; - uint8_t not_used_02 : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t not_used_02 : 1; - uint8_t slave3_nack : 1; - uint8_t slave2_nack : 1; - uint8_t slave1_nack : 1; - uint8_t slave0_nack : 1; - uint8_t not_used_01 : 2; - uint8_t wrist_tilt_ia : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_func_src2_t; - -#define LSM6DS3TR_C_WRIST_TILT_IA 0x55U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t not_used_01 : 2; - uint8_t wrist_tilt_ia_zneg : 1; - uint8_t wrist_tilt_ia_zpos : 1; - uint8_t wrist_tilt_ia_yneg : 1; - uint8_t wrist_tilt_ia_ypos : 1; - uint8_t wrist_tilt_ia_xneg : 1; - uint8_t wrist_tilt_ia_xpos : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t wrist_tilt_ia_xpos : 1; - uint8_t wrist_tilt_ia_xneg : 1; - uint8_t wrist_tilt_ia_ypos : 1; - uint8_t wrist_tilt_ia_yneg : 1; - uint8_t wrist_tilt_ia_zpos : 1; - uint8_t wrist_tilt_ia_zneg : 1; - uint8_t not_used_01 : 2; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_wrist_tilt_ia_t; - -#define LSM6DS3TR_C_TAP_CFG 0x58U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t lir : 1; - uint8_t tap_z_en : 1; - uint8_t tap_y_en : 1; - uint8_t tap_x_en : 1; - uint8_t slope_fds : 1; - uint8_t inact_en : 2; - uint8_t interrupts_enable : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t interrupts_enable : 1; - uint8_t inact_en : 2; - uint8_t slope_fds : 1; - uint8_t tap_x_en : 1; - uint8_t tap_y_en : 1; - uint8_t tap_z_en : 1; - uint8_t lir : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_tap_cfg_t; - -#define LSM6DS3TR_C_TAP_THS_6D 0x59U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t tap_ths : 5; - uint8_t sixd_ths : 2; - uint8_t d4d_en : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t d4d_en : 1; - uint8_t sixd_ths : 2; - uint8_t tap_ths : 5; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_tap_ths_6d_t; - -#define LSM6DS3TR_C_INT_DUR2 0x5AU -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t shock : 2; - uint8_t quiet : 2; - uint8_t dur : 4; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t dur : 4; - uint8_t quiet : 2; - uint8_t shock : 2; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_int_dur2_t; - -#define LSM6DS3TR_C_WAKE_UP_THS 0x5BU -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t wk_ths : 6; - uint8_t not_used_01 : 1; - uint8_t single_double_tap : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t single_double_tap : 1; - uint8_t not_used_01 : 1; - uint8_t wk_ths : 6; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_wake_up_ths_t; - -#define LSM6DS3TR_C_WAKE_UP_DUR 0x5CU -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t sleep_dur : 4; - uint8_t timer_hr : 1; - uint8_t wake_dur : 2; - uint8_t ff_dur : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t ff_dur : 1; - uint8_t wake_dur : 2; - uint8_t timer_hr : 1; - uint8_t sleep_dur : 4; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_wake_up_dur_t; - -#define LSM6DS3TR_C_FREE_FALL 0x5DU -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t ff_ths : 3; - uint8_t ff_dur : 5; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t ff_dur : 5; - uint8_t ff_ths : 3; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_free_fall_t; - -#define LSM6DS3TR_C_MD1_CFG 0x5EU -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t int1_timer : 1; - uint8_t int1_tilt : 1; - uint8_t int1_6d : 1; - uint8_t int1_double_tap : 1; - uint8_t int1_ff : 1; - uint8_t int1_wu : 1; - uint8_t int1_single_tap : 1; - uint8_t int1_inact_state : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t int1_inact_state : 1; - uint8_t int1_single_tap : 1; - uint8_t int1_wu : 1; - uint8_t int1_ff : 1; - uint8_t int1_double_tap : 1; - uint8_t int1_6d : 1; - uint8_t int1_tilt : 1; - uint8_t int1_timer : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_md1_cfg_t; - -#define LSM6DS3TR_C_MD2_CFG 0x5FU -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t int2_iron : 1; - uint8_t int2_tilt : 1; - uint8_t int2_6d : 1; - uint8_t int2_double_tap : 1; - uint8_t int2_ff : 1; - uint8_t int2_wu : 1; - uint8_t int2_single_tap : 1; - uint8_t int2_inact_state : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t int2_inact_state : 1; - uint8_t int2_single_tap : 1; - uint8_t int2_wu : 1; - uint8_t int2_ff : 1; - uint8_t int2_double_tap : 1; - uint8_t int2_6d : 1; - uint8_t int2_tilt : 1; - uint8_t int2_iron : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_md2_cfg_t; - -#define LSM6DS3TR_C_MASTER_CMD_CODE 0x60U -typedef struct { - uint8_t master_cmd_code : 8; -} lsm6ds3tr_c_master_cmd_code_t; - -#define LSM6DS3TR_C_SENS_SYNC_SPI_ERROR_CODE 0x61U -typedef struct { - uint8_t error_code : 8; -} lsm6ds3tr_c_sens_sync_spi_error_code_t; - -#define LSM6DS3TR_C_OUT_MAG_RAW_X_L 0x66U -#define LSM6DS3TR_C_OUT_MAG_RAW_X_H 0x67U -#define LSM6DS3TR_C_OUT_MAG_RAW_Y_L 0x68U -#define LSM6DS3TR_C_OUT_MAG_RAW_Y_H 0x69U -#define LSM6DS3TR_C_OUT_MAG_RAW_Z_L 0x6AU -#define LSM6DS3TR_C_OUT_MAG_RAW_Z_H 0x6BU -#define LSM6DS3TR_C_X_OFS_USR 0x73U -#define LSM6DS3TR_C_Y_OFS_USR 0x74U -#define LSM6DS3TR_C_Z_OFS_USR 0x75U -#define LSM6DS3TR_C_SLV0_ADD 0x02U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t rw_0 : 1; - uint8_t slave0_add : 7; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t slave0_add : 7; - uint8_t rw_0 : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_slv0_add_t; - -#define LSM6DS3TR_C_SLV0_SUBADD 0x03U -typedef struct { - uint8_t slave0_reg : 8; -} lsm6ds3tr_c_slv0_subadd_t; - -#define LSM6DS3TR_C_SLAVE0_CONFIG 0x04U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t slave0_numop : 3; - uint8_t src_mode : 1; - uint8_t aux_sens_on : 2; - uint8_t slave0_rate : 2; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t slave0_rate : 2; - uint8_t aux_sens_on : 2; - uint8_t src_mode : 1; - uint8_t slave0_numop : 3; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_slave0_config_t; - -#define LSM6DS3TR_C_SLV1_ADD 0x05U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t r_1 : 1; - uint8_t slave1_add : 7; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t slave1_add : 7; - uint8_t r_1 : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_slv1_add_t; - -#define LSM6DS3TR_C_SLV1_SUBADD 0x06U -typedef struct { - uint8_t slave1_reg : 8; -} lsm6ds3tr_c_slv1_subadd_t; - -#define LSM6DS3TR_C_SLAVE1_CONFIG 0x07U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t slave1_numop : 3; - uint8_t not_used_01 : 2; - uint8_t write_once : 1; - uint8_t slave1_rate : 2; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t slave1_rate : 2; - uint8_t write_once : 1; - uint8_t not_used_01 : 2; - uint8_t slave1_numop : 3; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_slave1_config_t; - -#define LSM6DS3TR_C_SLV2_ADD 0x08U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t r_2 : 1; - uint8_t slave2_add : 7; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t slave2_add : 7; - uint8_t r_2 : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_slv2_add_t; - -#define LSM6DS3TR_C_SLV2_SUBADD 0x09U -typedef struct { - uint8_t slave2_reg : 8; -} lsm6ds3tr_c_slv2_subadd_t; - -#define LSM6DS3TR_C_SLAVE2_CONFIG 0x0AU -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t slave2_numop : 3; - uint8_t not_used_01 : 3; - uint8_t slave2_rate : 2; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t slave2_rate : 2; - uint8_t not_used_01 : 3; - uint8_t slave2_numop : 3; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_slave2_config_t; - -#define LSM6DS3TR_C_SLV3_ADD 0x0BU -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t r_3 : 1; - uint8_t slave3_add : 7; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t slave3_add : 7; - uint8_t r_3 : 1; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_slv3_add_t; - -#define LSM6DS3TR_C_SLV3_SUBADD 0x0CU -typedef struct { - uint8_t slave3_reg : 8; -} lsm6ds3tr_c_slv3_subadd_t; - -#define LSM6DS3TR_C_SLAVE3_CONFIG 0x0DU -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t slave3_numop : 3; - uint8_t not_used_01 : 3; - uint8_t slave3_rate : 2; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t slave3_rate : 2; - uint8_t not_used_01 : 3; - uint8_t slave3_numop : 3; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_slave3_config_t; - -#define LSM6DS3TR_C_DATAWRITE_SRC_MODE_SUB_SLV0 0x0EU -typedef struct { - uint8_t slave_dataw : 8; -} lsm6ds3tr_c_datawrite_src_mode_sub_slv0_t; - -#define LSM6DS3TR_C_CONFIG_PEDO_THS_MIN 0x0FU -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t ths_min : 5; - uint8_t not_used_01 : 2; - uint8_t pedo_fs : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t pedo_fs : 1; - uint8_t not_used_01 : 2; - uint8_t ths_min : 5; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_config_pedo_ths_min_t; - -#define LSM6DS3TR_C_SM_THS 0x13U -#define LSM6DS3TR_C_PEDO_DEB_REG 0x14U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t deb_step : 3; - uint8_t deb_time : 5; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t deb_time : 5; - uint8_t deb_step : 3; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_pedo_deb_reg_t; - -#define LSM6DS3TR_C_STEP_COUNT_DELTA 0x15U -#define LSM6DS3TR_C_MAG_SI_XX 0x24U -#define LSM6DS3TR_C_MAG_SI_XY 0x25U -#define LSM6DS3TR_C_MAG_SI_XZ 0x26U -#define LSM6DS3TR_C_MAG_SI_YX 0x27U -#define LSM6DS3TR_C_MAG_SI_YY 0x28U -#define LSM6DS3TR_C_MAG_SI_YZ 0x29U -#define LSM6DS3TR_C_MAG_SI_ZX 0x2AU -#define LSM6DS3TR_C_MAG_SI_ZY 0x2BU -#define LSM6DS3TR_C_MAG_SI_ZZ 0x2CU -#define LSM6DS3TR_C_MAG_OFFX_L 0x2DU -#define LSM6DS3TR_C_MAG_OFFX_H 0x2EU -#define LSM6DS3TR_C_MAG_OFFY_L 0x2FU -#define LSM6DS3TR_C_MAG_OFFY_H 0x30U -#define LSM6DS3TR_C_MAG_OFFZ_L 0x31U -#define LSM6DS3TR_C_MAG_OFFZ_H 0x32U -#define LSM6DS3TR_C_A_WRIST_TILT_LAT 0x50U -#define LSM6DS3TR_C_A_WRIST_TILT_THS 0x54U -#define LSM6DS3TR_C_A_WRIST_TILT_MASK 0x59U -typedef struct { -#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN - uint8_t not_used_01 : 2; - uint8_t wrist_tilt_mask_zneg : 1; - uint8_t wrist_tilt_mask_zpos : 1; - uint8_t wrist_tilt_mask_yneg : 1; - uint8_t wrist_tilt_mask_ypos : 1; - uint8_t wrist_tilt_mask_xneg : 1; - uint8_t wrist_tilt_mask_xpos : 1; -#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN - uint8_t wrist_tilt_mask_xpos : 1; - uint8_t wrist_tilt_mask_xneg : 1; - uint8_t wrist_tilt_mask_ypos : 1; - uint8_t wrist_tilt_mask_yneg : 1; - uint8_t wrist_tilt_mask_zpos : 1; - uint8_t wrist_tilt_mask_zneg : 1; - uint8_t not_used_01 : 2; -#endif /* DRV_BYTE_ORDER */ -} lsm6ds3tr_c_a_wrist_tilt_mask_t; - -/** - * @defgroup LSM6DS3TR_C_Register_Union - * @brief This union group all the registers having a bit-field - * description. - * This union is useful but it's not needed by the driver. - * - * REMOVING this union you are compliant with: - * MISRA-C 2012 [Rule 19.2] -> " Union are not allowed " - * - * @{ - * - */ -typedef union { - lsm6ds3tr_c_func_cfg_access_t func_cfg_access; - lsm6ds3tr_c_sensor_sync_time_frame_t sensor_sync_time_frame; - lsm6ds3tr_c_sensor_sync_res_ratio_t sensor_sync_res_ratio; - lsm6ds3tr_c_fifo_ctrl1_t fifo_ctrl1; - lsm6ds3tr_c_fifo_ctrl2_t fifo_ctrl2; - lsm6ds3tr_c_fifo_ctrl3_t fifo_ctrl3; - lsm6ds3tr_c_fifo_ctrl4_t fifo_ctrl4; - lsm6ds3tr_c_fifo_ctrl5_t fifo_ctrl5; - lsm6ds3tr_c_drdy_pulse_cfg_g_t drdy_pulse_cfg_g; - lsm6ds3tr_c_int1_ctrl_t int1_ctrl; - lsm6ds3tr_c_int2_ctrl_t int2_ctrl; - lsm6ds3tr_c_ctrl1_xl_t ctrl1_xl; - lsm6ds3tr_c_ctrl2_g_t ctrl2_g; - lsm6ds3tr_c_ctrl3_c_t ctrl3_c; - lsm6ds3tr_c_ctrl4_c_t ctrl4_c; - lsm6ds3tr_c_ctrl5_c_t ctrl5_c; - lsm6ds3tr_c_ctrl6_c_t ctrl6_c; - lsm6ds3tr_c_ctrl7_g_t ctrl7_g; - lsm6ds3tr_c_ctrl8_xl_t ctrl8_xl; - lsm6ds3tr_c_ctrl9_xl_t ctrl9_xl; - lsm6ds3tr_c_ctrl10_c_t ctrl10_c; - lsm6ds3tr_c_master_config_t master_config; - lsm6ds3tr_c_wake_up_src_t wake_up_src; - lsm6ds3tr_c_tap_src_t tap_src; - lsm6ds3tr_c_d6d_src_t d6d_src; - lsm6ds3tr_c_status_reg_t status_reg; - lsm6ds3tr_c_sensorhub1_reg_t sensorhub1_reg; - lsm6ds3tr_c_sensorhub2_reg_t sensorhub2_reg; - lsm6ds3tr_c_sensorhub3_reg_t sensorhub3_reg; - lsm6ds3tr_c_sensorhub4_reg_t sensorhub4_reg; - lsm6ds3tr_c_sensorhub5_reg_t sensorhub5_reg; - lsm6ds3tr_c_sensorhub6_reg_t sensorhub6_reg; - lsm6ds3tr_c_sensorhub7_reg_t sensorhub7_reg; - lsm6ds3tr_c_sensorhub8_reg_t sensorhub8_reg; - lsm6ds3tr_c_sensorhub9_reg_t sensorhub9_reg; - lsm6ds3tr_c_sensorhub10_reg_t sensorhub10_reg; - lsm6ds3tr_c_sensorhub11_reg_t sensorhub11_reg; - lsm6ds3tr_c_sensorhub12_reg_t sensorhub12_reg; - lsm6ds3tr_c_fifo_status1_t fifo_status1; - lsm6ds3tr_c_fifo_status2_t fifo_status2; - lsm6ds3tr_c_fifo_status3_t fifo_status3; - lsm6ds3tr_c_fifo_status4_t fifo_status4; - lsm6ds3tr_c_sensorhub13_reg_t sensorhub13_reg; - lsm6ds3tr_c_sensorhub14_reg_t sensorhub14_reg; - lsm6ds3tr_c_sensorhub15_reg_t sensorhub15_reg; - lsm6ds3tr_c_sensorhub16_reg_t sensorhub16_reg; - lsm6ds3tr_c_sensorhub17_reg_t sensorhub17_reg; - lsm6ds3tr_c_sensorhub18_reg_t sensorhub18_reg; - lsm6ds3tr_c_func_src1_t func_src1; - lsm6ds3tr_c_func_src2_t func_src2; - lsm6ds3tr_c_wrist_tilt_ia_t wrist_tilt_ia; - lsm6ds3tr_c_tap_cfg_t tap_cfg; - lsm6ds3tr_c_tap_ths_6d_t tap_ths_6d; - lsm6ds3tr_c_int_dur2_t int_dur2; - lsm6ds3tr_c_wake_up_ths_t wake_up_ths; - lsm6ds3tr_c_wake_up_dur_t wake_up_dur; - lsm6ds3tr_c_free_fall_t free_fall; - lsm6ds3tr_c_md1_cfg_t md1_cfg; - lsm6ds3tr_c_md2_cfg_t md2_cfg; - lsm6ds3tr_c_master_cmd_code_t master_cmd_code; - lsm6ds3tr_c_sens_sync_spi_error_code_t sens_sync_spi_error_code; - lsm6ds3tr_c_slv0_add_t slv0_add; - lsm6ds3tr_c_slv0_subadd_t slv0_subadd; - lsm6ds3tr_c_slave0_config_t slave0_config; - lsm6ds3tr_c_slv1_add_t slv1_add; - lsm6ds3tr_c_slv1_subadd_t slv1_subadd; - lsm6ds3tr_c_slave1_config_t slave1_config; - lsm6ds3tr_c_slv2_add_t slv2_add; - lsm6ds3tr_c_slv2_subadd_t slv2_subadd; - lsm6ds3tr_c_slave2_config_t slave2_config; - lsm6ds3tr_c_slv3_add_t slv3_add; - lsm6ds3tr_c_slv3_subadd_t slv3_subadd; - lsm6ds3tr_c_slave3_config_t slave3_config; - lsm6ds3tr_c_datawrite_src_mode_sub_slv0_t datawrite_src_mode_sub_slv0; - lsm6ds3tr_c_config_pedo_ths_min_t config_pedo_ths_min; - lsm6ds3tr_c_pedo_deb_reg_t pedo_deb_reg; - lsm6ds3tr_c_a_wrist_tilt_mask_t a_wrist_tilt_mask; - bitwise_t bitwise; - uint8_t byte; -} lsm6ds3tr_c_reg_t; - -/** - * @} - * - */ - -int32_t lsm6ds3tr_c_read_reg(stmdev_ctx_t* ctx, uint8_t reg, uint8_t* data, uint16_t len); -int32_t lsm6ds3tr_c_write_reg(stmdev_ctx_t* ctx, uint8_t reg, uint8_t* data, uint16_t len); - -float_t lsm6ds3tr_c_from_fs2g_to_mg(int16_t lsb); -float_t lsm6ds3tr_c_from_fs4g_to_mg(int16_t lsb); -float_t lsm6ds3tr_c_from_fs8g_to_mg(int16_t lsb); -float_t lsm6ds3tr_c_from_fs16g_to_mg(int16_t lsb); - -float_t lsm6ds3tr_c_from_fs125dps_to_mdps(int16_t lsb); -float_t lsm6ds3tr_c_from_fs250dps_to_mdps(int16_t lsb); -float_t lsm6ds3tr_c_from_fs500dps_to_mdps(int16_t lsb); -float_t lsm6ds3tr_c_from_fs1000dps_to_mdps(int16_t lsb); -float_t lsm6ds3tr_c_from_fs2000dps_to_mdps(int16_t lsb); - -float_t lsm6ds3tr_c_from_lsb_to_celsius(int16_t lsb); - -typedef enum { - LSM6DS3TR_C_2g = 0, - LSM6DS3TR_C_16g = 1, - LSM6DS3TR_C_4g = 2, - LSM6DS3TR_C_8g = 3, - LSM6DS3TR_C_XL_FS_ND = 4, /* ERROR CODE */ -} lsm6ds3tr_c_fs_xl_t; -int32_t lsm6ds3tr_c_xl_full_scale_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_fs_xl_t val); -int32_t lsm6ds3tr_c_xl_full_scale_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_fs_xl_t* val); - -typedef enum { - LSM6DS3TR_C_XL_ODR_OFF = 0, - LSM6DS3TR_C_XL_ODR_12Hz5 = 1, - LSM6DS3TR_C_XL_ODR_26Hz = 2, - LSM6DS3TR_C_XL_ODR_52Hz = 3, - LSM6DS3TR_C_XL_ODR_104Hz = 4, - LSM6DS3TR_C_XL_ODR_208Hz = 5, - LSM6DS3TR_C_XL_ODR_416Hz = 6, - LSM6DS3TR_C_XL_ODR_833Hz = 7, - LSM6DS3TR_C_XL_ODR_1k66Hz = 8, - LSM6DS3TR_C_XL_ODR_3k33Hz = 9, - LSM6DS3TR_C_XL_ODR_6k66Hz = 10, - LSM6DS3TR_C_XL_ODR_1Hz6 = 11, - LSM6DS3TR_C_XL_ODR_ND = 12, /* ERROR CODE */ -} lsm6ds3tr_c_odr_xl_t; -int32_t lsm6ds3tr_c_xl_data_rate_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_odr_xl_t val); -int32_t lsm6ds3tr_c_xl_data_rate_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_odr_xl_t* val); - -typedef enum { - LSM6DS3TR_C_250dps = 0, - LSM6DS3TR_C_125dps = 1, - LSM6DS3TR_C_500dps = 2, - LSM6DS3TR_C_1000dps = 4, - LSM6DS3TR_C_2000dps = 6, - LSM6DS3TR_C_GY_FS_ND = 7, /* ERROR CODE */ -} lsm6ds3tr_c_fs_g_t; -int32_t lsm6ds3tr_c_gy_full_scale_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_fs_g_t val); -int32_t lsm6ds3tr_c_gy_full_scale_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_fs_g_t* val); - -typedef enum { - LSM6DS3TR_C_GY_ODR_OFF = 0, - LSM6DS3TR_C_GY_ODR_12Hz5 = 1, - LSM6DS3TR_C_GY_ODR_26Hz = 2, - LSM6DS3TR_C_GY_ODR_52Hz = 3, - LSM6DS3TR_C_GY_ODR_104Hz = 4, - LSM6DS3TR_C_GY_ODR_208Hz = 5, - LSM6DS3TR_C_GY_ODR_416Hz = 6, - LSM6DS3TR_C_GY_ODR_833Hz = 7, - LSM6DS3TR_C_GY_ODR_1k66Hz = 8, - LSM6DS3TR_C_GY_ODR_3k33Hz = 9, - LSM6DS3TR_C_GY_ODR_6k66Hz = 10, - LSM6DS3TR_C_GY_ODR_ND = 11, /* ERROR CODE */ -} lsm6ds3tr_c_odr_g_t; -int32_t lsm6ds3tr_c_gy_data_rate_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_odr_g_t val); -int32_t lsm6ds3tr_c_gy_data_rate_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_odr_g_t* val); - -int32_t lsm6ds3tr_c_block_data_update_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_block_data_update_get(stmdev_ctx_t* ctx, uint8_t* val); - -typedef enum { - LSM6DS3TR_C_LSb_1mg = 0, - LSM6DS3TR_C_LSb_16mg = 1, - LSM6DS3TR_C_WEIGHT_ND = 2, -} lsm6ds3tr_c_usr_off_w_t; -int32_t lsm6ds3tr_c_xl_offset_weight_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_usr_off_w_t val); -int32_t lsm6ds3tr_c_xl_offset_weight_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_usr_off_w_t* val); - -typedef enum { - LSM6DS3TR_C_XL_HIGH_PERFORMANCE = 0, - LSM6DS3TR_C_XL_NORMAL = 1, - LSM6DS3TR_C_XL_PW_MODE_ND = 2, /* ERROR CODE */ -} lsm6ds3tr_c_xl_hm_mode_t; -int32_t lsm6ds3tr_c_xl_power_mode_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_xl_hm_mode_t val); -int32_t lsm6ds3tr_c_xl_power_mode_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_xl_hm_mode_t* val); - -typedef enum { - LSM6DS3TR_C_STAT_RND_DISABLE = 0, - LSM6DS3TR_C_STAT_RND_ENABLE = 1, - LSM6DS3TR_C_STAT_RND_ND = 2, /* ERROR CODE */ -} lsm6ds3tr_c_rounding_status_t; -int32_t lsm6ds3tr_c_rounding_on_status_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_rounding_status_t val); -int32_t lsm6ds3tr_c_rounding_on_status_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_rounding_status_t* val); - -typedef enum { - LSM6DS3TR_C_GY_HIGH_PERFORMANCE = 0, - LSM6DS3TR_C_GY_NORMAL = 1, - LSM6DS3TR_C_GY_PW_MODE_ND = 2, /* ERROR CODE */ -} lsm6ds3tr_c_g_hm_mode_t; -int32_t lsm6ds3tr_c_gy_power_mode_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_g_hm_mode_t val); -int32_t lsm6ds3tr_c_gy_power_mode_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_g_hm_mode_t* val); - -typedef struct { - lsm6ds3tr_c_wake_up_src_t wake_up_src; - lsm6ds3tr_c_tap_src_t tap_src; - lsm6ds3tr_c_d6d_src_t d6d_src; - lsm6ds3tr_c_status_reg_t status_reg; - lsm6ds3tr_c_func_src1_t func_src1; - lsm6ds3tr_c_func_src2_t func_src2; - lsm6ds3tr_c_wrist_tilt_ia_t wrist_tilt_ia; - lsm6ds3tr_c_a_wrist_tilt_mask_t a_wrist_tilt_mask; -} lsm6ds3tr_c_all_sources_t; -int32_t lsm6ds3tr_c_all_sources_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_all_sources_t* val); - -int32_t lsm6ds3tr_c_status_reg_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_status_reg_t* val); - -int32_t lsm6ds3tr_c_xl_flag_data_ready_get(stmdev_ctx_t* ctx, uint8_t* val); - -int32_t lsm6ds3tr_c_gy_flag_data_ready_get(stmdev_ctx_t* ctx, uint8_t* val); - -int32_t lsm6ds3tr_c_temp_flag_data_ready_get(stmdev_ctx_t* ctx, uint8_t* val); - -int32_t lsm6ds3tr_c_xl_usr_offset_set(stmdev_ctx_t* ctx, uint8_t* buff); -int32_t lsm6ds3tr_c_xl_usr_offset_get(stmdev_ctx_t* ctx, uint8_t* buff); -int32_t lsm6ds3tr_c_timestamp_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_timestamp_get(stmdev_ctx_t* ctx, uint8_t* val); - -typedef enum { - LSM6DS3TR_C_LSB_6ms4 = 0, - LSM6DS3TR_C_LSB_25us = 1, - LSM6DS3TR_C_TS_RES_ND = 2, /* ERROR CODE */ -} lsm6ds3tr_c_timer_hr_t; -int32_t lsm6ds3tr_c_timestamp_res_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_timer_hr_t val); -int32_t lsm6ds3tr_c_timestamp_res_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_timer_hr_t* val); - -typedef enum { - LSM6DS3TR_C_ROUND_DISABLE = 0, - LSM6DS3TR_C_ROUND_XL = 1, - LSM6DS3TR_C_ROUND_GY = 2, - LSM6DS3TR_C_ROUND_GY_XL = 3, - LSM6DS3TR_C_ROUND_SH1_TO_SH6 = 4, - LSM6DS3TR_C_ROUND_XL_SH1_TO_SH6 = 5, - LSM6DS3TR_C_ROUND_GY_XL_SH1_TO_SH12 = 6, - LSM6DS3TR_C_ROUND_GY_XL_SH1_TO_SH6 = 7, - LSM6DS3TR_C_ROUND_OUT_ND = 8, /* ERROR CODE */ -} lsm6ds3tr_c_rounding_t; -int32_t lsm6ds3tr_c_rounding_mode_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_rounding_t val); -int32_t lsm6ds3tr_c_rounding_mode_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_rounding_t* val); - -int32_t lsm6ds3tr_c_temperature_raw_get(stmdev_ctx_t* ctx, int16_t* val); -int32_t lsm6ds3tr_c_angular_rate_raw_get(stmdev_ctx_t* ctx, int16_t* val); -int32_t lsm6ds3tr_c_acceleration_raw_get(stmdev_ctx_t* ctx, int16_t* val); - -int32_t lsm6ds3tr_c_mag_calibrated_raw_get(stmdev_ctx_t* ctx, int16_t* val); - -int32_t lsm6ds3tr_c_fifo_raw_data_get(stmdev_ctx_t* ctx, uint8_t* buffer, uint8_t len); - -typedef enum { - LSM6DS3TR_C_USER_BANK = 0, - LSM6DS3TR_C_BANK_A = 4, - LSM6DS3TR_C_BANK_B = 5, - LSM6DS3TR_C_BANK_ND = 6, /* ERROR CODE */ -} lsm6ds3tr_c_func_cfg_en_t; -int32_t lsm6ds3tr_c_mem_bank_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_func_cfg_en_t val); -int32_t lsm6ds3tr_c_mem_bank_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_func_cfg_en_t* val); - -typedef enum { - LSM6DS3TR_C_DRDY_LATCHED = 0, - LSM6DS3TR_C_DRDY_PULSED = 1, - LSM6DS3TR_C_DRDY_ND = 2, /* ERROR CODE */ -} lsm6ds3tr_c_drdy_pulsed_g_t; -int32_t lsm6ds3tr_c_data_ready_mode_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_drdy_pulsed_g_t val); -int32_t lsm6ds3tr_c_data_ready_mode_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_drdy_pulsed_g_t* val); - -int32_t lsm6ds3tr_c_device_id_get(stmdev_ctx_t* ctx, uint8_t* buff); -int32_t lsm6ds3tr_c_reset_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_reset_get(stmdev_ctx_t* ctx, uint8_t* val); - -typedef enum { - LSM6DS3TR_C_LSB_AT_LOW_ADD = 0, - LSM6DS3TR_C_MSB_AT_LOW_ADD = 1, - LSM6DS3TR_C_DATA_FMT_ND = 2, /* ERROR CODE */ -} lsm6ds3tr_c_ble_t; -int32_t lsm6ds3tr_c_data_format_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_ble_t val); -int32_t lsm6ds3tr_c_data_format_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_ble_t* val); - -int32_t lsm6ds3tr_c_auto_increment_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_auto_increment_get(stmdev_ctx_t* ctx, uint8_t* val); - -int32_t lsm6ds3tr_c_boot_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_boot_get(stmdev_ctx_t* ctx, uint8_t* val); - -typedef enum { - LSM6DS3TR_C_XL_ST_DISABLE = 0, - LSM6DS3TR_C_XL_ST_POSITIVE = 1, - LSM6DS3TR_C_XL_ST_NEGATIVE = 2, - LSM6DS3TR_C_XL_ST_ND = 3, /* ERROR CODE */ -} lsm6ds3tr_c_st_xl_t; -int32_t lsm6ds3tr_c_xl_self_test_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_st_xl_t val); -int32_t lsm6ds3tr_c_xl_self_test_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_st_xl_t* val); - -typedef enum { - LSM6DS3TR_C_GY_ST_DISABLE = 0, - LSM6DS3TR_C_GY_ST_POSITIVE = 1, - LSM6DS3TR_C_GY_ST_NEGATIVE = 3, - LSM6DS3TR_C_GY_ST_ND = 4, /* ERROR CODE */ -} lsm6ds3tr_c_st_g_t; -int32_t lsm6ds3tr_c_gy_self_test_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_st_g_t val); -int32_t lsm6ds3tr_c_gy_self_test_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_st_g_t* val); - -int32_t lsm6ds3tr_c_filter_settling_mask_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_filter_settling_mask_get(stmdev_ctx_t* ctx, uint8_t* val); - -typedef enum { - LSM6DS3TR_C_USE_SLOPE = 0, - LSM6DS3TR_C_USE_HPF = 1, - LSM6DS3TR_C_HP_PATH_ND = 2, /* ERROR CODE */ -} lsm6ds3tr_c_slope_fds_t; -int32_t lsm6ds3tr_c_xl_hp_path_internal_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_slope_fds_t val); -int32_t lsm6ds3tr_c_xl_hp_path_internal_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_slope_fds_t* val); - -typedef enum { - LSM6DS3TR_C_XL_ANA_BW_1k5Hz = 0, - LSM6DS3TR_C_XL_ANA_BW_400Hz = 1, - LSM6DS3TR_C_XL_ANA_BW_ND = 2, /* ERROR CODE */ -} lsm6ds3tr_c_bw0_xl_t; -int32_t lsm6ds3tr_c_xl_filter_analog_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_bw0_xl_t val); -int32_t lsm6ds3tr_c_xl_filter_analog_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_bw0_xl_t* val); - -typedef enum { - LSM6DS3TR_C_XL_LP1_ODR_DIV_2 = 0, - LSM6DS3TR_C_XL_LP1_ODR_DIV_4 = 1, - LSM6DS3TR_C_XL_LP1_NA = 2, /* ERROR CODE */ -} lsm6ds3tr_c_lpf1_bw_sel_t; -int32_t lsm6ds3tr_c_xl_lp1_bandwidth_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_lpf1_bw_sel_t val); -int32_t lsm6ds3tr_c_xl_lp1_bandwidth_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_lpf1_bw_sel_t* val); - -typedef enum { - LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_50 = 0x00, - LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_100 = 0x01, - LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_9 = 0x02, - LSM6DS3TR_C_XL_LOW_LAT_LP_ODR_DIV_400 = 0x03, - LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_50 = 0x10, - LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_100 = 0x11, - LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_9 = 0x12, - LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_400 = 0x13, - LSM6DS3TR_C_XL_LP_NA = 0x20, /* ERROR CODE */ -} lsm6ds3tr_c_input_composite_t; -int32_t lsm6ds3tr_c_xl_lp2_bandwidth_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_input_composite_t val); -int32_t lsm6ds3tr_c_xl_lp2_bandwidth_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_input_composite_t* val); - -int32_t lsm6ds3tr_c_xl_reference_mode_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_xl_reference_mode_get(stmdev_ctx_t* ctx, uint8_t* val); - -typedef enum { - LSM6DS3TR_C_XL_HP_ODR_DIV_4 = 0x00, /* Slope filter */ - LSM6DS3TR_C_XL_HP_ODR_DIV_100 = 0x01, - LSM6DS3TR_C_XL_HP_ODR_DIV_9 = 0x02, - LSM6DS3TR_C_XL_HP_ODR_DIV_400 = 0x03, - LSM6DS3TR_C_XL_HP_NA = 0x10, /* ERROR CODE */ -} lsm6ds3tr_c_hpcf_xl_t; -int32_t lsm6ds3tr_c_xl_hp_bandwidth_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_hpcf_xl_t val); -int32_t lsm6ds3tr_c_xl_hp_bandwidth_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_hpcf_xl_t* val); - -typedef enum { - LSM6DS3TR_C_LP2_ONLY = 0x00, - - LSM6DS3TR_C_HP_16mHz_LP2 = 0x80, - LSM6DS3TR_C_HP_65mHz_LP2 = 0x90, - LSM6DS3TR_C_HP_260mHz_LP2 = 0xA0, - LSM6DS3TR_C_HP_1Hz04_LP2 = 0xB0, - - LSM6DS3TR_C_HP_DISABLE_LP1_LIGHT = 0x0A, - LSM6DS3TR_C_HP_DISABLE_LP1_NORMAL = 0x09, - LSM6DS3TR_C_HP_DISABLE_LP_STRONG = 0x08, - LSM6DS3TR_C_HP_DISABLE_LP1_AGGRESSIVE = 0x0B, - - LSM6DS3TR_C_HP_16mHz_LP1_LIGHT = 0x8A, - LSM6DS3TR_C_HP_65mHz_LP1_NORMAL = 0x99, - LSM6DS3TR_C_HP_260mHz_LP1_STRONG = 0xA8, - LSM6DS3TR_C_HP_1Hz04_LP1_AGGRESSIVE = 0xBB, - - LSM6DS3TR_C_HP_GY_BAND_NA = 0xFF, /* ERROR CODE */ -} lsm6ds3tr_c_lpf1_sel_g_t; -int32_t lsm6ds3tr_c_gy_band_pass_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_lpf1_sel_g_t val); -int32_t lsm6ds3tr_c_gy_band_pass_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_lpf1_sel_g_t* val); - -typedef enum { - LSM6DS3TR_C_SPI_4_WIRE = 0, - LSM6DS3TR_C_SPI_3_WIRE = 1, - LSM6DS3TR_C_SPI_MODE_ND = 2, /* ERROR CODE */ -} lsm6ds3tr_c_sim_t; -int32_t lsm6ds3tr_c_spi_mode_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_sim_t val); -int32_t lsm6ds3tr_c_spi_mode_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_sim_t* val); - -typedef enum { - LSM6DS3TR_C_I2C_ENABLE = 0, - LSM6DS3TR_C_I2C_DISABLE = 1, - LSM6DS3TR_C_I2C_MODE_ND = 2, /* ERROR CODE */ -} lsm6ds3tr_c_i2c_disable_t; -int32_t lsm6ds3tr_c_i2c_interface_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_i2c_disable_t val); -int32_t lsm6ds3tr_c_i2c_interface_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_i2c_disable_t* val); - -typedef struct { - uint8_t int1_drdy_xl : 1; - uint8_t int1_drdy_g : 1; - uint8_t int1_boot : 1; - uint8_t int1_fth : 1; - uint8_t int1_fifo_ovr : 1; - uint8_t int1_full_flag : 1; - uint8_t int1_sign_mot : 1; - uint8_t int1_step_detector : 1; - uint8_t int1_timer : 1; - uint8_t int1_tilt : 1; - uint8_t int1_6d : 1; - uint8_t int1_double_tap : 1; - uint8_t int1_ff : 1; - uint8_t int1_wu : 1; - uint8_t int1_single_tap : 1; - uint8_t int1_inact_state : 1; - uint8_t den_drdy_int1 : 1; - uint8_t drdy_on_int1 : 1; -} lsm6ds3tr_c_int1_route_t; -int32_t lsm6ds3tr_c_pin_int1_route_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_int1_route_t val); -int32_t lsm6ds3tr_c_pin_int1_route_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_int1_route_t* val); - -typedef struct { - uint8_t int2_drdy_xl : 1; - uint8_t int2_drdy_g : 1; - uint8_t int2_drdy_temp : 1; - uint8_t int2_fth : 1; - uint8_t int2_fifo_ovr : 1; - uint8_t int2_full_flag : 1; - uint8_t int2_step_count_ov : 1; - uint8_t int2_step_delta : 1; - uint8_t int2_iron : 1; - uint8_t int2_tilt : 1; - uint8_t int2_6d : 1; - uint8_t int2_double_tap : 1; - uint8_t int2_ff : 1; - uint8_t int2_wu : 1; - uint8_t int2_single_tap : 1; - uint8_t int2_inact_state : 1; - uint8_t int2_wrist_tilt : 1; -} lsm6ds3tr_c_int2_route_t; -int32_t lsm6ds3tr_c_pin_int2_route_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_int2_route_t val); -int32_t lsm6ds3tr_c_pin_int2_route_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_int2_route_t* val); - -typedef enum { - LSM6DS3TR_C_PUSH_PULL = 0, - LSM6DS3TR_C_OPEN_DRAIN = 1, - LSM6DS3TR_C_PIN_MODE_ND = 2, /* ERROR CODE */ -} lsm6ds3tr_c_pp_od_t; -int32_t lsm6ds3tr_c_pin_mode_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_pp_od_t val); -int32_t lsm6ds3tr_c_pin_mode_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_pp_od_t* val); - -typedef enum { - LSM6DS3TR_C_ACTIVE_HIGH = 0, - LSM6DS3TR_C_ACTIVE_LOW = 1, - LSM6DS3TR_C_POLARITY_ND = 2, /* ERROR CODE */ -} lsm6ds3tr_c_h_lactive_t; -int32_t lsm6ds3tr_c_pin_polarity_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_h_lactive_t val); -int32_t lsm6ds3tr_c_pin_polarity_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_h_lactive_t* val); - -int32_t lsm6ds3tr_c_all_on_int1_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_all_on_int1_get(stmdev_ctx_t* ctx, uint8_t* val); - -typedef enum { - LSM6DS3TR_C_INT_PULSED = 0, - LSM6DS3TR_C_INT_LATCHED = 1, - LSM6DS3TR_C_INT_MODE = 2, /* ERROR CODE */ -} lsm6ds3tr_c_lir_t; -int32_t lsm6ds3tr_c_int_notification_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_lir_t val); -int32_t lsm6ds3tr_c_int_notification_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_lir_t* val); - -int32_t lsm6ds3tr_c_wkup_threshold_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_wkup_threshold_get(stmdev_ctx_t* ctx, uint8_t* val); - -int32_t lsm6ds3tr_c_wkup_dur_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_wkup_dur_get(stmdev_ctx_t* ctx, uint8_t* val); - -int32_t lsm6ds3tr_c_gy_sleep_mode_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_gy_sleep_mode_get(stmdev_ctx_t* ctx, uint8_t* val); - -typedef enum { - LSM6DS3TR_C_PROPERTY_DISABLE = 0, - LSM6DS3TR_C_XL_12Hz5_GY_NOT_AFFECTED = 1, - LSM6DS3TR_C_XL_12Hz5_GY_SLEEP = 2, - LSM6DS3TR_C_XL_12Hz5_GY_PD = 3, - LSM6DS3TR_C_ACT_MODE_ND = 4, /* ERROR CODE */ -} lsm6ds3tr_c_inact_en_t; -int32_t lsm6ds3tr_c_act_mode_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_inact_en_t val); -int32_t lsm6ds3tr_c_act_mode_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_inact_en_t* val); - -int32_t lsm6ds3tr_c_act_sleep_dur_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_act_sleep_dur_get(stmdev_ctx_t* ctx, uint8_t* val); - -int32_t lsm6ds3tr_c_tap_src_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_tap_src_t* val); - -int32_t lsm6ds3tr_c_tap_detection_on_z_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_tap_detection_on_z_get(stmdev_ctx_t* ctx, uint8_t* val); - -int32_t lsm6ds3tr_c_tap_detection_on_y_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_tap_detection_on_y_get(stmdev_ctx_t* ctx, uint8_t* val); - -int32_t lsm6ds3tr_c_tap_detection_on_x_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_tap_detection_on_x_get(stmdev_ctx_t* ctx, uint8_t* val); - -int32_t lsm6ds3tr_c_tap_threshold_x_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_tap_threshold_x_get(stmdev_ctx_t* ctx, uint8_t* val); - -int32_t lsm6ds3tr_c_tap_shock_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_tap_shock_get(stmdev_ctx_t* ctx, uint8_t* val); - -int32_t lsm6ds3tr_c_tap_quiet_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_tap_quiet_get(stmdev_ctx_t* ctx, uint8_t* val); - -int32_t lsm6ds3tr_c_tap_dur_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_tap_dur_get(stmdev_ctx_t* ctx, uint8_t* val); - -typedef enum { - LSM6DS3TR_C_ONLY_SINGLE = 0, - LSM6DS3TR_C_BOTH_SINGLE_DOUBLE = 1, - LSM6DS3TR_C_TAP_MODE_ND = 2, /* ERROR CODE */ -} lsm6ds3tr_c_single_double_tap_t; -int32_t lsm6ds3tr_c_tap_mode_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_single_double_tap_t val); -int32_t lsm6ds3tr_c_tap_mode_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_single_double_tap_t* val); - -typedef enum { - LSM6DS3TR_C_ODR_DIV_2_FEED = 0, - LSM6DS3TR_C_LPF2_FEED = 1, - LSM6DS3TR_C_6D_FEED_ND = 2, /* ERROR CODE */ -} lsm6ds3tr_c_low_pass_on_6d_t; -int32_t lsm6ds3tr_c_6d_feed_data_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_low_pass_on_6d_t val); -int32_t lsm6ds3tr_c_6d_feed_data_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_low_pass_on_6d_t* val); - -typedef enum { - LSM6DS3TR_C_DEG_80 = 0, - LSM6DS3TR_C_DEG_70 = 1, - LSM6DS3TR_C_DEG_60 = 2, - LSM6DS3TR_C_DEG_50 = 3, - LSM6DS3TR_C_6D_TH_ND = 4, /* ERROR CODE */ -} lsm6ds3tr_c_sixd_ths_t; -int32_t lsm6ds3tr_c_6d_threshold_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_sixd_ths_t val); -int32_t lsm6ds3tr_c_6d_threshold_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_sixd_ths_t* val); - -int32_t lsm6ds3tr_c_4d_mode_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_4d_mode_get(stmdev_ctx_t* ctx, uint8_t* val); - -int32_t lsm6ds3tr_c_ff_dur_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_ff_dur_get(stmdev_ctx_t* ctx, uint8_t* val); - -typedef enum { - LSM6DS3TR_C_FF_TSH_156mg = 0, - LSM6DS3TR_C_FF_TSH_219mg = 1, - LSM6DS3TR_C_FF_TSH_250mg = 2, - LSM6DS3TR_C_FF_TSH_312mg = 3, - LSM6DS3TR_C_FF_TSH_344mg = 4, - LSM6DS3TR_C_FF_TSH_406mg = 5, - LSM6DS3TR_C_FF_TSH_469mg = 6, - LSM6DS3TR_C_FF_TSH_500mg = 7, - LSM6DS3TR_C_FF_TSH_ND = 8, /* ERROR CODE */ -} lsm6ds3tr_c_ff_ths_t; -int32_t lsm6ds3tr_c_ff_threshold_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_ff_ths_t val); -int32_t lsm6ds3tr_c_ff_threshold_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_ff_ths_t* val); - -int32_t lsm6ds3tr_c_fifo_watermark_set(stmdev_ctx_t* ctx, uint16_t val); -int32_t lsm6ds3tr_c_fifo_watermark_get(stmdev_ctx_t* ctx, uint16_t* val); - -int32_t lsm6ds3tr_c_fifo_data_level_get(stmdev_ctx_t* ctx, uint16_t* val); - -int32_t lsm6ds3tr_c_fifo_wtm_flag_get(stmdev_ctx_t* ctx, uint8_t* val); - -int32_t lsm6ds3tr_c_fifo_pattern_get(stmdev_ctx_t* ctx, uint16_t* val); - -int32_t lsm6ds3tr_c_fifo_temp_batch_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_fifo_temp_batch_get(stmdev_ctx_t* ctx, uint8_t* val); - -typedef enum { - LSM6DS3TR_C_TRG_XL_GY_DRDY = 0, - LSM6DS3TR_C_TRG_STEP_DETECT = 1, - LSM6DS3TR_C_TRG_SH_DRDY = 2, - LSM6DS3TR_C_TRG_SH_ND = 3, /* ERROR CODE */ -} lsm6ds3tr_c_trigger_fifo_t; -int32_t lsm6ds3tr_c_fifo_write_trigger_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_trigger_fifo_t val); -int32_t lsm6ds3tr_c_fifo_write_trigger_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_trigger_fifo_t* val); - -int32_t lsm6ds3tr_c_fifo_pedo_and_timestamp_batch_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_fifo_pedo_and_timestamp_batch_get(stmdev_ctx_t* ctx, uint8_t* val); - -typedef enum { - LSM6DS3TR_C_FIFO_XL_DISABLE = 0, - LSM6DS3TR_C_FIFO_XL_NO_DEC = 1, - LSM6DS3TR_C_FIFO_XL_DEC_2 = 2, - LSM6DS3TR_C_FIFO_XL_DEC_3 = 3, - LSM6DS3TR_C_FIFO_XL_DEC_4 = 4, - LSM6DS3TR_C_FIFO_XL_DEC_8 = 5, - LSM6DS3TR_C_FIFO_XL_DEC_16 = 6, - LSM6DS3TR_C_FIFO_XL_DEC_32 = 7, - LSM6DS3TR_C_FIFO_XL_DEC_ND = 8, /* ERROR CODE */ -} lsm6ds3tr_c_dec_fifo_xl_t; -int32_t lsm6ds3tr_c_fifo_xl_batch_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_dec_fifo_xl_t val); -int32_t lsm6ds3tr_c_fifo_xl_batch_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_dec_fifo_xl_t* val); - -typedef enum { - LSM6DS3TR_C_FIFO_GY_DISABLE = 0, - LSM6DS3TR_C_FIFO_GY_NO_DEC = 1, - LSM6DS3TR_C_FIFO_GY_DEC_2 = 2, - LSM6DS3TR_C_FIFO_GY_DEC_3 = 3, - LSM6DS3TR_C_FIFO_GY_DEC_4 = 4, - LSM6DS3TR_C_FIFO_GY_DEC_8 = 5, - LSM6DS3TR_C_FIFO_GY_DEC_16 = 6, - LSM6DS3TR_C_FIFO_GY_DEC_32 = 7, - LSM6DS3TR_C_FIFO_GY_DEC_ND = 8, /* ERROR CODE */ -} lsm6ds3tr_c_dec_fifo_gyro_t; -int32_t lsm6ds3tr_c_fifo_gy_batch_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_dec_fifo_gyro_t val); -int32_t lsm6ds3tr_c_fifo_gy_batch_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_dec_fifo_gyro_t* val); - -typedef enum { - LSM6DS3TR_C_FIFO_DS3_DISABLE = 0, - LSM6DS3TR_C_FIFO_DS3_NO_DEC = 1, - LSM6DS3TR_C_FIFO_DS3_DEC_2 = 2, - LSM6DS3TR_C_FIFO_DS3_DEC_3 = 3, - LSM6DS3TR_C_FIFO_DS3_DEC_4 = 4, - LSM6DS3TR_C_FIFO_DS3_DEC_8 = 5, - LSM6DS3TR_C_FIFO_DS3_DEC_16 = 6, - LSM6DS3TR_C_FIFO_DS3_DEC_32 = 7, - LSM6DS3TR_C_FIFO_DS3_DEC_ND = 8, /* ERROR CODE */ -} lsm6ds3tr_c_dec_ds3_fifo_t; -int32_t lsm6ds3tr_c_fifo_dataset_3_batch_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_dec_ds3_fifo_t val); -int32_t lsm6ds3tr_c_fifo_dataset_3_batch_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_dec_ds3_fifo_t* val); - -typedef enum { - LSM6DS3TR_C_FIFO_DS4_DISABLE = 0, - LSM6DS3TR_C_FIFO_DS4_NO_DEC = 1, - LSM6DS3TR_C_FIFO_DS4_DEC_2 = 2, - LSM6DS3TR_C_FIFO_DS4_DEC_3 = 3, - LSM6DS3TR_C_FIFO_DS4_DEC_4 = 4, - LSM6DS3TR_C_FIFO_DS4_DEC_8 = 5, - LSM6DS3TR_C_FIFO_DS4_DEC_16 = 6, - LSM6DS3TR_C_FIFO_DS4_DEC_32 = 7, - LSM6DS3TR_C_FIFO_DS4_DEC_ND = 8, /* ERROR CODE */ -} lsm6ds3tr_c_dec_ds4_fifo_t; -int32_t lsm6ds3tr_c_fifo_dataset_4_batch_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_dec_ds4_fifo_t val); -int32_t lsm6ds3tr_c_fifo_dataset_4_batch_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_dec_ds4_fifo_t* val); - -int32_t lsm6ds3tr_c_fifo_xl_gy_8bit_format_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_fifo_xl_gy_8bit_format_get(stmdev_ctx_t* ctx, uint8_t* val); - -int32_t lsm6ds3tr_c_fifo_stop_on_wtm_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_fifo_stop_on_wtm_get(stmdev_ctx_t* ctx, uint8_t* val); - -typedef enum { - LSM6DS3TR_C_BYPASS_MODE = 0, - LSM6DS3TR_C_FIFO_MODE = 1, - LSM6DS3TR_C_STREAM_TO_FIFO_MODE = 3, - LSM6DS3TR_C_BYPASS_TO_STREAM_MODE = 4, - LSM6DS3TR_C_STREAM_MODE = 6, - LSM6DS3TR_C_FIFO_MODE_ND = 8, /* ERROR CODE */ -} lsm6ds3tr_c_fifo_mode_t; -int32_t lsm6ds3tr_c_fifo_mode_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_fifo_mode_t val); -int32_t lsm6ds3tr_c_fifo_mode_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_fifo_mode_t* val); - -typedef enum { - LSM6DS3TR_C_FIFO_DISABLE = 0, - LSM6DS3TR_C_FIFO_12Hz5 = 1, - LSM6DS3TR_C_FIFO_26Hz = 2, - LSM6DS3TR_C_FIFO_52Hz = 3, - LSM6DS3TR_C_FIFO_104Hz = 4, - LSM6DS3TR_C_FIFO_208Hz = 5, - LSM6DS3TR_C_FIFO_416Hz = 6, - LSM6DS3TR_C_FIFO_833Hz = 7, - LSM6DS3TR_C_FIFO_1k66Hz = 8, - LSM6DS3TR_C_FIFO_3k33Hz = 9, - LSM6DS3TR_C_FIFO_6k66Hz = 10, - LSM6DS3TR_C_FIFO_RATE_ND = 11, /* ERROR CODE */ -} lsm6ds3tr_c_odr_fifo_t; -int32_t lsm6ds3tr_c_fifo_data_rate_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_odr_fifo_t val); -int32_t lsm6ds3tr_c_fifo_data_rate_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_odr_fifo_t* val); - -typedef enum { - LSM6DS3TR_C_DEN_ACT_LOW = 0, - LSM6DS3TR_C_DEN_ACT_HIGH = 1, - LSM6DS3TR_C_DEN_POL_ND = 2, /* ERROR CODE */ -} lsm6ds3tr_c_den_lh_t; -int32_t lsm6ds3tr_c_den_polarity_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_den_lh_t val); -int32_t lsm6ds3tr_c_den_polarity_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_den_lh_t* val); - -typedef enum { - LSM6DS3TR_C_DEN_DISABLE = 0, - LSM6DS3TR_C_LEVEL_FIFO = 6, - LSM6DS3TR_C_LEVEL_LETCHED = 3, - LSM6DS3TR_C_LEVEL_TRIGGER = 2, - LSM6DS3TR_C_EDGE_TRIGGER = 4, - LSM6DS3TR_C_DEN_MODE_ND = 5, /* ERROR CODE */ -} lsm6ds3tr_c_den_mode_t; -int32_t lsm6ds3tr_c_den_mode_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_den_mode_t val); -int32_t lsm6ds3tr_c_den_mode_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_den_mode_t* val); - -typedef enum { - LSM6DS3TR_C_STAMP_IN_GY_DATA = 0, - LSM6DS3TR_C_STAMP_IN_XL_DATA = 1, - LSM6DS3TR_C_STAMP_IN_GY_XL_DATA = 2, - LSM6DS3TR_C_DEN_STAMP_ND = 3, /* ERROR CODE */ -} lsm6ds3tr_c_den_xl_en_t; -int32_t lsm6ds3tr_c_den_enable_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_den_xl_en_t val); -int32_t lsm6ds3tr_c_den_enable_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_den_xl_en_t* val); - -int32_t lsm6ds3tr_c_den_mark_axis_z_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_den_mark_axis_z_get(stmdev_ctx_t* ctx, uint8_t* val); - -int32_t lsm6ds3tr_c_den_mark_axis_y_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_den_mark_axis_y_get(stmdev_ctx_t* ctx, uint8_t* val); - -int32_t lsm6ds3tr_c_den_mark_axis_x_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_den_mark_axis_x_get(stmdev_ctx_t* ctx, uint8_t* val); - -int32_t lsm6ds3tr_c_pedo_step_reset_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_pedo_step_reset_get(stmdev_ctx_t* ctx, uint8_t* val); - -int32_t lsm6ds3tr_c_pedo_sens_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_pedo_sens_get(stmdev_ctx_t* ctx, uint8_t* val); - -int32_t lsm6ds3tr_c_pedo_threshold_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_pedo_threshold_get(stmdev_ctx_t* ctx, uint8_t* val); - -typedef enum { - LSM6DS3TR_C_PEDO_AT_2g = 0, - LSM6DS3TR_C_PEDO_AT_4g = 1, - LSM6DS3TR_C_PEDO_FS_ND = 2, /* ERROR CODE */ -} lsm6ds3tr_c_pedo_fs_t; -int32_t lsm6ds3tr_c_pedo_full_scale_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_pedo_fs_t val); -int32_t lsm6ds3tr_c_pedo_full_scale_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_pedo_fs_t* val); - -int32_t lsm6ds3tr_c_pedo_debounce_steps_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_pedo_debounce_steps_get(stmdev_ctx_t* ctx, uint8_t* val); - -int32_t lsm6ds3tr_c_pedo_timeout_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_pedo_timeout_get(stmdev_ctx_t* ctx, uint8_t* val); - -int32_t lsm6ds3tr_c_pedo_steps_period_set(stmdev_ctx_t* ctx, uint8_t* buff); -int32_t lsm6ds3tr_c_pedo_steps_period_get(stmdev_ctx_t* ctx, uint8_t* buff); - -int32_t lsm6ds3tr_c_motion_sens_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_motion_sens_get(stmdev_ctx_t* ctx, uint8_t* val); - -int32_t lsm6ds3tr_c_motion_threshold_set(stmdev_ctx_t* ctx, uint8_t* buff); -int32_t lsm6ds3tr_c_motion_threshold_get(stmdev_ctx_t* ctx, uint8_t* buff); - -int32_t lsm6ds3tr_c_tilt_sens_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_tilt_sens_get(stmdev_ctx_t* ctx, uint8_t* val); - -int32_t lsm6ds3tr_c_wrist_tilt_sens_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_wrist_tilt_sens_get(stmdev_ctx_t* ctx, uint8_t* val); - -int32_t lsm6ds3tr_c_tilt_latency_set(stmdev_ctx_t* ctx, uint8_t* buff); -int32_t lsm6ds3tr_c_tilt_latency_get(stmdev_ctx_t* ctx, uint8_t* buff); - -int32_t lsm6ds3tr_c_tilt_threshold_set(stmdev_ctx_t* ctx, uint8_t* buff); -int32_t lsm6ds3tr_c_tilt_threshold_get(stmdev_ctx_t* ctx, uint8_t* buff); - -int32_t lsm6ds3tr_c_tilt_src_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_a_wrist_tilt_mask_t* val); -int32_t lsm6ds3tr_c_tilt_src_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_a_wrist_tilt_mask_t* val); - -int32_t lsm6ds3tr_c_mag_soft_iron_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_mag_soft_iron_get(stmdev_ctx_t* ctx, uint8_t* val); - -int32_t lsm6ds3tr_c_mag_hard_iron_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_mag_hard_iron_get(stmdev_ctx_t* ctx, uint8_t* val); - -int32_t lsm6ds3tr_c_mag_soft_iron_mat_set(stmdev_ctx_t* ctx, uint8_t* buff); -int32_t lsm6ds3tr_c_mag_soft_iron_mat_get(stmdev_ctx_t* ctx, uint8_t* buff); - -int32_t lsm6ds3tr_c_mag_offset_set(stmdev_ctx_t* ctx, int16_t* val); -int32_t lsm6ds3tr_c_mag_offset_get(stmdev_ctx_t* ctx, int16_t* val); - -int32_t lsm6ds3tr_c_func_en_set(stmdev_ctx_t* ctx, uint8_t val); - -int32_t lsm6ds3tr_c_sh_sync_sens_frame_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_sh_sync_sens_frame_get(stmdev_ctx_t* ctx, uint8_t* val); - -typedef enum { - LSM6DS3TR_C_RES_RATIO_2_11 = 0, - LSM6DS3TR_C_RES_RATIO_2_12 = 1, - LSM6DS3TR_C_RES_RATIO_2_13 = 2, - LSM6DS3TR_C_RES_RATIO_2_14 = 3, - LSM6DS3TR_C_RES_RATIO_ND = 4, /* ERROR CODE */ -} lsm6ds3tr_c_rr_t; -int32_t lsm6ds3tr_c_sh_sync_sens_ratio_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_rr_t val); -int32_t lsm6ds3tr_c_sh_sync_sens_ratio_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_rr_t* val); - -int32_t lsm6ds3tr_c_sh_master_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_sh_master_get(stmdev_ctx_t* ctx, uint8_t* val); - -int32_t lsm6ds3tr_c_sh_pass_through_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_sh_pass_through_get(stmdev_ctx_t* ctx, uint8_t* val); - -typedef enum { - LSM6DS3TR_C_EXT_PULL_UP = 0, - LSM6DS3TR_C_INTERNAL_PULL_UP = 1, - LSM6DS3TR_C_SH_PIN_MODE = 2, /* ERROR CODE */ -} lsm6ds3tr_c_pull_up_en_t; -int32_t lsm6ds3tr_c_sh_pin_mode_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_pull_up_en_t val); -int32_t lsm6ds3tr_c_sh_pin_mode_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_pull_up_en_t* val); - -typedef enum { - LSM6DS3TR_C_XL_GY_DRDY = 0, - LSM6DS3TR_C_EXT_ON_INT2_PIN = 1, - LSM6DS3TR_C_SH_SYNCRO_ND = 2, /* ERROR CODE */ -} lsm6ds3tr_c_start_config_t; -int32_t lsm6ds3tr_c_sh_syncro_mode_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_start_config_t val); -int32_t lsm6ds3tr_c_sh_syncro_mode_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_start_config_t* val); - -int32_t lsm6ds3tr_c_sh_drdy_on_int1_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_sh_drdy_on_int1_get(stmdev_ctx_t* ctx, uint8_t* val); - -typedef struct { - lsm6ds3tr_c_sensorhub1_reg_t sh_byte_1; - lsm6ds3tr_c_sensorhub2_reg_t sh_byte_2; - lsm6ds3tr_c_sensorhub3_reg_t sh_byte_3; - lsm6ds3tr_c_sensorhub4_reg_t sh_byte_4; - lsm6ds3tr_c_sensorhub5_reg_t sh_byte_5; - lsm6ds3tr_c_sensorhub6_reg_t sh_byte_6; - lsm6ds3tr_c_sensorhub7_reg_t sh_byte_7; - lsm6ds3tr_c_sensorhub8_reg_t sh_byte_8; - lsm6ds3tr_c_sensorhub9_reg_t sh_byte_9; - lsm6ds3tr_c_sensorhub10_reg_t sh_byte_10; - lsm6ds3tr_c_sensorhub11_reg_t sh_byte_11; - lsm6ds3tr_c_sensorhub12_reg_t sh_byte_12; - lsm6ds3tr_c_sensorhub13_reg_t sh_byte_13; - lsm6ds3tr_c_sensorhub14_reg_t sh_byte_14; - lsm6ds3tr_c_sensorhub15_reg_t sh_byte_15; - lsm6ds3tr_c_sensorhub16_reg_t sh_byte_16; - lsm6ds3tr_c_sensorhub17_reg_t sh_byte_17; - lsm6ds3tr_c_sensorhub18_reg_t sh_byte_18; -} lsm6ds3tr_c_emb_sh_read_t; -int32_t lsm6ds3tr_c_sh_read_data_raw_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_emb_sh_read_t* val); - -int32_t lsm6ds3tr_c_sh_cmd_sens_sync_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_sh_cmd_sens_sync_get(stmdev_ctx_t* ctx, uint8_t* val); - -int32_t lsm6ds3tr_c_sh_spi_sync_error_set(stmdev_ctx_t* ctx, uint8_t val); -int32_t lsm6ds3tr_c_sh_spi_sync_error_get(stmdev_ctx_t* ctx, uint8_t* val); - -typedef enum { - LSM6DS3TR_C_SLV_0 = 0, - LSM6DS3TR_C_SLV_0_1 = 1, - LSM6DS3TR_C_SLV_0_1_2 = 2, - LSM6DS3TR_C_SLV_0_1_2_3 = 3, - LSM6DS3TR_C_SLV_EN_ND = 4, /* ERROR CODE */ -} lsm6ds3tr_c_aux_sens_on_t; -int32_t lsm6ds3tr_c_sh_num_of_dev_connected_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_aux_sens_on_t val); -int32_t lsm6ds3tr_c_sh_num_of_dev_connected_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_aux_sens_on_t* val); - -typedef struct { - uint8_t slv0_add; - uint8_t slv0_subadd; - uint8_t slv0_data; -} lsm6ds3tr_c_sh_cfg_write_t; -int32_t lsm6ds3tr_c_sh_cfg_write(stmdev_ctx_t* ctx, lsm6ds3tr_c_sh_cfg_write_t* val); - -typedef struct { - uint8_t slv_add; - uint8_t slv_subadd; - uint8_t slv_len; -} lsm6ds3tr_c_sh_cfg_read_t; -int32_t lsm6ds3tr_c_sh_slv0_cfg_read(stmdev_ctx_t* ctx, lsm6ds3tr_c_sh_cfg_read_t* val); -int32_t lsm6ds3tr_c_sh_slv1_cfg_read(stmdev_ctx_t* ctx, lsm6ds3tr_c_sh_cfg_read_t* val); -int32_t lsm6ds3tr_c_sh_slv2_cfg_read(stmdev_ctx_t* ctx, lsm6ds3tr_c_sh_cfg_read_t* val); -int32_t lsm6ds3tr_c_sh_slv3_cfg_read(stmdev_ctx_t* ctx, lsm6ds3tr_c_sh_cfg_read_t* val); - -typedef enum { - LSM6DS3TR_C_SL0_NO_DEC = 0, - LSM6DS3TR_C_SL0_DEC_2 = 1, - LSM6DS3TR_C_SL0_DEC_4 = 2, - LSM6DS3TR_C_SL0_DEC_8 = 3, - LSM6DS3TR_C_SL0_DEC_ND = 4, /* ERROR CODE */ -} lsm6ds3tr_c_slave0_rate_t; -int32_t lsm6ds3tr_c_sh_slave_0_dec_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_slave0_rate_t val); -int32_t lsm6ds3tr_c_sh_slave_0_dec_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_slave0_rate_t* val); - -typedef enum { - LSM6DS3TR_C_EACH_SH_CYCLE = 0, - LSM6DS3TR_C_ONLY_FIRST_CYCLE = 1, - LSM6DS3TR_C_SH_WR_MODE_ND = 2, /* ERROR CODE */ -} lsm6ds3tr_c_write_once_t; -int32_t lsm6ds3tr_c_sh_write_mode_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_write_once_t val); -int32_t lsm6ds3tr_c_sh_write_mode_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_write_once_t* val); - -typedef enum { - LSM6DS3TR_C_SL1_NO_DEC = 0, - LSM6DS3TR_C_SL1_DEC_2 = 1, - LSM6DS3TR_C_SL1_DEC_4 = 2, - LSM6DS3TR_C_SL1_DEC_8 = 3, - LSM6DS3TR_C_SL1_DEC_ND = 4, /* ERROR CODE */ -} lsm6ds3tr_c_slave1_rate_t; -int32_t lsm6ds3tr_c_sh_slave_1_dec_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_slave1_rate_t val); -int32_t lsm6ds3tr_c_sh_slave_1_dec_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_slave1_rate_t* val); - -typedef enum { - LSM6DS3TR_C_SL2_NO_DEC = 0, - LSM6DS3TR_C_SL2_DEC_2 = 1, - LSM6DS3TR_C_SL2_DEC_4 = 2, - LSM6DS3TR_C_SL2_DEC_8 = 3, - LSM6DS3TR_C_SL2_DEC_ND = 4, /* ERROR CODE */ -} lsm6ds3tr_c_slave2_rate_t; -int32_t lsm6ds3tr_c_sh_slave_2_dec_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_slave2_rate_t val); -int32_t lsm6ds3tr_c_sh_slave_2_dec_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_slave2_rate_t* val); - -typedef enum { - LSM6DS3TR_C_SL3_NO_DEC = 0, - LSM6DS3TR_C_SL3_DEC_2 = 1, - LSM6DS3TR_C_SL3_DEC_4 = 2, - LSM6DS3TR_C_SL3_DEC_8 = 3, - LSM6DS3TR_C_SL3_DEC_ND = 4, /* ERROR CODE */ -} lsm6ds3tr_c_slave3_rate_t; -int32_t lsm6ds3tr_c_sh_slave_3_dec_set(stmdev_ctx_t* ctx, lsm6ds3tr_c_slave3_rate_t val); -int32_t lsm6ds3tr_c_sh_slave_3_dec_get(stmdev_ctx_t* ctx, lsm6ds3tr_c_slave3_rate_t* val); - -/** - * @} - * - */ - -#ifdef __cplusplus -} -#endif - -#endif /* LSM6DS3TR_C_DRIVER_H */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/airmouse/tracking/imu/imu_lsm6ds3trc.c b/airmouse/tracking/imu/lsm6ds3trc.c similarity index 73% rename from airmouse/tracking/imu/imu_lsm6ds3trc.c rename to airmouse/tracking/imu/lsm6ds3trc.c index c013fc6e611..9ea6cebe860 100644 --- a/airmouse/tracking/imu/imu_lsm6ds3trc.c +++ b/airmouse/tracking/imu/lsm6ds3trc.c @@ -1,33 +1,27 @@ -#include "lsm6ds3tr_c_reg.h" - -#include - #include "imu.h" +#include "../../lib/lsm6ds3tr-api/lsm6ds3tr-c_reg.h" -#define TAG "LSM6DS3TR-C" - -#define LSM6DS3_ADDRESS (0x6A << 1) - -static const double DEG_TO_RAD = 0.017453292519943295769236907684886; +#define LSM6DS3_TAG "LSM6DS3" +#define LSM6DS3_DEV_ADDRESS (0x6A << 1) stmdev_ctx_t lsm6ds3trc_ctx; int32_t lsm6ds3trc_write_i2c(void* handle, uint8_t reg_addr, const uint8_t* data, uint16_t len) { - if(furi_hal_i2c_write_mem(handle, LSM6DS3_ADDRESS, reg_addr, (uint8_t*)data, len, 50)) + if(furi_hal_i2c_write_mem(handle, LSM6DS3_DEV_ADDRESS, reg_addr, (uint8_t*)data, len, 50)) return 0; return -1; } int32_t lsm6ds3trc_read_i2c(void* handle, uint8_t reg_addr, uint8_t* read_data, uint16_t len) { - if(furi_hal_i2c_read_mem(handle, LSM6DS3_ADDRESS, reg_addr, read_data, len, 50)) return 0; + if(furi_hal_i2c_read_mem(handle, LSM6DS3_DEV_ADDRESS, reg_addr, read_data, len, 50)) return 0; return -1; } bool lsm6ds3trc_begin() { - FURI_LOG_I(TAG, "Init LSM6DS3TR-C"); + FURI_LOG_I(LSM6DS3_TAG, "Init LSM6DS3TR-C"); - if(!furi_hal_i2c_is_device_ready(&furi_hal_i2c_handle_external, LSM6DS3_ADDRESS, 50)) { - FURI_LOG_E(TAG, "Not ready"); + if(!furi_hal_i2c_is_device_ready(&furi_hal_i2c_handle_external, LSM6DS3_DEV_ADDRESS, 50)) { + FURI_LOG_E(LSM6DS3_TAG, "Not ready"); return false; } @@ -39,7 +33,7 @@ bool lsm6ds3trc_begin() { uint8_t whoami; lsm6ds3tr_c_device_id_get(&lsm6ds3trc_ctx, &whoami); if(whoami != LSM6DS3TR_C_ID) { - FURI_LOG_I(TAG, "Unknown model: %x", (int)whoami); + FURI_LOG_I(LSM6DS3_TAG, "Unknown model: %x", (int)whoami); return false; } @@ -59,7 +53,7 @@ bool lsm6ds3trc_begin() { lsm6ds3tr_c_gy_power_mode_set(&lsm6ds3trc_ctx, LSM6DS3TR_C_GY_HIGH_PERFORMANCE); lsm6ds3tr_c_gy_band_pass_set(&lsm6ds3trc_ctx, LSM6DS3TR_C_LP2_ONLY); - FURI_LOG_I(TAG, "Init OK"); + FURI_LOG_I(LSM6DS3_TAG, "Init OK"); return true; } @@ -76,19 +70,22 @@ int lsm6ds3trc_read(double* vec) { if(reg.status_reg.xlda) { lsm6ds3tr_c_acceleration_raw_get(&lsm6ds3trc_ctx, data); - vec[2] = (double)lsm6ds3tr_c_from_fs2g_to_mg(data[0]) / 1000; + vec[1] = (double)lsm6ds3tr_c_from_fs2g_to_mg(data[0]) / 1000; vec[0] = (double)lsm6ds3tr_c_from_fs2g_to_mg(data[1]) / 1000; - vec[1] = (double)lsm6ds3tr_c_from_fs2g_to_mg(data[2]) / 1000; + vec[2] = -(double)lsm6ds3tr_c_from_fs2g_to_mg(data[2]) / 1000; ret |= ACC_DATA_READY; } if(reg.status_reg.gda) { lsm6ds3tr_c_angular_rate_raw_get(&lsm6ds3trc_ctx, data); - vec[5] = (double)lsm6ds3tr_c_from_fs2000dps_to_mdps(data[0]) * DEG_TO_RAD / 1000; + vec[4] = (double)lsm6ds3tr_c_from_fs2000dps_to_mdps(data[0]) * DEG_TO_RAD / 1000; vec[3] = (double)lsm6ds3tr_c_from_fs2000dps_to_mdps(data[1]) * DEG_TO_RAD / 1000; - vec[4] = (double)lsm6ds3tr_c_from_fs2000dps_to_mdps(data[2]) * DEG_TO_RAD / 1000; + vec[5] = -(double)lsm6ds3tr_c_from_fs2000dps_to_mdps(data[2]) * DEG_TO_RAD / 1000; ret |= GYR_DATA_READY; } return ret; } + +struct imu_t imu_lsm6ds3trc = + {LSM6DS3_DEV_ADDRESS, lsm6ds3trc_begin, lsm6ds3trc_end, lsm6ds3trc_read, LSM6DS3_TAG}; diff --git a/airmouse/tracking/imu/lsm6dso.c b/airmouse/tracking/imu/lsm6dso.c new file mode 100644 index 00000000000..01b1020c07c --- /dev/null +++ b/airmouse/tracking/imu/lsm6dso.c @@ -0,0 +1,90 @@ +#include "imu.h" +#include "../../lib/lsm6dso-api/lsm6dso_reg.h" + +#define LSM6DSO_TAG "LSM6DO" +#define LSM6DSO_DEV_ADDRESS (0x6B << 1) + +stmdev_ctx_t lsm6dso_ctx; + +int32_t lsm6dso_write_i2c(void* handle, uint8_t reg_addr, uint8_t* data, uint16_t len) { + if(furi_hal_i2c_write_mem(handle, LSM6DSO_DEV_ADDRESS, reg_addr, data, len, 50)) return 0; + return -2; +} + +int32_t lsm6dso_read_i2c(void* handle, uint8_t reg_addr, uint8_t* read_data, uint16_t len) { + if(furi_hal_i2c_read_mem(handle, LSM6DSO_DEV_ADDRESS, reg_addr, read_data, len, 50)) return 0; + return -2; +} + +bool lsm6dso_begin() { + FURI_LOG_I(LSM6DSO_TAG, "Init LSM6DSOTR-C"); + + if(!furi_hal_i2c_is_device_ready(&furi_hal_i2c_handle_external, LSM6DSO_DEV_ADDRESS, 50)) { + FURI_LOG_E(LSM6DSO_TAG, "Not ready"); + return false; + } + + lsm6dso_ctx.write_reg = lsm6dso_write_i2c; + lsm6dso_ctx.read_reg = lsm6dso_read_i2c; + lsm6dso_ctx.mdelay = furi_delay_ms; + lsm6dso_ctx.handle = &furi_hal_i2c_handle_external; + + uint8_t whoami; + lsm6dso_device_id_get(&lsm6dso_ctx, &whoami); + if(whoami != LSM6DSO_ID) { + FURI_LOG_I(LSM6DSO_TAG, "Unknown model: %x", (int)whoami); + return false; + } + + lsm6dso_reset_set(&lsm6dso_ctx, PROPERTY_ENABLE); + uint8_t rst = PROPERTY_ENABLE; + while(rst) lsm6dso_reset_get(&lsm6dso_ctx, &rst); + + lsm6dso_block_data_update_set(&lsm6dso_ctx, PROPERTY_ENABLE); + lsm6dso_fifo_mode_set(&lsm6dso_ctx, LSM6DSO_BYPASS_MODE); + + lsm6dso_xl_data_rate_set(&lsm6dso_ctx, LSM6DSO_XL_ODR_104Hz); + lsm6dso_xl_full_scale_set(&lsm6dso_ctx, LSM6DSO_4g); + //lsm6dso_xl_lp1_bandwidth_set(&lsm6dso_ctx, LSM6DSO_XL_LP1_ODR_DIV_4); + + lsm6dso_gy_data_rate_set(&lsm6dso_ctx, LSM6DSO_GY_ODR_104Hz); + lsm6dso_gy_full_scale_set(&lsm6dso_ctx, LSM6DSO_2000dps); + lsm6dso_gy_power_mode_set(&lsm6dso_ctx, LSM6DSO_GY_HIGH_PERFORMANCE); + //lsm6dso_gy_band_pass_set(&lsm6dso_ctx, LSM6DSO_LP2_ONLY); + + FURI_LOG_I(LSM6DSO_TAG, "Init OK"); + return true; +} + +void lsm6dso_end() { + lsm6dso_xl_data_rate_set(&lsm6dso_ctx, LSM6DSO_XL_ODR_OFF); + lsm6dso_gy_data_rate_set(&lsm6dso_ctx, LSM6DSO_GY_ODR_OFF); +} + +int lsm6dso_read(double* vec) { + int ret = 0; + int16_t data[3]; + lsm6dso_reg_t reg; + lsm6dso_status_reg_get(&lsm6dso_ctx, ®.status_reg); + + if(reg.status_reg.xlda) { + lsm6dso_acceleration_raw_get(&lsm6dso_ctx, data); + vec[2] = (double)lsm6dso_from_fs2_to_mg(data[0]) / 1000; + vec[0] = (double)lsm6dso_from_fs2_to_mg(data[1]) / 1000; + vec[1] = (double)lsm6dso_from_fs2_to_mg(data[2]) / 1000; + ret |= ACC_DATA_READY; + } + + if(reg.status_reg.gda) { + lsm6dso_angular_rate_raw_get(&lsm6dso_ctx, data); + vec[5] = (double)lsm6dso_from_fs2000_to_mdps(data[0]) * DEG_TO_RAD / 1000; + vec[3] = (double)lsm6dso_from_fs2000_to_mdps(data[1]) * DEG_TO_RAD / 1000; + vec[4] = (double)lsm6dso_from_fs2000_to_mdps(data[2]) * DEG_TO_RAD / 1000; + ret |= GYR_DATA_READY; + } + + return ret; +} + +struct imu_t imu_lsm6dso = + {LSM6DSO_DEV_ADDRESS, lsm6dso_begin, lsm6dso_end, lsm6dso_read, LSM6DSO_TAG}; diff --git a/arkanoid/application.fam b/arkanoid/application.fam index 50bd202b07d..8b9004111f9 100644 --- a/arkanoid/application.fam +++ b/arkanoid/application.fam @@ -9,6 +9,6 @@ App( fap_icon="arkanoid_10px.png", fap_category="Games", fap_author="@xMasterX & @gotnull", - fap_version="1.1", + fap_version="1.2", fap_description="Arkanoid Game", ) diff --git a/arkanoid/arkanoid_game.c b/arkanoid/arkanoid_game.c index 167f6755dd3..0eec3bf6eb3 100644 --- a/arkanoid/arkanoid_game.c +++ b/arkanoid/arkanoid_game.c @@ -356,16 +356,16 @@ static void arkanoid_draw_callback(Canvas* const canvas, void* ctx) { } static void arkanoid_input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); GameEvent event = {.type = EventTypeKey, .input = *input_event}; furi_message_queue_put(event_queue, &event, FuriWaitForever); } static void arkanoid_update_timer_callback(void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); GameEvent event = {.type = EventTypeTick}; furi_message_queue_put(event_queue, &event, 0); diff --git a/asteroids/application.fam b/asteroids/application.fam index ef25980d011..1269229dfe3 100644 --- a/asteroids/application.fam +++ b/asteroids/application.fam @@ -12,6 +12,6 @@ App( fap_category="Games", fap_author="@antirez & @SimplyMinimal", fap_weburl="https://github.com/antirez/flipper-asteroids", - fap_version="1.1", + fap_version="1.2", fap_description="Asteroids game", ) diff --git a/barcode_gen/application.fam b/barcode_gen/application.fam index 0ce53c0446b..475cb0c0aac 100644 --- a/barcode_gen/application.fam +++ b/barcode_gen/application.fam @@ -11,6 +11,6 @@ App( fap_file_assets="barcode_encoding_files", fap_author="@Kingal1337", fap_weburl="https://github.com/Kingal1337/flipper-barcode-generator", - fap_version="1.2", + fap_version="1.3", fap_description="App allows you to display various barcodes on flipper screen", ) diff --git a/barcode_gen/barcode_app.c b/barcode_gen/barcode_app.c index fa0e43aa563..0cd751496cd 100644 --- a/barcode_gen/barcode_app.c +++ b/barcode_gen/barcode_app.c @@ -4,7 +4,6 @@ #include #include #include -#include /** * Opens a file browser dialog and returns the filepath of the selected file @@ -15,7 +14,14 @@ * @returns true if a file is selected */ -NotificationApp* notifications = 0; +static NotificationApp* barcode_notifications; + +const NotificationSequence sequence_display_backlight_barcode = { + &message_force_display_brightness_setting_1f, + &message_display_backlight_on, + &message_do_not_reset, + NULL, +}; static bool select_file(const char* folder, FuriString* file_path) { DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); @@ -148,6 +154,8 @@ void select_barcode_item(BarcodeApp* app) { }, true); + notification_message(barcode_notifications, &sequence_display_backlight_barcode); + view_dispatcher_switch_to_view(app->view_dispatcher, BarcodeView); } @@ -303,11 +311,11 @@ void free_app(BarcodeApp* app) { free(app); } -void set_backlight_brightness(float brightness) { - NotificationApp* notifications = furi_record_open(RECORD_NOTIFICATION); - notifications->settings.display_brightness = brightness; - notification_message(notifications, &sequence_display_backlight_on); -} +/*void set_backlight_brightness(float brightness) { + NotificationApp* barcode_notifications = furi_record_open(RECORD_NOTIFICATION); + barcode_notifications->settings.display_brightness = brightness; + notification_message(barcode_notifications, &sequence_display_backlight_on); +}*/ int32_t barcode_main(void* p) { UNUSED(p); @@ -329,12 +337,12 @@ int32_t barcode_main(void* p) { submenu_add_item(app->main_menu, "Edit Barcode", EditBarcodeItem, submenu_callback, app); - NotificationApp* notifications = furi_record_open(RECORD_NOTIFICATION); + barcode_notifications = furi_record_open(RECORD_NOTIFICATION); // Save original brightness - float originalBrightness = notifications->settings.display_brightness; + //float originalBrightness = barcode_notifications->settings.display_brightness; // force backlight and increase brightness - notification_message_block(notifications, &sequence_display_backlight_enforce_on); - set_backlight_brightness(10); // set to highest + //notification_message(barcode_notifications, &sequence_display_backlight_enforce_on); + //set_backlight_brightness(10); // set to highest /***************************** * Creating Text Input View @@ -441,8 +449,9 @@ int32_t barcode_main(void* p) { view_dispatcher_run(app->view_dispatcher); free_app(app); - notification_message_block(notifications, &sequence_display_backlight_enforce_auto); - set_backlight_brightness(originalBrightness); + notification_message_block(barcode_notifications, &sequence_display_backlight_enforce_auto); + //set_backlight_brightness(originalBrightness); + furi_record_close(RECORD_NOTIFICATION); return 0; } diff --git a/blackjack/blackjack.c b/blackjack/blackjack.c index e8093fa8d1a..cdb5b81b0ce 100644 --- a/blackjack/blackjack.c +++ b/blackjack/blackjack.c @@ -467,15 +467,17 @@ void init(GameState* game_state) { } static void input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); + AppEvent event = {.type = EventTypeKey, .input = *input_event}; furi_message_queue_put(event_queue, &event, FuriWaitForever); } static void update_timer_callback(void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); + AppEvent event = {.type = EventTypeTick}; furi_message_queue_put(event_queue, &event, 0); } diff --git a/bomberduck/application.fam b/bomberduck/application.fam index 4356b366120..a6523603ed3 100644 --- a/bomberduck/application.fam +++ b/bomberduck/application.fam @@ -12,6 +12,6 @@ App( fap_category="Games", fap_icon_assets="assets", fap_author="@leo-need-more-coffee & @xMasterX", - fap_version="1.1", + fap_version="1.2", fap_description="Bomberduck(Bomberman) Game", ) diff --git a/bpmtapper/application.fam b/bpmtapper/application.fam index e722234ad41..6aa1264491d 100644 --- a/bpmtapper/application.fam +++ b/bpmtapper/application.fam @@ -11,6 +11,6 @@ App( order=15, fap_author="@panki27", fap_weburl="https://github.com/panki27/bpm-tapper", - fap_version="1.1", + fap_version="1.2", fap_description="Tap center button to measure BPM", ) diff --git a/bpmtapper/bpm.c b/bpmtapper/bpm.c index 343776e21ee..09a34c98108 100644 --- a/bpmtapper/bpm.c +++ b/bpmtapper/bpm.c @@ -122,9 +122,9 @@ static void show_hello() { // END HELLO DIALOG } -static void input_callback(InputEvent* input_event, void* context) { - furi_assert(context); - FuriMessageQueue* event_queue = context; +static void input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); + FuriMessageQueue* event_queue = ctx; PluginEvent event = {.type = EventTypeKey, .input = *input_event}; furi_message_queue_put(event_queue, &event, FuriWaitForever); diff --git a/bt_trigger/application.fam b/bt_trigger/application.fam index d36b586108a..1de1237f5d9 100644 --- a/bt_trigger/application.fam +++ b/bt_trigger/application.fam @@ -12,6 +12,6 @@ App( fap_libs=["ble_profile"], fap_author="@Nem0oo", fap_weburl="https://github.com/Nem0oo/flipper-zero-bluetooth-trigger", - fap_version="1.3", + fap_version="1.4", fap_description="Control your smartphone camera via your Flipper Zero", ) diff --git a/bt_trigger/bt_trigger.c b/bt_trigger/bt_trigger.c index d52eb91d170..9f213710e6a 100644 --- a/bt_trigger/bt_trigger.c +++ b/bt_trigger/bt_trigger.c @@ -202,9 +202,10 @@ static void input_callback(InputEvent* input_event, void* ctx) { //Timer callback static void timer_callback(void* ctx) { - FuriMessageQueue* event_queue = ctx; //check eventqueue is not null - furi_assert(event_queue); + furi_assert(ctx); + //Getting our event queue + FuriMessageQueue* event_queue = ctx; //creating event and adding it to the event list IosTriggerEvent event = {.type = EventTypeTick}; furi_message_queue_put(event_queue, &event, 0); diff --git a/caesarcipher/application.fam b/caesarcipher/application.fam index 8dbbf80b2da..66d608b0ba2 100644 --- a/caesarcipher/application.fam +++ b/caesarcipher/application.fam @@ -13,6 +13,6 @@ App( order=20, fap_author="@panki27", fap_weburl="https://github.com/panki27/caesar-cipher", - fap_version="1.1", + fap_version="1.2", fap_description="Encrypt and decrypt text using Caesar Cipher", ) diff --git a/calculator/application.fam b/calculator/application.fam index f4298c25f22..c08201e9c55 100644 --- a/calculator/application.fam +++ b/calculator/application.fam @@ -11,6 +11,6 @@ App( fap_category="Tools", fap_author="@n-o-T-I-n-s-a-n-e", fap_weburl="https://github.com/n-o-T-I-n-s-a-n-e", - fap_version="1.1", + fap_version="1.2", fap_description="Calculator, that can calculate simple expressions", ) diff --git a/calculator/calcIcon.png b/calculator/calcIcon.png index 05cda6ce675..bfad92a2b66 100644 Binary files a/calculator/calcIcon.png and b/calculator/calcIcon.png differ diff --git a/counter/application.fam b/counter/application.fam index 324e2d3b129..9ae3ec7a6da 100644 --- a/counter/application.fam +++ b/counter/application.fam @@ -11,6 +11,6 @@ App( fap_icon_assets="icons", fap_author="@Krulknul", fap_weburl="https://github.com/Krulknul/dolphin-counter", - fap_version="1.3", + fap_version="1.4", fap_description="Simple counter", ) diff --git a/counter/counter.c b/counter/counter.c index 79c0e20f40f..2a6c55b1b9f 100644 --- a/counter/counter.c +++ b/counter/counter.c @@ -20,7 +20,7 @@ typedef struct { FuriMessageQueue* input_queue; ViewPort* view_port; Gui* gui; - FuriMutex** mutex; + FuriMutex* mutex; NotificationApp* notifications; int count; diff --git a/counter/icons/counter_icon.png b/counter/icons/counter_icon.png index 47efe68db82..29918489b15 100644 Binary files a/counter/icons/counter_icon.png and b/counter/icons/counter_icon.png differ diff --git a/cross_remote/application.fam b/cross_remote/application.fam index b19304bf526..38ccfc336b3 100644 --- a/cross_remote/application.fam +++ b/cross_remote/application.fam @@ -6,7 +6,7 @@ App( stack_size=3 * 1024, fap_icon="icons/xremote_10px.png", fap_icon_assets="icons", - fap_version="2.5", + fap_version="2.6", fap_category="Infrared", fap_author="Leedave", fap_description="One-Click, sends multiple commands", diff --git a/cross_remote/docs/changelog.md b/cross_remote/docs/changelog.md index d324e51a972..2d2ab423828 100644 --- a/cross_remote/docs/changelog.md +++ b/cross_remote/docs/changelog.md @@ -1,3 +1,6 @@ +## 2.6 +- Fix for conflict wiht SubGHz folder variable in 0.103.1-rc + ## 2.5 - Back button on info screen now reacts the same as ok button - Fixed crash on exit in fw 0.100.3 diff --git a/cross_remote/scenes/xremote_scene_ir_timer.c b/cross_remote/scenes/xremote_scene_ir_timer.c index 41a737c1d9a..ecf440eff6f 100644 --- a/cross_remote/scenes/xremote_scene_ir_timer.c +++ b/cross_remote/scenes/xremote_scene_ir_timer.c @@ -41,11 +41,6 @@ bool xremote_scene_ir_timer_on_event(void* context, SceneManagerEvent event) { if(item->time > 9999) { item->time = 9999; } - //app->first_station = atoi(app->text_store[0]); - /*if(app->first_station > app->max_station) { - app->first_station = app->max_station; - snprintf(app->text_store[0], 5, "%lu", app->first_station); - }*/ scene_manager_previous_scene(app->scene_manager); return true; } diff --git a/cross_remote/scenes/xremote_scene_sg_list.c b/cross_remote/scenes/xremote_scene_sg_list.c index b6896271947..a75bc896a3f 100644 --- a/cross_remote/scenes/xremote_scene_sg_list.c +++ b/cross_remote/scenes/xremote_scene_sg_list.c @@ -4,7 +4,8 @@ void xremote_scene_sg_list_on_enter(void* context) { XRemote* app = context; DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options(&browser_options, SUBGHZ_APP_EXTENSION, &I_sg_10px); + dialog_file_browser_set_basic_options( + &browser_options, SUBGHZ_APP_FILENAME_EXTENSION, &I_sg_10px); browser_options.base_path = SUBGHZ_APP_FOLDER; FuriString* path; diff --git a/cross_remote/scenes/xremote_scene_transmit.c b/cross_remote/scenes/xremote_scene_transmit.c index 6eeaa53bb29..339d4b7cb02 100644 --- a/cross_remote/scenes/xremote_scene_transmit.c +++ b/cross_remote/scenes/xremote_scene_transmit.c @@ -169,6 +169,11 @@ bool xremote_scene_transmit_on_event(void* context, SceneManagerEvent event) { } } else if(event.type == SceneManagerEventTypeTick) { FURI_LOG_D(TAG, "Tick Event"); + with_view_model( + xremote_transmit_get_view(app->xremote_transmit), + void* model, + { UNUSED(model); }, + true); if(app->state_notifications == SubGhzNotificationStateTx && app->led == 1) { //blink for subghz } diff --git a/cross_remote/scenes/xremote_scene_xr_list.c b/cross_remote/scenes/xremote_scene_xr_list.c index 7f069b3785d..e8592d98e13 100644 --- a/cross_remote/scenes/xremote_scene_xr_list.c +++ b/cross_remote/scenes/xremote_scene_xr_list.c @@ -26,7 +26,6 @@ void xremote_scene_xr_list_on_enter(void* context) { if(success) { //Load Remote Button View - //scene_manager_next_scene(app->scene_manager, XRemoteSceneWip); scene_manager_next_scene(app->scene_manager, XRemoteSceneTransmit); } else { //scene_manager_next_scene(app->scene_manager, XRemoteSceneWip); diff --git a/cross_remote/scenes/xremote_scene_xr_list_edit.c b/cross_remote/scenes/xremote_scene_xr_list_edit.c index e4e88b1577a..9050a0e552b 100644 --- a/cross_remote/scenes/xremote_scene_xr_list_edit.c +++ b/cross_remote/scenes/xremote_scene_xr_list_edit.c @@ -21,10 +21,8 @@ void xremote_scene_xr_list_edit_on_enter(void* context) { if(success) { //Load Remote Button View - //scene_manager_next_scene(app->scene_manager, XRemoteSceneWip); scene_manager_next_scene(app->scene_manager, XRemoteSceneXrListEditItem); } else { - //scene_manager_next_scene(app->scene_manager, XRemoteSceneWip); scene_manager_previous_scene(app->scene_manager); } } diff --git a/cross_remote/views/xremote_transmit.c b/cross_remote/views/xremote_transmit.c index 3412200e4c1..a3a37bd9480 100644 --- a/cross_remote/views/xremote_transmit.c +++ b/cross_remote/views/xremote_transmit.c @@ -100,12 +100,36 @@ void xremote_transmit_draw(Canvas* canvas, XRemoteTransmitModel* model) { } } +bool xremote_transmit_input(InputEvent* event, void* context) { + furi_assert(context); + XRemoteTransmit* instance = context; + if(event->type == InputTypeRelease) { + switch(event->key) { + case InputKeyBack: + with_view_model( + instance->view, + XRemoteTransmitModel * model, + { + UNUSED(model); + instance->callback( + XRemoteCustomEventViewTransmitterSendStop, instance->context); + }, + true); + break; + default: + break; + } + } + return true; +} + XRemoteTransmit* xremote_transmit_alloc() { XRemoteTransmit* instance = malloc(sizeof(XRemoteTransmit)); instance->view = view_alloc(); view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(XRemoteTransmitModel)); view_set_context(instance->view, instance); view_set_draw_callback(instance->view, (ViewDrawCallback)xremote_transmit_draw); + view_set_input_callback(instance->view, xremote_transmit_input); view_set_enter_callback(instance->view, xremote_transmit_enter); with_view_model( diff --git a/cross_remote/views/xremote_transmit.h b/cross_remote/views/xremote_transmit.h index 250b742f3d9..5fa483ceb0c 100644 --- a/cross_remote/views/xremote_transmit.h +++ b/cross_remote/views/xremote_transmit.h @@ -21,4 +21,6 @@ void xremote_transmit_free(XRemoteTransmit* instance); View* xremote_transmit_get_view(XRemoteTransmit* instance); -void xremote_transmit_enter(void* context); \ No newline at end of file +void xremote_transmit_enter(void* context); + +bool xremote_transmit_input(InputEvent* event, void* context); \ No newline at end of file diff --git a/cross_remote/xremote_i.h b/cross_remote/xremote_i.h index 5cbcb6aef0f..1fac5600597 100644 --- a/cross_remote/xremote_i.h +++ b/cross_remote/xremote_i.h @@ -23,9 +23,6 @@ #include #include #include - -//#include //Not found - #include #include @@ -53,14 +50,11 @@ #define XREMOTE_TEXT_STORE_SIZE 128 #define XREMOTE_MAX_ITEM_NAME_LENGTH 22 #define XREMOTE_MAX_REMOTE_NAME_LENGTH 22 -#define XREMOTE_VERSION "2.5" +#define XREMOTE_VERSION "2.6" #define INFRARED_APP_EXTENSION ".ir" #define INFRARED_APP_FOLDER ANY_PATH("infrared") -#define SUBGHZ_APP_EXTENSION ".sub" -#define SUBGHZ_APP_FOLDER ANY_PATH("subghz") - #define TAG "XRemote" typedef enum { diff --git a/doom/application.fam b/doom/application.fam index 7fe04d1d6b1..eced9b66367 100644 --- a/doom/application.fam +++ b/doom/application.fam @@ -13,6 +13,6 @@ App( fap_category="Games", fap_icon_assets="assets", fap_author="@xMasterX & @Svarich & @hedger (original code by @p4nic4ttack)", - fap_version="1.3", + fap_version="1.4", fap_description="Will it run Doom?", ) diff --git a/doom/doom.c b/doom/doom.c index e979e37d3e5..dc6b438b6bf 100644 --- a/doom/doom.c +++ b/doom/doom.c @@ -795,8 +795,8 @@ static void render_callback(Canvas* const canvas, void* ctx) { } static void input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); PluginEvent event = {.type = EventTypeKey, .input = *input_event}; furi_message_queue_put(event_queue, &event, 0); @@ -846,8 +846,8 @@ static void doom_state_init(PluginState* const plugin_state) { } static void doom_game_update_timer_callback(void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); PluginEvent event = {.type = EventTypeTick}; furi_message_queue_put(event_queue, &event, 0); diff --git a/doom/sound.h b/doom/sound.h index 514381334b1..a6f5ada4710 100644 --- a/doom/sound.h +++ b/doom/sound.h @@ -28,7 +28,7 @@ typedef struct { typedef struct { MusicPlayerModel* model; MusicPlayerWorker* worker; - FuriMutex** model_mutex; + FuriMutex* model_mutex; } MusicPlayer; #endif \ No newline at end of file diff --git a/dtmf_dolphin/application.fam b/dtmf_dolphin/application.fam index 5f3bb6a4573..522b79cbc00 100644 --- a/dtmf_dolphin/application.fam +++ b/dtmf_dolphin/application.fam @@ -13,6 +13,6 @@ App( order=20, fap_category="Tools", fap_author="@litui & @xMasterX", - fap_version="1.2", + fap_version="1.3", fap_description="DTMF (Dual-Tone Multi-Frequency) dialer, Bluebox, and Redbox.", ) diff --git a/esp8266_deauth/esp8266_deauth.c b/esp8266_deauth/esp8266_deauth.c index 69b36411d25..96bf73adb9b 100644 --- a/esp8266_deauth/esp8266_deauth.c +++ b/esp8266_deauth/esp8266_deauth.c @@ -207,8 +207,8 @@ static void esp8266_deauth_module_render_callback(Canvas* const canvas, void* ct } static void esp8266_deauth_module_input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); SPluginEvent event = {.m_type = EventTypeKey, .m_input = *input_event}; furi_message_queue_put(event_queue, &event, FuriWaitForever); diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/.github/workflows/cmake.yml b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/.github/workflows/cmake.yml index 6c56c5a4184..00ff1e5534a 100644 --- a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/.github/workflows/cmake.yml +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/.github/workflows/cmake.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-20.04 strategy: matrix: - family: [C0, F0, F1, F2, F3, F4, F7, G0, G4, H7, L0, L1, L4, L5, U5, WB, WL, MP1] + family: [C0, F0, F1, F2, F3, F4, F7, G0, G4, H5, H7, L0, L1, L4, L5, U0, U5, WB, WL, MP1] fail-fast: false steps: diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/README.md b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/README.md index 513d34bff3b..0315b65ccd1 100644 --- a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/README.md +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/README.md @@ -3,7 +3,7 @@ ![Tests](https://github.com/ObKo/stm32-cmake/workflows/Tests/badge.svg) This project is used to develop applications for the STM32 - ST's ARM Cortex-Mx MCUs. -It uses cmake and GCC, along with newlib (libc), STM32Cube. Supports C0 F0 F1 F2 F3 F4 F7 G0 G4 H7 L0 L1 L4 L5 U5 WB WL device families. +It uses cmake and GCC, along with newlib (libc), STM32Cube. Supports C0 F0 F1 F2 F3 F4 F7 G0 G4 H7 L0 L1 L4 L5 U0 U5 WB WL device families. ## Requirements @@ -56,7 +56,7 @@ The most important set of variables which needs to be set can be found in the fo These configuration options need to be set for the build process to work properly: * `STM32_CUBE__PATH` - path to STM32Cube directory, where `` is one - of `C0 F0 F1 F2 F3 F4 F7 G0 G4 H7 L0 L1 L4 L5 U5 WB WL` **default**: `/opt/STM32Cube` + of `C0 F0 F1 F2 F3 F4 F7 G0 G4 H7 L0 L1 L4 L5 U0 U5 WB WL` **default**: `/opt/STM32Cube` These configuration variables are optional: diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/FindBSP.cmake b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/FindBSP.cmake index e5617d75315..27437fa28be 100644 --- a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/FindBSP.cmake +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/FindBSP.cmake @@ -252,6 +252,17 @@ set(BSP_MP1_COMPONENTS ) set(BSP_MP1_SOURCES_STM32MP15xx_DISCO bus stpmic1) set(BSP_MP1_SOURCES_STM32MP15xx_EVAL bus stpmic1) +### U0 ### +set(BSP_U0_BOARDS + STM32U0xx_Nucleo STM32U083C_Discovery +) +set(BSP_U0_COMPONENTS + stts22h +) + +set(BSP_U0_SOURCES_STM32U083C_Discovery stts22h) +set(BSP_U0_DEVICE_STM32U083C_Discovery U083CC) + ### WB ### set(BSP_WB_BOARDS STM32WB15CC_Nucleo STM32WB55_Nucleo STM32WB55_USBDongle STM32WB5MM_Discovery diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/c0.cmake b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/c0.cmake index 165b0e03a95..28aa096cfd2 100644 --- a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/c0.cmake +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/c0.cmake @@ -23,3 +23,29 @@ target_compile_options(STM32::C0 INTERFACE target_link_options(STM32::C0 INTERFACE -mcpu=cortex-m0plus ) + +list(APPEND STM32_ALL_DEVICES + C011D6 + C011F4 + C011F6 + C011J4 + C011J6 + C031C4 + C031C6 + C031F4 + C031F6 + C031G4 + C031G6 + C031K4 + C031K6 +) + +list(APPEND STM32_SUPPORTED_FAMILIES_LONG_NAME + STM32C0 +) + +list(APPEND STM32_FETCH_FAMILIES C0) + +set(CUBE_C0_VERSION v1.1.0) +set(CMSIS_C0_VERSION v1.1.0) +set(HAL_C0_VERSION v1.1.0) diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/common.cmake b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/common.cmake index a35cf0affcd..391c34abc75 100644 --- a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/common.cmake +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/common.cmake @@ -1,12 +1,4 @@ -set(STM32_SUPPORTED_FAMILIES_LONG_NAME - STM32C0 - STM32F0 STM32F1 STM32F2 STM32F3 STM32F4 STM32F7 - STM32G0 STM32G4 - STM32H7_M4 STM32H7_M7 - STM32L0 STM32L1 STM32L4 STM32L5 - STM32U5 - STM32WB_M4 STM32WL_M4 STM32WL_M0PLUS - STM32MP1_M4 ) +include(stm32/devices) foreach(FAMILY ${STM32_SUPPORTED_FAMILIES_LONG_NAME}) # append short names (F0, F1, H7_M4, ...) to STM32_SUPPORTED_FAMILIES_SHORT_NAME @@ -379,23 +371,3 @@ if(NOT (TARGET STM32::Nano::FloatScan)) $<$:-Wl,--undefined,_scanf_float> ) endif() - -include(stm32/utilities) -include(stm32/c0) -include(stm32/f0) -include(stm32/f1) -include(stm32/f2) -include(stm32/f3) -include(stm32/f4) -include(stm32/f7) -include(stm32/g0) -include(stm32/g4) -include(stm32/h7) -include(stm32/l0) -include(stm32/l1) -include(stm32/l4) -include(stm32/l5) -include(stm32/u5) -include(stm32/wb) -include(stm32/wl) -include(stm32/mp1) diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/devices.cmake b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/devices.cmake index f69c9ba9e27..af29301a8a6 100644 --- a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/devices.cmake +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/devices.cmake @@ -1,1215 +1,69 @@ -set(STM32_ALL_DEVICES - C011D6 - C011F4 - C011F6 - C011J4 - C011J6 - C031C4 - C031C6 - C031F4 - C031F6 - C031G4 - C031G6 - C031K4 - C031K6 - F030C6 - F030C8 - F030CC - F030F4 - F030K6 - F030R8 - F030RC - F031C4 - F031C6 - F031E6 - F031F4 - F031F6 - F031G4 - F031G6 - F031K4 - F031K6 - F038C6 - F038E6 - F038F6 - F038G6 - F038K6 - F042C4 - F042C6 - F042F4 - F042F6 - F042G4 - F042G6 - F042K4 - F042K6 - F042T6 - F048C6 - F048G6 - F048T6 - F051C4 - F051C6 - F051C8 - F051K4 - F051K6 - F051K8 - F051R4 - F051R6 - F051R8 - F051T8 - F058C8 - F058R8 - F058T8 - F070C6 - F070CB - F070F6 - F070RB - F071C8 - F071CB - F071RB - F071V8 - F071VB - F072C8 - F072CB - F072R8 - F072RB - F072V8 - F072VB - F078CB - F078RB - F078VB - F091CB - F091CC - F091RB - F091RC - F091VB - F091VC - F098CC - F098RC - F098VC - F100C4 - F100C6 - F100C8 - F100CB - F100R4 - F100R6 - F100R8 - F100RB - F100RC - F100RD - F100RE - F100V8 - F100VB - F100VC - F100VD - F100VE - F100ZC - F100ZD - F100ZE - F101C4 - F101C6 - F101C8 - F101CB - F101R4 - F101R6 - F101R8 - F101RB - F101RC - F101RD - F101RE - F101RF - F101RG - F101T4 - F101T6 - F101T8 - F101TB - F101V8 - F101VB - F101VC - F101VD - F101VE - F101VF - F101VG - F101ZC - F101ZD - F101ZE - F101ZF - F101ZG - F102C4 - F102C6 - F102C8 - F102CB - F102R4 - F102R6 - F102R8 - F102RB - F103C4 - F103C6 - F103C8 - F103CB - F103R4 - F103R6 - F103R8 - F103RB - F103RC - F103RD - F103RE - F103RF - F103RG - F103T4 - F103T6 - F103T8 - F103TB - F103V8 - F103VB - F103VC - F103VD - F103VE - F103VF - F103VG - F103ZC - F103ZD - F103ZE - F103ZF - F103ZG - F105R8 - F105RB - F105RC - F105V8 - F105VB - F105VC - F107RB - F107RC - F107VB - F107VC - F205RB - F205RC - F205RE - F205RF - F205RG - F205VB - F205VC - F205VE - F205VF - F205VG - F205ZC - F205ZE - F205ZF - F205ZG - F207IC - F207IE - F207IF - F207IG - F207VC - F207VE - F207VF - F207VG - F207ZC - F207ZE - F207ZF - F207ZG - F215RE - F215RG - F215VE - F215VG - F215ZE - F215ZG - F217IE - F217IG - F217VE - F217VG - F217ZE - F217ZG - F301C6 - F301C8 - F301K6 - F301K8 - F301R6 - F301R8 - F302C6 - F302C8 - F302CB - F302CC - F302K6 - F302K8 - F302R6 - F302R8 - F302RB - F302RC - F302RD - F302RE - F302VB - F302VC - F302VD - F302VE - F302ZD - F302ZE - F303C6 - F303C8 - F303CB - F303CC - F303K6 - F303K8 - F303R6 - F303R8 - F303RB - F303RC - F303RD - F303RE - F303VB - F303VC - F303VD - F303VE - F303ZD - F303ZE - F318C8 - F318K8 - F328C8 - F334C4 - F334C6 - F334C8 - F334K4 - F334K6 - F334K8 - F334R6 - F334R8 - F358CC - F358RC - F358VC - F373C8 - F373CB - F373CC - F373R8 - F373RB - F373RC - F373V8 - F373VB - F373VC - F378CC - F378RC - F378VC - F398VE - F401CB - F401CC - F401CD - F401CE - F401RB - F401RC - F401RD - F401RE - F401VB - F401VC - F401VD - F401VE - F405OE - F405OG - F405RG - F405VG - F405ZG - F407IE - F407IG - F407VE - F407VG - F407ZE - F407ZG - F410C8 - F410CB - F410R8 - F410RB - F410T8 - F410TB - F411CC - F411CE - F411RC - F411RE - F411VC - F411VE - F412CE - F412CG - F412RE - F412RG - F412VE - F412VG - F412ZE - F412ZG - F413CG - F413CH - F413MG - F413MH - F413RG - F413RH - F413VG - F413VH - F413ZG - F413ZH - F415OG - F415RG - F415VG - F415ZG - F417IE - F417IG - F417VE - F417VG - F417ZE - F417ZG - F423CH - F423MH - F423RH - F423VH - F423ZH - F427AG - F427AI - F427IG - F427II - F427VG - F427VI - F427ZG - F427ZI - F429AG - F429AI - F429BE - F429BG - F429BI - F429IE - F429IG - F429II - F429NE - F429NG - F429NI - F429VE - F429VG - F429VI - F429ZE - F429ZG - F429ZI - F437AI - F437IG - F437II - F437VG - F437VI - F437ZG - F437ZI - F439AI - F439BG - F439BI - F439IG - F439II - F439NG - F439NI - F439VG - F439VI - F439ZG - F439ZI - F446MC - F446ME - F446RC - F446RE - F446VC - F446VE - F446ZC - F446ZE - F469AE - F469AG - F469AI - F469BE - F469BG - F469BI - F469IE - F469IG - F469II - F469NE - F469NG - F469NI - F469VE - F469VG - F469VI - F469ZE - F469ZG - F469ZI - F479AG - F479AI - F479BG - F479BI - F479IG - F479II - F479NG - F479NI - F479VG - F479VI - F479ZG - F479ZI - F722IC - F722IE - F722RC - F722RE - F722VC - F722VE - F722ZC - F722ZE - F723IC - F723IE - F723VE - F723ZC - F723ZE - F730I8 - F730R8 - F730V8 - F730Z8 - F732IE - F732RE - F732VE - F732ZE - F733IE - F733VE - F733ZE - F745IE - F745IG - F745VE - F745VG - F745ZE - F745ZG - F746BE - F746BG - F746IE - F746IG - F746NE - F746NG - F746VE - F746VG - F746ZE - F746ZG - F750N8 - F750V8 - F750Z8 - F756BG - F756IG - F756NG - F756VG - F756ZG - F765BG - F765BI - F765IG - F765II - F765NG - F765NI - F765VG - F765VI - F765ZG - F765ZI - F767BG - F767BI - F767IG - F767II - F767NG - F767NI - F767VG - F767VI - F767ZG - F767ZI - F769AI - F769BG - F769BI - F769IG - F769II - F769NG - F769NI - F777BI - F777II - F777NI - F777VI - F777ZI - F778AI - F779AI - F779BI - F779II - F779NI - G030C6 - G030C8 - G030F6 - G030J6 - G030K6 - G030K8 - G031C4 - G031C6 - G031C8 - G031F4 - G031F6 - G031F8 - G031G4 - G031G6 - G031G8 - G031J4 - G031J6 - G031K4 - G031K6 - G031K8 - G031Y8 - G041C6 - G041C8 - G041F6 - G041F8 - G041G6 - G041G8 - G041J6 - G041K6 - G041K8 - G041Y8 - G050C6 - G050C8 - G050F6 - G050K6 - G050K8 - G051C6 - G051C8 - G051F6 - G051F8 - G051G6 - G051G8 - G051K6 - G051K8 - G061C6 - G061C8 - G061F6 - G061F8 - G061G6 - G061G8 - G061K6 - G061K8 - G070CB - G070KB - G070RB - G071C6 - G071C8 - G071CB - G071EB - G071G6 - G071G8 - G071GB - G071K6 - G071K8 - G071KB - G071R6 - G071R8 - G071RB - G081CB - G081EB - G081GB - G081KB - G081RB - G0B0CE - G0B0KE - G0B0RE - G0B0VE - G0B1CB - G0B1CC - G0B1CE - G0B1KB - G0B1KC - G0B1KE - G0B1MB - G0B1MC - G0B1ME - G0B1NE - G0B1RB - G0B1RC - G0B1RE - G0B1VB - G0B1VC - G0B1VE - G0C1CC - G0C1CE - G0C1KC - G0C1KE - G0C1MC - G0C1ME - G0C1RC - G0C1RE - G0C1VC - G0C1VE - G431C6 - G431C8 - G431CB - G431K6 - G431K8 - G431KB - G431M6 - G431M8 - G431MB - G431R6 - G431R8 - G431RB - G431V6 - G431V8 - G431VB - G441CB - G441KB - G441MB - G441RB - G441VB - G471CC - G471CE - G471MC - G471ME - G471QC - G471QE - G471RC - G471RE - G471VC - G471VE - G473CB - G473CC - G473CE - G473MB - G473MC - G473ME - G473PB - G473PC - G473PE - G473QB - G473QC - G473QE - G473RB - G473RC - G473RE - G473VB - G473VC - G473VE - G474CB - G474CC - G474CE - G474MB - G474MC - G474ME - G474PB - G474PC - G474PE - G474QB - G474QC - G474QE - G474RB - G474RC - G474RE - G474VB - G474VC - G474VE - G483CE - G483ME - G483PE - G483QE - G483RE - G483VE - G484CE - G484ME - G484PE - G484QE - G484RE - G484VE - G491CC - G491KC - G491MC - G491RC - G491VC - G491CE - G491KE - G491ME - G491RE - G491VE - G4A1CE - G4A1KE - G4A1ME - G4A1RE - G4A1VE - GBK1CB - H723VE - H723VG - H723ZE - H723ZG - H725AE - H725AG - H725IE - H725IG - H725RE - H725RG - H725VE - H725VG - H725ZE - H725ZG - H730AB - H730IB - H730VB - H730ZB - H733VG - H733ZG - H735AG - H735IG - H735RG - H735VG - H735ZG - H742AG - H742AI - H742BG - H742BI - H742IG - H742II - H742VG - H742VI - H742XG - H742XI - H742ZG - H742ZI - H743AG - H743AI - H743BG - H743BI - H743IG - H743II - H743VG - H743VI - H743XG - H743XI - H743ZG - H743ZI - H745BG - H745BI - H745IG - H745II - H745XG - H745XI - H745ZG - H745ZI - H747AG - H747AI - H747BG - H747BI - H747IG - H747II - H747XG - H747XI - H747ZI - H750IB - H750VB - H750XB - H750ZB - H753AI - H753BI - H753II - H753VI - H753XI - H753ZI - H755BI - H755II - H755XI - H755ZI - H757AI - H757BI - H757II - H757XI - H757ZI - H7A3AG - H7A3AI - H7A3IG - H7A3II - H7A3LG - H7A3LI - H7A3NG - H7A3NI - H7A3QI - H7A3RG - H7A3RI - H7A3VG - H7A3VI - H7A3ZG - H7A3ZI - H7B0AB - H7B0IB - H7B0RB - H7B0VB - H7B0ZB - H7B3AI - H7B3II - H7B3LI - H7B3NI - H7B3QI - H7B3RI - H7B3VI - H7B3ZI - L010C6 - L010F4 - L010K4 - L010K8 - L010R8 - L010RB - L011D3 - L011D4 - L011E3 - L011E4 - L011F3 - L011F4 - L011G3 - L011G4 - L011K3 - L011K4 - L021D4 - L021F4 - L021G4 - L021K4 - L031C4 - L031C6 - L031E4 - L031E6 - L031F4 - L031F6 - L031G4 - L031G6 - L031K4 - L031K6 - L041C6 - L041E6 - L041F6 - L041G6 - L041K6 - L051C6 - L051C8 - L051K6 - L051K8 - L051R6 - L051R8 - L051T6 - L051T8 - L052C6 - L052C8 - L052K6 - L052K8 - L052R6 - L052R8 - L052T6 - L052T8 - L053C6 - L053C8 - L053R6 - L053R8 - L062C8 - L062K8 - L063C8 - L063R8 - L071C8 - L071CB - L071CZ - L071K8 - L071KB - L071KZ - L071RB - L071RZ - L071V8 - L071VB - L071VZ - L072CB - L072CZ - L072KB - L072KZ - L072RB - L072RZ - L072V8 - L072VB - L072VZ - L073CB - L073CZ - L073RB - L073RZ - L073V8 - L073VB - L073VZ - L081CB - L081CZ - L081KZ - L082CZ - L082KZ - L083CB - L083CZ - L083RB - L083RZ - L083V8 - L083VB - L083VZ - L100C6 - L100R8 - L100RB - L100RC - L151C6 - L151C8 - L151CB - L151CC - L151QC - L151QD - L151QE - L151R6 - L151R8 - L151RB - L151RC - L151RD - L151RE - L151UC - L151V8 - L151VB - L151VC - L151VD - L151VE - L151ZC - L151ZD - L151ZE - L152C6 - L152C8 - L152CB - L152CC - L152QC - L152QD - L152QE - L152R6 - L152R8 - L152RB - L152RC - L152RD - L152RE - L152UC - L152V8 - L152VB - L152VC - L152VD - L152VE - L152ZC - L152ZD - L152ZE - L162QC - L162QD - L162RC - L162RD - L162RE - L162VC - L162VD - L162VE - L162ZC - L162ZD - L162ZE - L412C8 - L412CB - L412K8 - L412KB - L412R8 - L412RB - L412T8 - L412TB - L422CB - L422KB - L422RB - L422TB - L431CB - L431CC - L431KB - L431KC - L431RB - L431RC - L431VC - L432KB - L432KC - L433CB - L433CC - L433RB - L433RC - L433VC - L442KC - L443CC - L443RC - L443VC - L451CC - L451CE - L451RC - L451RE - L451VC - L451VE - L452CC - L452CE - L452RC - L452RE - L452VC - L452VE - L462CE - L462RE - L462VE - L471QE - L471QG - L471RE - L471RG - L471VE - L471VG - L471ZE - L471ZG - L475RC - L475RE - L475RG - L475VC - L475VE - L475VG - L476JE - L476JG - L476ME - L476MG - L476QE - L476QG - L476RC - L476RE - L476RG - L476VC - L476VE - L476VG - L476ZE - L476ZG - L486JG - L486QG - L486RG - L486VG - L486ZG - L496AE - L496AG - L496QE - L496QG - L496RE - L496RG - L496VE - L496VG - L496ZE - L496ZG - L4A6AG - L4A6QG - L4A6RG - L4A6VG - L4A6ZG - L4P5AE - L4P5AG - L4P5CE - L4P5CG - L4P5QE - L4P5QG - L4P5RE - L4P5RG - L4P5VE - L4P5VG - L4P5ZE - L4P5ZG - L4Q5AG - L4Q5CG - L4Q5QG - L4Q5RG - L4Q5VG - L4Q5ZG - L4R5AG - L4R5AI - L4R5QG - L4R5QI - L4R5VG - L4R5VI - L4R5ZG - L4R5ZI - L4R7AI - L4R7VI - L4R7ZI - L4R9AG - L4R9AI - L4R9VG - L4R9VI - L4R9ZG - L4R9ZI - L4S5AI - L4S5QI - L4S5VI - L4S5ZI - L4S7AI - L4S7VI - L4S7ZI - L4S9AI - L4S9VI - L4S9ZI - L552CC - L552CE - L552ME - L552QC - L552QE - L552RC - L552RE - L552VC - L552VE - L552ZC - L552ZE - L562CE - L562ME - L562QE - L562RE - L562VE - L562ZE - MP151A - MP151C - MP151D - MP151F - MP153A - MP153C - MP153D - MP153F - MP157A - MP157C - MP157D - MP157F - U575CG - U575CI - U585CI - U575RG - U575RI - U585RI - U5750G - U5750I - U5850I - U575VG - U575VI - U585VI - U575QG - U575QI - U585QI - U575ZG - U575ZI - U585ZI - U575AG - U575AI - U585AI - WB5MMG - WB50CG - WB30CE - WB10CC - WB55CC - WB55CE - WB55CG - WB55RC - WB55RE - WB55RG - WB55VC - WB55VE - WB55VG - WB55VY - WB15CC - WB35CC - WB35CE - WL55CC - WL54CC - WL55JC - WL54JC - WLE5J8 - WLE5JB - WLE5JC - WLE5C8 - WLE5CB - WLE5CC - WLE4J8 - WLE4JB - WLE4JC - WLE4C8 - WLE4CB - WLE4CC -) +function(stm32_util_create_family_targets FAMILY) + set(CORES ${ARGN}) + list(LENGTH CORES NUM_CORES) + if(${NUM_CORES} EQUAL 0) + set(CORE "") + set(CORE_C "") + elseif(${NUM_CORES} EQUAL 1) + set(CORE "_${CORES}") + set(CORE_C "::${CORES}") + else() + message(FATAL_ERROR "Expected at most one core for family ${FAMILY}: ${CORES}") + endif() + + if(NOT (TARGET STM32::${FAMILY}${CORE_C})) + add_library(STM32::${FAMILY}${CORE_C} INTERFACE IMPORTED) + # Set compiler flags for target + # -Wall: all warnings activated + # -ffunction-sections -fdata-sections: remove unused code + target_compile_options(STM32::${FAMILY}${CORE_C} INTERFACE + -mthumb -Wall -ffunction-sections -fdata-sections + ) + # Set linker flags + # -mthumb: Generate thumb code + # -Wl,--gc-sections: Remove unused code + target_link_options(STM32::${FAMILY}${CORE_C} INTERFACE + -mthumb -Wl,--gc-sections + ) + target_compile_definitions(STM32::${FAMILY}${CORE_C} INTERFACE + STM32${FAMILY} + ) + endif() + foreach(TYPE ${STM32_${FAMILY}_TYPES}) + if(NOT (TARGET STM32::${TYPE}${CORE_C})) + add_library(STM32::${TYPE}${CORE_C} INTERFACE IMPORTED) + target_link_libraries(STM32::${TYPE}${CORE_C} INTERFACE STM32::${FAMILY}${CORE_C}) + target_compile_definitions(STM32::${TYPE}${CORE_C} INTERFACE + STM32${TYPE} + ) + endif() + endforeach() +endfunction() + +set(STM32_ALL_DEVICES "") +set(STM32_SUPPORTED_FAMILIES_LONG_NAME "") + +include(stm32/c0) +include(stm32/f0) +include(stm32/f1) +include(stm32/f2) +include(stm32/f3) +include(stm32/f4) +include(stm32/f7) +include(stm32/g0) +include(stm32/g4) +include(stm32/h5) +include(stm32/h7) +include(stm32/l0) +include(stm32/l1) +include(stm32/l4) +include(stm32/l5) +include(stm32/u0) +include(stm32/u5) +include(stm32/wb) +include(stm32/wl) +include(stm32/mp1) + # Store a list of devices into a given STM_DEVICES list. # You can also specify multiple device families. Examples: @@ -1304,3 +158,112 @@ macro(stm32_pretty_print_dev_list FAMILIES STM_DEVICES) message(STATUS "${TMP_LIST}") endif() endmacro() + + + +include(FetchContent) + +FetchContent_Declare( + STM32-CMSIS + GIT_REPOSITORY https://github.com/STMicroelectronics/cmsis_core/ + GIT_TAG v5.6.0 + GIT_PROGRESS TRUE +) + +foreach(FAMILY ${STM32_FETCH_FAMILIES}) + string(TOLOWER ${FAMILY} FAMILY_L) + + FetchContent_Declare( + STM32Cube${FAMILY} + GIT_REPOSITORY https://github.com/STMicroelectronics/STM32Cube${FAMILY}/ + GIT_TAG ${CUBE_${FAMILY}_VERSION} + GIT_PROGRESS TRUE + ) + + if(CMSIS_${FAMILY}_VERSION STREQUAL cube) + set(STM32_USE_CMSIS_FROM_CUBE_${FAMILY} ON) + else() + FetchContent_Declare( + STM32-CMSIS-${FAMILY} + GIT_REPOSITORY https://github.com/STMicroelectronics/cmsis_device_${FAMILY_L}/ + GIT_TAG ${CMSIS_${FAMILY}_VERSION} + GIT_PROGRESS TRUE + ) + endif() + + if(HAL_${FAMILY}_VERSION STREQUAL cube) + set(STM32_USE_HAL_FROM_CUBE_${FAMILY} ON) + else() + FetchContent_Declare( + STM32-HAL-${FAMILY} + GIT_REPOSITORY https://github.com/STMicroelectronics/stm32${FAMILY_L}xx_hal_driver/ + GIT_TAG ${HAL_${FAMILY}_VERSION} + GIT_PROGRESS TRUE + ) + endif() + +endforeach() + +function(stm32_fetch_cube) + foreach(FAMILY ${ARGV}) + set(CUBE_NAME STM32Cube${FAMILY}) + string(TOLOWER ${CUBE_NAME} CUBE_NAME_L) + + if(STM32_CUBE_${FAMILY}_PATH) + message(VERBOSE "STM32_CUBE_${FAMILY}_PATH specified, skipping fetch for ${CUBE_NAME}") + continue() + endif() + + FetchContent_MakeAvailable(${CUBE_NAME}) + set(STM32_CUBE_${FAMILY}_PATH ${${CUBE_NAME_L}_SOURCE_DIR} PARENT_SCOPE) + endforeach() +endfunction() + +function(stm32_fetch_cmsis) + if(NOT STM32_CMSIS_PATH) + FetchContent_MakeAvailable(STM32-CMSIS) + set(STM32_CMSIS_PATH ${stm32-cmsis_SOURCE_DIR} PARENT_SCOPE) + else() + message(INFO "STM32_CMSIS_PATH specified, skipping fetch for STM32-CMSIS") + endif() + + foreach(FAMILY ${ARGV}) + if(STM32_USE_CMSIS_FROM_CUBE_${FAMILY}) + stm32_fetch_cube(${FAMILY}) + message(STATUS "Cube fetched for ${FAMILY} at ${STM32_CUBE_${FAMILY}_PATH}") + set(STM32_CMSIS_${FAMILY}_PATH ${STM32_CUBE_${FAMILY}_PATH}/Drivers/CMSIS/Device/ST/STM32${FAMILY}xx PARENT_SCOPE) + else() + set(CMSIS_NAME STM32-CMSIS-${FAMILY}) + string(TOLOWER ${CMSIS_NAME} CMSIS_NAME_L) + + if(STM32_CMSIS_${FAMILY}_PATH) + message(INFO "STM32_CMSIS_${FAMILY}_PATH specified, skipping fetch for ${CMSIS_NAME}") + continue() + endif() + + FetchContent_MakeAvailable(${CMSIS_NAME}) + set(STM32_CMSIS_${FAMILY}_PATH ${${CMSIS_NAME_L}_SOURCE_DIR} PARENT_SCOPE) + endif() + endforeach() +endfunction() + +function(stm32_fetch_hal) + foreach(FAMILY ${ARGV}) + if(STM32_USE_HAL_FROM_CUBE_${FAMILY}) + stm32_fetch_cube(${FAMILY}) + message(STATUS "Cube fetched for ${FAMILY} at ${STM32_CUBE_${FAMILY}_PATH}") + set(STM32_HAL_${FAMILY}_PATH ${STM32_CUBE_${FAMILY}_PATH}/Drivers/STM32${FAMILY}xx_HAL_Driver PARENT_SCOPE) + else() + set(HAL_NAME STM32-HAL-${FAMILY}) + string(TOLOWER ${HAL_NAME} HAL_NAME_L) + + if(STM32_HAL_${FAMILY}_PATH) + message(INFO "STM32_HAL_${FAMILY}_PATH specified, skipping fetch for ${HAL_NAME}") + continue() + endif() + + FetchContent_MakeAvailable(${HAL_NAME}) + set(STM32_HAL_${FAMILY}_PATH ${${HAL_NAME_L}_SOURCE_DIR} PARENT_SCOPE) + endif() + endforeach() +endfunction() diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/f0.cmake b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/f0.cmake index 92d5e7a3532..e52846bdb7f 100644 --- a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/f0.cmake +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/f0.cmake @@ -23,3 +23,89 @@ target_compile_options(STM32::F0 INTERFACE target_link_options(STM32::F0 INTERFACE -mcpu=cortex-m0 ) + +list(APPEND STM32_ALL_DEVICES + F030C6 + F030C8 + F030CC + F030F4 + F030K6 + F030R8 + F030RC + F031C4 + F031C6 + F031E6 + F031F4 + F031F6 + F031G4 + F031G6 + F031K4 + F031K6 + F038C6 + F038E6 + F038F6 + F038G6 + F038K6 + F042C4 + F042C6 + F042F4 + F042F6 + F042G4 + F042G6 + F042K4 + F042K6 + F042T6 + F048C6 + F048G6 + F048T6 + F051C4 + F051C6 + F051C8 + F051K4 + F051K6 + F051K8 + F051R4 + F051R6 + F051R8 + F051T8 + F058C8 + F058R8 + F058T8 + F070C6 + F070CB + F070F6 + F070RB + F071C8 + F071CB + F071RB + F071V8 + F071VB + F072C8 + F072CB + F072R8 + F072RB + F072V8 + F072VB + F078CB + F078RB + F078VB + F091CB + F091CC + F091RB + F091RC + F091VB + F091VC + F098CC + F098RC + F098VC +) + +list(APPEND STM32_SUPPORTED_FAMILIES_LONG_NAME + STM32F0 +) + +list(APPEND STM32_FETCH_FAMILIES F0) + +set(CUBE_F0_VERSION v1.11.2) +set(CMSIS_F0_VERSION v2.3.5) +set(HAL_F0_VERSION v1.7.5) diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/f1.cmake b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/f1.cmake index bc97ceb6775..08d68892482 100644 --- a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/f1.cmake +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/f1.cmake @@ -76,3 +76,111 @@ function(stm32f1_get_memory_info DEVICE TYPE FLASH_SIZE RAM_SIZE) set(${RAM_SIZE} ${RAM} PARENT_SCOPE) endfunction() + +list(APPEND STM32_ALL_DEVICES + F100C4 + F100C6 + F100C8 + F100CB + F100R4 + F100R6 + F100R8 + F100RB + F100RC + F100RD + F100RE + F100V8 + F100VB + F100VC + F100VD + F100VE + F100ZC + F100ZD + F100ZE + F101C4 + F101C6 + F101C8 + F101CB + F101R4 + F101R6 + F101R8 + F101RB + F101RC + F101RD + F101RE + F101RF + F101RG + F101T4 + F101T6 + F101T8 + F101TB + F101V8 + F101VB + F101VC + F101VD + F101VE + F101VF + F101VG + F101ZC + F101ZD + F101ZE + F101ZF + F101ZG + F102C4 + F102C6 + F102C8 + F102CB + F102R4 + F102R6 + F102R8 + F102RB + F103C4 + F103C6 + F103C8 + F103CB + F103R4 + F103R6 + F103R8 + F103RB + F103RC + F103RD + F103RE + F103RF + F103RG + F103T4 + F103T6 + F103T8 + F103TB + F103V8 + F103VB + F103VC + F103VD + F103VE + F103VF + F103VG + F103ZC + F103ZD + F103ZE + F103ZF + F103ZG + F105R8 + F105RB + F105RC + F105V8 + F105VB + F105VC + F107RB + F107RC + F107VB + F107VC +) + +list(APPEND STM32_SUPPORTED_FAMILIES_LONG_NAME + STM32F1 +) + +list(APPEND STM32_FETCH_FAMILIES F1) + +set(CUBE_F1_VERSION v1.8.4) +set(CMSIS_F1_VERSION v4.3.3) +set(HAL_F1_VERSION v1.1.8) diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/f2.cmake b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/f2.cmake index 38c2c2a543a..2f266c70352 100644 --- a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/f2.cmake +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/f2.cmake @@ -37,3 +37,54 @@ function(stm32f2_get_memory_info DEVICE TYPE FLASH_SIZE RAM_SIZE) set(${RAM_SIZE} ${RAM} PARENT_SCOPE) endif() endfunction() + +list(APPEND STM32_ALL_DEVICES + F205RB + F205RC + F205RE + F205RF + F205RG + F205VB + F205VC + F205VE + F205VF + F205VG + F205ZC + F205ZE + F205ZF + F205ZG + F207IC + F207IE + F207IF + F207IG + F207VC + F207VE + F207VF + F207VG + F207ZC + F207ZE + F207ZF + F207ZG + F215RE + F215RG + F215VE + F215VG + F215ZE + F215ZG + F217IE + F217IG + F217VE + F217VG + F217ZE + F217ZG +) + +list(APPEND STM32_SUPPORTED_FAMILIES_LONG_NAME + STM32F2 +) + +list(APPEND STM32_FETCH_FAMILIES F2) + +set(CUBE_F2_VERSION v1.9.3) +set(CMSIS_F2_VERSION v2.2.5) +set(HAL_F2_VERSION v1.2.7) diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/f3.cmake b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/f3.cmake index 7c3845b428b..49a2a5517b1 100644 --- a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/f3.cmake +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/f3.cmake @@ -57,3 +57,85 @@ function(stm32f3_get_memory_info DEVICE TYPE FLASH_SIZE RAM_SIZE) set(${RAM_SIZE} ${RAM} PARENT_SCOPE) endif() endfunction() + +list(APPEND STM32_ALL_DEVICES + F301C6 + F301C8 + F301K6 + F301K8 + F301R6 + F301R8 + F302C6 + F302C8 + F302CB + F302CC + F302K6 + F302K8 + F302R6 + F302R8 + F302RB + F302RC + F302RD + F302RE + F302VB + F302VC + F302VD + F302VE + F302ZD + F302ZE + F303C6 + F303C8 + F303CB + F303CC + F303K6 + F303K8 + F303R6 + F303R8 + F303RB + F303RC + F303RD + F303RE + F303VB + F303VC + F303VD + F303VE + F303ZD + F303ZE + F318C8 + F318K8 + F328C8 + F334C4 + F334C6 + F334C8 + F334K4 + F334K6 + F334K8 + F334R6 + F334R8 + F358CC + F358RC + F358VC + F373C8 + F373CB + F373CC + F373R8 + F373RB + F373RC + F373V8 + F373VB + F373VC + F378CC + F378RC + F378VC + F398VE +) + +list(APPEND STM32_SUPPORTED_FAMILIES_LONG_NAME + STM32F3 +) + +list(APPEND STM32_FETCH_FAMILIES F3) + +set(CUBE_F3_VERSION v1.11.2) +set(CMSIS_F3_VERSION v2.3.5) +set(HAL_F3_VERSION v1.5.5) diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/f4.cmake b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/f4.cmake index 06d1d9eb5ad..a98cfba6f6b 100644 --- a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/f4.cmake +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/f4.cmake @@ -27,3 +27,165 @@ target_compile_options(STM32::F4 INTERFACE target_link_options(STM32::F4 INTERFACE -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard ) + +list(APPEND STM32_ALL_DEVICES + F401CB + F401CC + F401CD + F401CE + F401RB + F401RC + F401RD + F401RE + F401VB + F401VC + F401VD + F401VE + F405OE + F405OG + F405RG + F405VG + F405ZG + F407IE + F407IG + F407VE + F407VG + F407ZE + F407ZG + F410C8 + F410CB + F410R8 + F410RB + F410T8 + F410TB + F411CC + F411CE + F411RC + F411RE + F411VC + F411VE + F412CE + F412CG + F412RE + F412RG + F412VE + F412VG + F412ZE + F412ZG + F413CG + F413CH + F413MG + F413MH + F413RG + F413RH + F413VG + F413VH + F413ZG + F413ZH + F415OG + F415RG + F415VG + F415ZG + F417IE + F417IG + F417VE + F417VG + F417ZE + F417ZG + F423CH + F423MH + F423RH + F423VH + F423ZH + F427AG + F427AI + F427IG + F427II + F427VG + F427VI + F427ZG + F427ZI + F429AG + F429AI + F429BE + F429BG + F429BI + F429IE + F429IG + F429II + F429NE + F429NG + F429NI + F429VE + F429VG + F429VI + F429ZE + F429ZG + F429ZI + F437AI + F437IG + F437II + F437VG + F437VI + F437ZG + F437ZI + F439AI + F439BG + F439BI + F439IG + F439II + F439NG + F439NI + F439VG + F439VI + F439ZG + F439ZI + F446MC + F446ME + F446RC + F446RE + F446VC + F446VE + F446ZC + F446ZE + F469AE + F469AG + F469AI + F469BE + F469BG + F469BI + F469IE + F469IG + F469II + F469NE + F469NG + F469NI + F469VE + F469VG + F469VI + F469ZE + F469ZG + F469ZI + F479AG + F479AI + F479BG + F479BI + F479IG + F479II + F479NG + F479NI + F479VG + F479VI + F479ZG + F479ZI +) + +list(APPEND STM32_SUPPORTED_FAMILIES_LONG_NAME + STM32F4 +) + +list(APPEND STM32_FETCH_FAMILIES F4) + +set(CUBE_F4_VERSION v1.28.0) +set(CMSIS_F4_VERSION v2.6.9) +set(HAL_F4_VERSION v1.8.2) diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/f7.cmake b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/f7.cmake index cd9d87e7f14..68c5acefa7c 100644 --- a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/f7.cmake +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/f7.cmake @@ -23,3 +23,101 @@ target_compile_options(STM32::F7 INTERFACE target_link_options(STM32::F7 INTERFACE -mcpu=cortex-m7 -mfpu=fpv5-sp-d16 -mfloat-abi=hard ) + +list(APPEND STM32_ALL_DEVICES + F722IC + F722IE + F722RC + F722RE + F722VC + F722VE + F722ZC + F722ZE + F723IC + F723IE + F723VE + F723ZC + F723ZE + F730I8 + F730R8 + F730V8 + F730Z8 + F732IE + F732RE + F732VE + F732ZE + F733IE + F733VE + F733ZE + F745IE + F745IG + F745VE + F745VG + F745ZE + F745ZG + F746BE + F746BG + F746IE + F746IG + F746NE + F746NG + F746VE + F746VG + F746ZE + F746ZG + F750N8 + F750V8 + F750Z8 + F756BG + F756IG + F756NG + F756VG + F756ZG + F765BG + F765BI + F765IG + F765II + F765NG + F765NI + F765VG + F765VI + F765ZG + F765ZI + F767BG + F767BI + F767IG + F767II + F767NG + F767NI + F767VG + F767VI + F767ZG + F767ZI + F769AI + F769BG + F769BI + F769IG + F769II + F769NG + F769NI + F777BI + F777II + F777NI + F777VI + F777ZI + F778AI + F779AI + F779BI + F779II + F779NI +) + +list(APPEND STM32_SUPPORTED_FAMILIES_LONG_NAME + STM32F7 +) + +list(APPEND STM32_FETCH_FAMILIES F7) + +set(CUBE_F7_VERSION v1.16.1) +set(CMSIS_F7_VERSION v1.2.6) +set(HAL_F7_VERSION v1.2.9) diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/g0.cmake b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/g0.cmake index ce362099b55..f3c20a5501f 100644 --- a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/g0.cmake +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/g0.cmake @@ -23,3 +23,119 @@ target_compile_options(STM32::G0 INTERFACE target_link_options(STM32::G0 INTERFACE -mcpu=cortex-m0plus ) + +list(APPEND STM32_ALL_DEVICES + G030C6 + G030C8 + G030F6 + G030J6 + G030K6 + G030K8 + G031C4 + G031C6 + G031C8 + G031F4 + G031F6 + G031F8 + G031G4 + G031G6 + G031G8 + G031J4 + G031J6 + G031K4 + G031K6 + G031K8 + G031Y8 + G041C6 + G041C8 + G041F6 + G041F8 + G041G6 + G041G8 + G041J6 + G041K6 + G041K8 + G041Y8 + G050C6 + G050C8 + G050F6 + G050K6 + G050K8 + G051C6 + G051C8 + G051F6 + G051F8 + G051G6 + G051G8 + G051K6 + G051K8 + G061C6 + G061C8 + G061F6 + G061F8 + G061G6 + G061G8 + G061K6 + G061K8 + G070CB + G070KB + G070RB + G071C6 + G071C8 + G071CB + G071EB + G071G6 + G071G8 + G071GB + G071K6 + G071K8 + G071KB + G071R6 + G071R8 + G071RB + G081CB + G081EB + G081GB + G081KB + G081RB + G0B0CE + G0B0KE + G0B0RE + G0B0VE + G0B1CB + G0B1CC + G0B1CE + G0B1KB + G0B1KC + G0B1KE + G0B1MB + G0B1MC + G0B1ME + G0B1NE + G0B1RB + G0B1RC + G0B1RE + G0B1VB + G0B1VC + G0B1VE + G0C1CC + G0C1CE + G0C1KC + G0C1KE + G0C1MC + G0C1ME + G0C1RC + G0C1RE + G0C1VC + G0C1VE +) + +list(APPEND STM32_SUPPORTED_FAMILIES_LONG_NAME + STM32G0 +) + +list(APPEND STM32_FETCH_FAMILIES G0) + +set(CUBE_G0_VERSION v1.4.1) +set(CMSIS_G0_VERSION v1.4.0) +set(HAL_G0_VERSION v1.4.1) diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/g4.cmake b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/g4.cmake index f05b5757f71..380f1a9b418 100644 --- a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/g4.cmake +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/g4.cmake @@ -23,3 +23,110 @@ target_compile_options(STM32::G4 INTERFACE target_link_options(STM32::G4 INTERFACE -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard ) + +list(APPEND STM32_ALL_DEVICES + G431C6 + G431C8 + G431CB + G431K6 + G431K8 + G431KB + G431M6 + G431M8 + G431MB + G431R6 + G431R8 + G431RB + G431V6 + G431V8 + G431VB + G441CB + G441KB + G441MB + G441RB + G441VB + G471CC + G471CE + G471MC + G471ME + G471QC + G471QE + G471RC + G471RE + G471VC + G471VE + G473CB + G473CC + G473CE + G473MB + G473MC + G473ME + G473PB + G473PC + G473PE + G473QB + G473QC + G473QE + G473RB + G473RC + G473RE + G473VB + G473VC + G473VE + G474CB + G474CC + G474CE + G474MB + G474MC + G474ME + G474PB + G474PC + G474PE + G474QB + G474QC + G474QE + G474RB + G474RC + G474RE + G474VB + G474VC + G474VE + G483CE + G483ME + G483PE + G483QE + G483RE + G483VE + G484CE + G484ME + G484PE + G484QE + G484RE + G484VE + G491CC + G491KC + G491MC + G491RC + G491VC + G491CE + G491KE + G491ME + G491RE + G491VE + G4A1CE + G4A1KE + G4A1ME + G4A1RE + G4A1VE + GBK1CB +) + +list(APPEND STM32_SUPPORTED_FAMILIES_LONG_NAME + STM32G4 +) + +list(APPEND STM32_FETCH_FAMILIES G4) + +set(CUBE_G4_VERSION v1.4.0) +set(CMSIS_G4_VERSION v1.2.1) +set(HAL_G4_VERSION v1.2.1) diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/h5.cmake b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/h5.cmake new file mode 100644 index 00000000000..ec3e9003ac2 --- /dev/null +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/h5.cmake @@ -0,0 +1,67 @@ +set(STM32_H5_TYPES + H503xx H562xx H563xx H573xx +) + +set(STM32_H5_TYPE_MATCH + "H503.." "H562.." "H563.." "H573.." +) +set(STM32_H5_RAM_SIZES + 32K 640K 640K 640K +) +set(STM32_H5_CCRAM_SIZES + 0K 0K 0K 0K +) + +stm32_util_create_family_targets(H5) + +target_compile_options(STM32::H5 INTERFACE + -mcpu=cortex-m33 -mfloat-abi=hard -mfpu=fpv5-sp-d16 -mthumb +) + +target_link_options(STM32::H5 INTERFACE + -mcpu=cortex-m33 -mfloat-abi=hard -mfpu=fpv5-sp-d16 -mthumb +) + +list(APPEND STM32_ALL_DEVICES + H503CB + H503EB + H503KB + H503RB + H562AG + H562AI + H562IG + H562II + H562RG + H562RI + H562VG + H562VI + H562ZG + H562ZI + H563AG + H563AI + H563IG + H563II + H563MI + H563RG + H563RI + H563VG + H563VI + H563ZG + H563ZI + H573AI + H573II + H573MI + H573RI + H573VI + H573ZI +) + +list(APPEND STM32_SUPPORTED_FAMILIES_LONG_NAME + STM32H5 +) + +list(APPEND STM32_FETCH_FAMILIES H5) + +set(CUBE_H5_VERSION v1.1.0) +set(CMSIS_H5_VERSION v1.1.0) +set(HAL_H5_VERSION v1.1.0) diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/h7.cmake b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/h7.cmake index b94101482f4..ac5d5d76a38 100644 --- a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/h7.cmake +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/h7.cmake @@ -85,3 +85,130 @@ function(stm32h7_get_device_cores DEVICE TYPE CORES) set(${CORES} M7 PARENT_SCOPE) endif() endfunction() + +list(APPEND STM32_ALL_DEVICES + H723VE + H723VG + H723ZE + H723ZG + H725AE + H725AG + H725IE + H725IG + H725RE + H725RG + H725VE + H725VG + H725ZE + H725ZG + H730AB + H730IB + H730VB + H730ZB + H733VG + H733ZG + H735AG + H735IG + H735RG + H735VG + H735ZG + H742AG + H742AI + H742BG + H742BI + H742IG + H742II + H742VG + H742VI + H742XG + H742XI + H742ZG + H742ZI + H743AG + H743AI + H743BG + H743BI + H743IG + H743II + H743VG + H743VI + H743XG + H743XI + H743ZG + H743ZI + H745BG + H745BI + H745IG + H745II + H745XG + H745XI + H745ZG + H745ZI + H747AG + H747AI + H747BG + H747BI + H747IG + H747II + H747XG + H747XI + H747ZI + H750IB + H750VB + H750XB + H750ZB + H753AI + H753BI + H753II + H753VI + H753XI + H753ZI + H755BI + H755II + H755XI + H755ZI + H757AI + H757BI + H757II + H757XI + H757ZI + H7A3AG + H7A3AI + H7A3IG + H7A3II + H7A3LG + H7A3LI + H7A3NG + H7A3NI + H7A3QI + H7A3RG + H7A3RI + H7A3VG + H7A3VI + H7A3ZG + H7A3ZI + H7B0AB + H7B0IB + H7B0RB + H7B0VB + H7B0ZB + H7B3AI + H7B3II + H7B3LI + H7B3NI + H7B3QI + H7B3RI + H7B3VI + H7B3ZI +) + +list(APPEND STM32_SUPPORTED_FAMILIES_LONG_NAME + STM32H7_M4 + STM32H7_M7 +) + +list(APPEND STM32_FETCH_FAMILIES H7) + +set(CUBE_H7_VERSION v1.9.0) +set(CMSIS_H7_VERSION v1.10.0) +set(HAL_H7_VERSION v1.10.0) diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/l0.cmake b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/l0.cmake index abc5dfd1dd4..01d6053cbe2 100644 --- a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/l0.cmake +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/l0.cmake @@ -27,3 +27,114 @@ target_compile_options(STM32::L0 INTERFACE target_link_options(STM32::L0 INTERFACE -mcpu=cortex-m0plus ) + +list(APPEND STM32_ALL_DEVICES + L010C6 + L010F4 + L010K4 + L010K8 + L010R8 + L010RB + L011D3 + L011D4 + L011E3 + L011E4 + L011F3 + L011F4 + L011G3 + L011G4 + L011K3 + L011K4 + L021D4 + L021F4 + L021G4 + L021K4 + L031C4 + L031C6 + L031E4 + L031E6 + L031F4 + L031F6 + L031G4 + L031G6 + L031K4 + L031K6 + L041C6 + L041E6 + L041F6 + L041G6 + L041K6 + L051C6 + L051C8 + L051K6 + L051K8 + L051R6 + L051R8 + L051T6 + L051T8 + L052C6 + L052C8 + L052K6 + L052K8 + L052R6 + L052R8 + L052T6 + L052T8 + L053C6 + L053C8 + L053R6 + L053R8 + L062C8 + L062K8 + L063C8 + L063R8 + L071C8 + L071CB + L071CZ + L071K8 + L071KB + L071KZ + L071RB + L071RZ + L071V8 + L071VB + L071VZ + L072CB + L072CZ + L072KB + L072KZ + L072RB + L072RZ + L072V8 + L072VB + L072VZ + L073CB + L073CZ + L073RB + L073RZ + L073V8 + L073VB + L073VZ + L081CB + L081CZ + L081KZ + L082CZ + L082KZ + L083CB + L083CZ + L083RB + L083RZ + L083V8 + L083VB + L083VZ +) + +list(APPEND STM32_SUPPORTED_FAMILIES_LONG_NAME + STM32L0 +) + +list(APPEND STM32_FETCH_FAMILIES L0) + +set(CUBE_L0_VERSION v1.12.0) +set(CMSIS_L0_VERSION v1.9.1) +set(HAL_L0_VERSION v1.10.4) diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/l1.cmake b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/l1.cmake index 84feb792b5a..3d5a6a90dc6 100644 --- a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/l1.cmake +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/l1.cmake @@ -71,3 +71,75 @@ function(stm32l1_get_memory_info DEVICE TYPE FLASH_SIZE RAM_SIZE) set(${RAM_SIZE} ${RAM} PARENT_SCOPE) endif() endfunction() + +list(APPEND STM32_ALL_DEVICES + L100C6 + L100R8 + L100RB + L100RC + L151C6 + L151C8 + L151CB + L151CC + L151QC + L151QD + L151QE + L151R6 + L151R8 + L151RB + L151RC + L151RD + L151RE + L151UC + L151V8 + L151VB + L151VC + L151VD + L151VE + L151ZC + L151ZD + L151ZE + L152C6 + L152C8 + L152CB + L152CC + L152QC + L152QD + L152QE + L152R6 + L152R8 + L152RB + L152RC + L152RD + L152RE + L152UC + L152V8 + L152VB + L152VC + L152VD + L152VE + L152ZC + L152ZD + L152ZE + L162QC + L162QD + L162RC + L162RD + L162RE + L162VC + L162VD + L162VE + L162ZC + L162ZD + L162ZE +) + +list(APPEND STM32_SUPPORTED_FAMILIES_LONG_NAME + STM32L1 +) + +list(APPEND STM32_FETCH_FAMILIES L1) + +set(CUBE_L1_VERSION v1.10.3) +set(CMSIS_L1_VERSION v2.3.2) +set(HAL_L1_VERSION v1.4.4) diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/l4.cmake b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/l4.cmake index 64f70f7df8f..ecd5e0305a3 100644 --- a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/l4.cmake +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/l4.cmake @@ -38,3 +38,154 @@ target_compile_options(STM32::L4 INTERFACE target_link_options(STM32::L4 INTERFACE -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard ) + +list(APPEND STM32_ALL_DEVICES + L412C8 + L412CB + L412K8 + L412KB + L412R8 + L412RB + L412T8 + L412TB + L422CB + L422KB + L422RB + L422TB + L431CB + L431CC + L431KB + L431KC + L431RB + L431RC + L431VC + L432KB + L432KC + L433CB + L433CC + L433RB + L433RC + L433VC + L442KC + L443CC + L443RC + L443VC + L451CC + L451CE + L451RC + L451RE + L451VC + L451VE + L452CC + L452CE + L452RC + L452RE + L452VC + L452VE + L462CE + L462RE + L462VE + L471QE + L471QG + L471RE + L471RG + L471VE + L471VG + L471ZE + L471ZG + L475RC + L475RE + L475RG + L475VC + L475VE + L475VG + L476JE + L476JG + L476ME + L476MG + L476QE + L476QG + L476RC + L476RE + L476RG + L476VC + L476VE + L476VG + L476ZE + L476ZG + L486JG + L486QG + L486RG + L486VG + L486ZG + L496AE + L496AG + L496QE + L496QG + L496RE + L496RG + L496VE + L496VG + L496ZE + L496ZG + L4A6AG + L4A6QG + L4A6RG + L4A6VG + L4A6ZG + L4P5AE + L4P5AG + L4P5CE + L4P5CG + L4P5QE + L4P5QG + L4P5RE + L4P5RG + L4P5VE + L4P5VG + L4P5ZE + L4P5ZG + L4Q5AG + L4Q5CG + L4Q5QG + L4Q5RG + L4Q5VG + L4Q5ZG + L4R5AG + L4R5AI + L4R5QG + L4R5QI + L4R5VG + L4R5VI + L4R5ZG + L4R5ZI + L4R7AI + L4R7VI + L4R7ZI + L4R9AG + L4R9AI + L4R9VG + L4R9VI + L4R9ZG + L4R9ZI + L4S5AI + L4S5QI + L4S5VI + L4S5ZI + L4S7AI + L4S7VI + L4S7ZI + L4S9AI + L4S9VI + L4S9ZI +) + +list(APPEND STM32_SUPPORTED_FAMILIES_LONG_NAME + STM32L4 +) + +list(APPEND STM32_FETCH_FAMILIES L4) + +set(CUBE_L4_VERSION v1.17.0) +set(CMSIS_L4_VERSION v1.7.1) +set(HAL_L4_VERSION v1.13.0) diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/l5.cmake b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/l5.cmake index 7663b8b6bb2..d74025b07d1 100644 --- a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/l5.cmake +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/l5.cmake @@ -20,3 +20,33 @@ target_compile_options(STM32::L5 INTERFACE target_link_options(STM32::L5 INTERFACE -mcpu=cortex-m33 -mfpu=fpv5-sp-d16 -mfloat-abi=hard ) + +list(APPEND STM32_ALL_DEVICES + L552CC + L552CE + L552ME + L552QC + L552QE + L552RC + L552RE + L552VC + L552VE + L552ZC + L552ZE + L562CE + L562ME + L562QE + L562RE + L562VE + L562ZE +) + +list(APPEND STM32_SUPPORTED_FAMILIES_LONG_NAME + STM32L5 +) + +list(APPEND STM32_FETCH_FAMILIES L5) + +set(CUBE_L5_VERSION v1.4.0) +set(CMSIS_L5_VERSION v1.0.4) +set(HAL_L5_VERSION v1.0.4) diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/mp1.cmake b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/mp1.cmake index 4c8afd639f3..14a2f75e8a1 100644 --- a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/mp1.cmake +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/mp1.cmake @@ -29,3 +29,28 @@ function(stm32mp1_get_memory_info DEVICE TYPE FLASH_SIZE) set(${FLASH_SIZE} "0KB" PARENT_SCOPE) endif() endfunction() + +list(APPEND STM32_ALL_DEVICES + MP151A + MP151C + MP151D + MP151F + MP153A + MP153C + MP153D + MP153F + MP157A + MP157C + MP157D + MP157F +) + +list(APPEND STM32_SUPPORTED_FAMILIES_LONG_NAME + STM32MP1_M4 +) + +list(APPEND STM32_FETCH_FAMILIES MP1) + +set(CUBE_MP1_VERSION 1.5.0) +set(CMSIS_MP1_VERSION cube) +set(HAL_MP1_VERSION cube) diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/u0.cmake b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/u0.cmake new file mode 100644 index 00000000000..561f60fea1d --- /dev/null +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/u0.cmake @@ -0,0 +1,63 @@ +set(STM32_U0_TYPES + U031xx + U073xx + U083xx +) +set(STM32_U0_TYPE_MATCH + "U031.[468]" + "U073.C" + "U083.C" +) +set(STM32_U0_RAM_SIZES + 12K + 40K + 40K +) +set(STM32_U0_CCRAM_SIZES + 0K + 0K + 0K +) + +stm32_util_create_family_targets(U0) + +target_compile_options(STM32::U0 INTERFACE + -mcpu=cortex-m0plus +) +target_link_options(STM32::U0 INTERFACE + -mcpu=cortex-m0plus +) + +list(APPEND STM32_ALL_DEVICES + U031C6 + U031C8 + U031F4 + U031F6 + U031F8 + U031G6 + U031G8 + U031K4 + U031K8 + U031R6 + U031R8 + U073CC + U073HC + U073KC + U073MC + U073RC + U083CC + U083HC + U083KC + U083MC + U083RC +) + +list(APPEND STM32_SUPPORTED_FAMILIES_LONG_NAME + STM32U0 +) + +list(APPEND STM32_FETCH_FAMILIES U0) + +set(CUBE_U0_VERSION v1.0.0) +set(CMSIS_U0_VERSION v1.0.0) +set(HAL_U0_VERSION v1.0.0) diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/u5.cmake b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/u5.cmake index 4dcbd7bbb48..7199aea0c79 100644 --- a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/u5.cmake +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/u5.cmake @@ -17,3 +17,37 @@ target_compile_options(STM32::U5 INTERFACE target_link_options(STM32::U5 INTERFACE -mcpu=cortex-m33 -mfpu=fpv5-sp-d16 -mfloat-abi=hard ) + +list(APPEND STM32_ALL_DEVICES + U575CG + U575CI + U585CI + U575RG + U575RI + U585RI + U5750G + U5750I + U5850I + U575VG + U575VI + U585VI + U575QG + U575QI + U585QI + U575ZG + U575ZI + U585ZI + U575AG + U575AI + U585AI +) + +list(APPEND STM32_SUPPORTED_FAMILIES_LONG_NAME + STM32U5 +) + +list(APPEND STM32_FETCH_FAMILIES U5) + +set(CUBE_U5_VERSION v1.4.0) +set(CMSIS_U5_VERSION v1.3.1) +set(HAL_U5_VERSION v1.4.0) diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/utilities.cmake b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/utilities.cmake deleted file mode 100644 index 8ede1e7077b..00000000000 --- a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/utilities.cmake +++ /dev/null @@ -1,160 +0,0 @@ -function(stm32_util_create_family_targets FAMILY) - set(CORES ${ARGN}) - list(LENGTH CORES NUM_CORES) - if(${NUM_CORES} EQUAL 0) - set(CORE "") - set(CORE_C "") - elseif(${NUM_CORES} EQUAL 1) - set(CORE "_${CORES}") - set(CORE_C "::${CORES}") - else() - message(FATAL_ERROR "Expected at most one core for family ${FAMILY}: ${CORES}") - endif() - - if(NOT (TARGET STM32::${FAMILY}${CORE_C})) - add_library(STM32::${FAMILY}${CORE_C} INTERFACE IMPORTED) - # Set compiler flags for target - # -Wall: all warnings activated - # -ffunction-sections -fdata-sections: remove unused code - target_compile_options(STM32::${FAMILY}${CORE_C} INTERFACE - -mthumb -Wall -ffunction-sections -fdata-sections - ) - # Set linker flags - # -mthumb: Generate thumb code - # -Wl,--gc-sections: Remove unused code - target_link_options(STM32::${FAMILY}${CORE_C} INTERFACE - -mthumb -Wl,--gc-sections - ) - target_compile_definitions(STM32::${FAMILY}${CORE_C} INTERFACE - STM32${FAMILY} - ) - endif() - foreach(TYPE ${STM32_${FAMILY}_TYPES}) - if(NOT (TARGET STM32::${TYPE}${CORE_C})) - add_library(STM32::${TYPE}${CORE_C} INTERFACE IMPORTED) - target_link_libraries(STM32::${TYPE}${CORE_C} INTERFACE STM32::${FAMILY}${CORE_C}) - target_compile_definitions(STM32::${TYPE}${CORE_C} INTERFACE - STM32${TYPE} - ) - endif() - endforeach() -endfunction() - -include(FetchContent) - -# A CMSIS or HAL driver can specify 'cube' as version number to indicate that the driver is taken from the Cube repository -set(STM32_FETCH_FAMILIES C0 F0 F1 F2 F3 F4 F7 G0 G4 H7 L0 L1 L4 L5 MP1 U5 WB WL ) -set(STM32_FETCH_CUBE_VERSIONS v1.1.0 v1.11.2 v1.8.4 v1.9.3 v1.11.2 v1.26.1 v1.16.1 v1.4.1 v1.4.0 v1.9.0 v1.12.0 v1.10.3 v1.17.0 v1.4.0 1.5.0 v1.3.0 v1.12.0 v1.1.0) -set(STM32_FETCH_CMSIS_VERSIONS v1.1.0 v2.3.5 v4.3.3 v2.2.5 v2.3.5 v2.6.6 v1.2.6 v1.4.0 v1.2.1 v1.10.0 v1.9.1 v2.3.2 v1.7.1 v1.0.4 cube v1.3.0 v1.9.0 v1.1.0) -set(STM32_FETCH_HAL_VERSIONS v1.1.0 v1.7.5 v1.1.8 v1.2.7 v1.5.5 v1.7.12 v1.2.9 v1.4.1 v1.2.1 v1.10.0 v1.10.4 v1.4.4 v1.13.0 v1.0.4 cube v1.3.0 v1.9.0 v1.1.0) - - -FetchContent_Declare( - STM32-CMSIS - GIT_REPOSITORY https://github.com/STMicroelectronics/cmsis_core/ - GIT_TAG v5.6.0 - GIT_PROGRESS TRUE -) - -set(IDX 0) -foreach(FAMILY ${STM32_FETCH_FAMILIES}) - string(TOLOWER ${FAMILY} FAMILY_L) - list(GET STM32_FETCH_CUBE_VERSIONS ${IDX} CUBE_VERSION) - list(GET STM32_FETCH_CMSIS_VERSIONS ${IDX} CMSIS_VERSION) - list(GET STM32_FETCH_HAL_VERSIONS ${IDX} HAL_VERSION) - - FetchContent_Declare( - STM32Cube${FAMILY} - GIT_REPOSITORY https://github.com/STMicroelectronics/STM32Cube${FAMILY}/ - GIT_TAG ${CUBE_VERSION} - GIT_PROGRESS TRUE - ) - - if(CMSIS_VERSION STREQUAL cube) - set(STM32_USE_CMSIS_FROM_CUBE_${FAMILY} ON) - else() - FetchContent_Declare( - STM32-CMSIS-${FAMILY} - GIT_REPOSITORY https://github.com/STMicroelectronics/cmsis_device_${FAMILY_L}/ - GIT_TAG ${CMSIS_VERSION} - GIT_PROGRESS TRUE - ) - endif() - - if(HAL_VERSION STREQUAL cube) - set(STM32_USE_HAL_FROM_CUBE_${FAMILY} ON) - else() - FetchContent_Declare( - STM32-HAL-${FAMILY} - GIT_REPOSITORY https://github.com/STMicroelectronics/stm32${FAMILY_L}xx_hal_driver/ - GIT_TAG ${HAL_VERSION} - GIT_PROGRESS TRUE - ) - endif() - - math(EXPR IDX "${IDX} + 1") -endforeach() - -function(stm32_fetch_cube) - foreach(FAMILY ${ARGV}) - set(CUBE_NAME STM32Cube${FAMILY}) - string(TOLOWER ${CUBE_NAME} CUBE_NAME_L) - - if(STM32_CUBE_${FAMILY}_PATH) - message(VERBOSE "STM32_CUBE_${FAMILY}_PATH specified, skipping fetch for ${CUBE_NAME}") - continue() - endif() - - FetchContent_MakeAvailable(${CUBE_NAME}) - set(STM32_CUBE_${FAMILY}_PATH ${${CUBE_NAME_L}_SOURCE_DIR} PARENT_SCOPE) - endforeach() -endfunction() - -function(stm32_fetch_cmsis) - if(NOT STM32_CMSIS_PATH) - FetchContent_MakeAvailable(STM32-CMSIS) - set(STM32_CMSIS_PATH ${stm32-cmsis_SOURCE_DIR} PARENT_SCOPE) - else() - message(INFO "STM32_CMSIS_PATH specified, skipping fetch for STM32-CMSIS") - endif() - - foreach(FAMILY ${ARGV}) - if(STM32_USE_CMSIS_FROM_CUBE_${FAMILY}) - stm32_fetch_cube(${FAMILY}) - message(STATUS "Cube fetched for ${FAMILY} at ${STM32_CUBE_${FAMILY}_PATH}") - set(STM32_CMSIS_${FAMILY}_PATH ${STM32_CUBE_${FAMILY}_PATH}/Drivers/CMSIS/Device/ST/STM32${FAMILY}xx PARENT_SCOPE) - else() - set(CMSIS_NAME STM32-CMSIS-${FAMILY}) - string(TOLOWER ${CMSIS_NAME} CMSIS_NAME_L) - - if(STM32_CMSIS_${FAMILY}_PATH) - message(INFO "STM32_CMSIS_${FAMILY}_PATH specified, skipping fetch for ${CMSIS_NAME}") - continue() - endif() - - FetchContent_MakeAvailable(${CMSIS_NAME}) - set(STM32_CMSIS_${FAMILY}_PATH ${${CMSIS_NAME_L}_SOURCE_DIR} PARENT_SCOPE) - endif() - endforeach() -endfunction() - -function(stm32_fetch_hal) - foreach(FAMILY ${ARGV}) - if(STM32_USE_HAL_FROM_CUBE_${FAMILY}) - stm32_fetch_cube(${FAMILY}) - message(STATUS "Cube fetched for ${FAMILY} at ${STM32_CUBE_${FAMILY}_PATH}") - set(STM32_HAL_${FAMILY}_PATH ${STM32_CUBE_${FAMILY}_PATH}/Drivers/STM32${FAMILY}xx_HAL_Driver PARENT_SCOPE) - else() - set(HAL_NAME STM32-HAL-${FAMILY}) - string(TOLOWER ${HAL_NAME} HAL_NAME_L) - - if(STM32_HAL_${FAMILY}_PATH) - message(INFO "STM32_HAL_${FAMILY}_PATH specified, skipping fetch for ${HAL_NAME}") - continue() - endif() - - FetchContent_MakeAvailable(${HAL_NAME}) - set(STM32_HAL_${FAMILY}_PATH ${${HAL_NAME_L}_SOURCE_DIR} PARENT_SCOPE) - endif() - endforeach() -endfunction() diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/wb.cmake b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/wb.cmake index 77dfbec6d61..1e88432de4f 100644 --- a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/wb.cmake +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/wb.cmake @@ -36,3 +36,32 @@ function(stm32wb_get_memory_info DEVICE TYPE CORE RAM RAM_ORIGIN TWO_FLASH_BANKS set(${RAM_ORIGIN} 0x20000004 PARENT_SCOPE) endfunction() +list(APPEND STM32_ALL_DEVICES + WB5MMG + WB50CG + WB30CE + WB10CC + WB55CC + WB55CE + WB55CG + WB55RC + WB55RE + WB55RG + WB55VC + WB55VE + WB55VG + WB55VY + WB15CC + WB35CC + WB35CE +) + +list(APPEND STM32_SUPPORTED_FAMILIES_LONG_NAME + STM32WB_M4 +) + +list(APPEND STM32_FETCH_FAMILIES WB) + +set(CUBE_WB_VERSION v1.12.0) +set(CMSIS_WB_VERSION v1.9.0) +set(HAL_WB_VERSION v1.9.0) diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/wl.cmake b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/wl.cmake index eb54897e269..9649a60afae 100644 --- a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/wl.cmake +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/cmake/stm32/wl.cmake @@ -66,12 +66,40 @@ function(stm32wl_get_memory_info DEVICE TYPE CORE RAM FLASH_ORIGIN RAM_ORIGIN TW endif() endfunction() - - function(stm32wl_get_device_cores DEVICE TYPE CORES) if(${TYPE} IN_LIST STM32_WL_DUAL_CORE) set(${CORES} M4 M0PLUS PARENT_SCOPE) else() set(${CORES} M4 PARENT_SCOPE) endif() -endfunction() \ No newline at end of file +endfunction() + +list(APPEND STM32_ALL_DEVICES + WL55CC + WL54CC + WL55JC + WL54JC + WLE5J8 + WLE5JB + WLE5JC + WLE5C8 + WLE5CB + WLE5CC + WLE4J8 + WLE4JB + WLE4JC + WLE4C8 + WLE4CB + WLE4CC +) + +list(APPEND STM32_SUPPORTED_FAMILIES_LONG_NAME + STM32WL_M0PLUS + STM32WL_M4 +) + +list(APPEND STM32_FETCH_FAMILIES WL) + +set(CUBE_WL_VERSION v1.1.0) +set(CMSIS_WL_VERSION v1.1.0) +set(HAL_WL_VERSION v1.1.0) diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/docs/MAINTAIN.md b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/docs/MAINTAIN.md new file mode 100644 index 00000000000..67926b51c7b --- /dev/null +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/docs/MAINTAIN.md @@ -0,0 +1,27 @@ +# Supporting new families + +## Write device file + +a file .cmake must be added to the folder cmake/stm32 +This file containes the differents devices and the regex used to parse them. +It also give information on the RAM and CCRAM available + +## Add family to list of know families + +Update the list `STM32_SUPPORTED_FAMILIES_LONG_NAME` located in the cmake/stm32/common.cmake file + +## Add devices to list of devices in devices.cmake + +Add all known devices to the list of all devices + +## Update cube, cmsis and hal version in utilities.cmake + +The versions to use can be found as follow: + - Cube version : a valid tag from the repo https://github.com/STMicroelectronics/STM32Cube${FAMILY} + - Cmsis version : a valid tag from the repo https://github.com/STMicroelectronics/cmsis_device_${FAMILY_L} + - Hal version : a valid tag from the repo https://github.com/STMicroelectronics/stm32${FAMILY_L}xx_hal_driver + +## Add family to CI + +Add the file stm32${FAMILY_L}xx_hal_conf.h file to the root folder of each test. (A template is provided in the corresponding HAL) +Update the cmake.yml workflow file to include the new family diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/bsp/CMakeLists.txt b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/bsp/CMakeLists.txt index 83cdf930145..37db1aa0162 100644 --- a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/bsp/CMakeLists.txt +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/bsp/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/stm32_gcc.cmake) if(NOT TEST_FAMILIES) - set(TEST_FAMILIES C0 F0 F1 F2 F3 F4 F7 G0 G4 H7 L0 L1 L4 L5 MP1 U5 WB WL) + set(TEST_FAMILIES C0 F0 F1 F2 F3 F4 F7 G0 G4 H7 L0 L1 L4 L5 MP1 U0 U5 WB WL) endif() # Nucleo boards can have different devices on it @@ -28,6 +28,8 @@ set(DEVICE_STM32L4xx_Nucleo_32 L412KB) set(DEVICE_STM32L4xx_Nucleo_144 L496ZG) set(DEVICE_STM32MP15xx_DISCO MP157CAC) set(DEVICE_STM32MP15xx_EVAL MP157FAA) +set(DEVICE_STM32U0xx_Nucleo U031R8) +set(DEVICE_STM32U0xx_DISCO U083CC) set(DEFINES_STM32469I_EVAL USE_IOEXPANDER) set(DEFINES_STM32F769I_EVAL USE_IOEXPANDER) set(DEFINES_STM32L476G_EVAL USE_IOEXPANDER) diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/bsp/stm32h5xx_hal_conf.h b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/bsp/stm32h5xx_hal_conf.h new file mode 100644 index 00000000000..c453c736eee --- /dev/null +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/bsp/stm32h5xx_hal_conf.h @@ -0,0 +1,488 @@ +/** + ********************************************************************************************************************** + * @file stm32h5xx_hal_conf_template.h + * @author MCD Application Team + * @brief HAL configuration template file. + * This file should be copied to the application folder and renamed + * to stm32h5xx_hal_conf.h. + ********************************************************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ********************************************************************************************************************** + */ + +/* Define to prevent recursive inclusion -----------------------------------------------------------------------------*/ +#ifndef STM32H5xx_HAL_CONF_H +#define STM32H5xx_HAL_CONF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Exported types ----------------------------------------------------------------------------------------------------*/ +/* Exported constants ------------------------------------------------------------------------------------------------*/ + +/* ########################################### Module Selection ##################################################### */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ +#define HAL_MODULE_ENABLED +#define HAL_ADC_MODULE_ENABLED +#define HAL_CEC_MODULE_ENABLED +#define HAL_COMP_MODULE_ENABLED +#define HAL_CORDIC_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED +#define HAL_CRC_MODULE_ENABLED +#define HAL_CRYP_MODULE_ENABLED +#define HAL_DAC_MODULE_ENABLED +#define HAL_DCACHE_MODULE_ENABLED +#define HAL_DCMI_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_DTS_MODULE_ENABLED +#define HAL_EXTI_MODULE_ENABLED +#define HAL_ETH_MODULE_ENABLED +#define HAL_FDCAN_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_FMAC_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_GTZC_MODULE_ENABLED +#define HAL_HASH_MODULE_ENABLED +#define HAL_HCD_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +#define HAL_I2S_MODULE_ENABLED +#define HAL_I3C_MODULE_ENABLED +#define HAL_ICACHE_MODULE_ENABLED +#define HAL_IRDA_MODULE_ENABLED +#define HAL_IWDG_MODULE_ENABLED +#define HAL_LPTIM_MODULE_ENABLED +#define HAL_MMC_MODULE_ENABLED +#define HAL_NAND_MODULE_ENABLED +#define HAL_NOR_MODULE_ENABLED +#define HAL_OTFDEC_MODULE_ENABLED +#define HAL_OPAMP_MODULE_ENABLED +#define HAL_PCD_MODULE_ENABLED +#define HAL_PKA_MODULE_ENABLED +#define HAL_PSSI_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_RAMCFG_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_RNG_MODULE_ENABLED +#define HAL_RTC_MODULE_ENABLED +#define HAL_SAI_MODULE_ENABLED +#define HAL_SD_MODULE_ENABLED +#define HAL_SDRAM_MODULE_ENABLED +#define HAL_SMARTCARD_MODULE_ENABLED +#define HAL_SMBUS_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +#define HAL_SRAM_MODULE_ENABLED +#define HAL_TIM_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED +#define HAL_USART_MODULE_ENABLED +#define HAL_WWDG_MODULE_ENABLED +#define HAL_XSPI_MODULE_ENABLED + +/* ####################################### Oscillator Values adaptation ##############################################*/ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) +#define HSE_VALUE 25000000UL /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) +#define HSE_STARTUP_TIMEOUT 100UL /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal Core Speed oscillator (CSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when CSI is used as system clock source, directly or through the PLL). + */ +#if !defined (CSI_VALUE) +#define CSI_VALUE 4000000UL /*!< Value of the Internal oscillator in Hz*/ +#endif /* CSI_VALUE */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) +#define HSI_VALUE 64000000UL /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal High Speed oscillator (HSI48) value for USB FS, SDMMC and RNG. + * This internal oscillator is mainly dedicated to provide a high precision clock to + * the USB peripheral by means of a special Clock Recovery System (CRS) circuitry. + * When the CRS is not used, the HSI48 RC oscillator runs on it default frequency + * which is subject to manufacturing process variations. + */ +#if !defined (HSI48_VALUE) +#define HSI48_VALUE 48000000UL /*!< Value of the Internal High Speed oscillator for USB FS/SDMMC/RNG in Hz. + The real value my vary depending on manufacturing process variations.*/ +#endif /* HSI48_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) +#define LSI_VALUE 32000UL /*!< LSI Typical Value in Hz*/ +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz +The real value may vary depending on the variations +in voltage and temperature.*/ + +#if !defined (LSI_STARTUP_TIME) +#define LSI_STARTUP_TIME 130UL /*!< Time out for LSI start up, in ms */ +#endif /* LSI_STARTUP_TIME */ + +/** + * @brief External Low Speed oscillator (LSE) value. + * This value is used by the UART, RTC HAL module to compute the system frequency + */ +#if !defined (LSE_VALUE) +#define LSE_VALUE 32768UL /*!< Value of the External oscillator in Hz*/ +#endif /* LSE_VALUE */ + +#if !defined (LSE_STARTUP_TIMEOUT) +#define LSE_STARTUP_TIMEOUT 5000UL /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + + +/** + * @brief External clock source for SPI/SAI peripheral + * This value is used by the SPI/SAI HAL module to compute the SPI/SAI clock source + * frequency, this source is inserted directly through I2S_CKIN pad. + */ +#if !defined (EXTERNAL_CLOCK_VALUE) +#define EXTERNAL_CLOCK_VALUE 12288000UL /*!< Value of the External clock in Hz*/ +#endif /* EXTERNAL_CLOCK_VALUE */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ############################################ System Configuration ################################################ */ +/** + * @brief This is the HAL system configuration section + */ +#define VDD_VALUE 3300UL /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY ((1UL<<__NVIC_PRIO_BITS) - 1UL) /*!< tick interrupt priority (lowest by default) */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 0U /*!< Enable prefetch */ + +/* ############################################ Assert Selection #################################################### */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1U */ + +/* ############################################ Register callback feature configuration ############################# */ +/** + * @brief Set below the peripheral configuration to "1U" to add the support + * of HAL callback registration/unregistration feature for the HAL + * driver(s). This allows user application to provide specific callback + * functions thanks to HAL_PPP_RegisterCallback() rather than overwriting + * the default weak callback functions (see each stm32h5xx_hal_ppp.h file + * for possible callback identifiers defined in HAL_PPP_CallbackIDTypeDef + * for each PPP peripheral). + */ +#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */ +#define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */ +#define USE_HAL_COMP_REGISTER_CALLBACKS 0U /* COMP register callback disabled */ +#define USE_HAL_CORDIC_REGISTER_CALLBACKS 0U /* CORDIC register callback disabled */ +#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */ +#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */ +#define USE_HAL_DCMI_REGISTER_CALLBACKS 0U /* DCMI register callback disabled */ +#define USE_HAL_DTS_REGISTER_CALLBACKS 0U /* DTS register callback disabled */ +#define USE_HAL_ETH_REGISTER_CALLBACKS 0U /* ETH register callback disabled */ +#define USE_HAL_FDCAN_REGISTER_CALLBACKS 0U /* FDCAN register callback disabled */ +#define USE_HAL_FMAC_REGISTER_CALLBACKS 0U /* FMAC register callback disabled */ +#define USE_HAL_NOR_REGISTER_CALLBACKS 0U /* NOR register callback disabled */ +#define USE_HAL_HASH_REGISTER_CALLBACKS 0U /* HASH register callback disabled */ +#define USE_HAL_HCD_REGISTER_CALLBACKS 0U /* HCD register callback disabled */ +#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */ +#define USE_HAL_I2S_REGISTER_CALLBACKS 0U /* I2S register callback disabled */ +#define USE_HAL_I3C_REGISTER_CALLBACKS 0U /* I3C register callback disabled */ +#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U /* IRDA register callback disabled */ +#define USE_HAL_IWDG_REGISTER_CALLBACKS 0U /* IWDG register callback disabled */ +#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */ +#define USE_HAL_MMC_REGISTER_CALLBACKS 0U /* MMC register callback disabled */ +#define USE_HAL_NAND_REGISTER_CALLBACKS 0U /* NAND register callback disabled */ +#define USE_HAL_OPAMP_REGISTER_CALLBACKS 0U /* OTFDEC register callback disabled */ +#define USE_HAL_OTFDEC_REGISTER_CALLBACKS 0U /* OPAMP register callback disabled */ +#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */ +#define USE_HAL_PKA_REGISTER_CALLBACKS 0U /* PKA register callback disabled */ +#define USE_HAL_RAMCFG_REGISTER_CALLBACKS 0U /* RAMCFG register callback disabled */ +#define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */ +#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */ +#define USE_HAL_SAI_REGISTER_CALLBACKS 0U /* SAI register callback disabled */ +#define USE_HAL_SD_REGISTER_CALLBACKS 0U /* SD register callback disabled */ +#define USE_HAL_SDRAM_REGISTER_CALLBACKS 0U /* SDRAM register callback disabled */ +#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U /* SMARTCARD register callback disabled */ +#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U /* SMBUS register callback disabled */ +#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */ +#define USE_HAL_SRAM_REGISTER_CALLBACKS 0U /* SRAM register callback disabled */ +#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */ +#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */ +#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */ +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */ +#define USE_HAL_XSPI_REGISTER_CALLBACKS 0U /* XSPI register callback disabled */ + +/* ############################################ SPI peripheral configuration ######################################## */ + +/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver + * Activated: CRC code is present inside driver + * Deactivated: CRC code cleaned from driver + */ +#define USE_SPI_CRC 1U + + +/* Includes ----------------------------------------------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED +#include "stm32h5xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED +#include "stm32h5xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_ICACHE_MODULE_ENABLED +#include "stm32h5xx_hal_icache.h" +#endif /* HAL_ICACHE_MODULE_ENABLED */ + +#ifdef HAL_DCACHE_MODULE_ENABLED +#include "stm32h5xx_hal_dcache.h" +#endif /* HAL_DCACHE_MODULE_ENABLED */ + +#ifdef HAL_GTZC_MODULE_ENABLED +#include "stm32h5xx_hal_gtzc.h" +#endif /* HAL_GTZC_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED +#include "stm32h5xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_DTS_MODULE_ENABLED +#include "stm32h5xx_hal_dts.h" +#endif /* HAL_DTS_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED +#include "stm32h5xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_PKA_MODULE_ENABLED +#include "stm32h5xx_hal_pka.h" +#endif /* HAL_PKA_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED +#include "stm32h5xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED +#include "stm32h5xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED +#include "stm32h5xx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED +#include "stm32h5xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED +#include "stm32h5xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_HASH_MODULE_ENABLED +#include "stm32h5xx_hal_hash.h" +#endif /* HAL_HASH_MODULE_ENABLED */ + +#ifdef HAL_SRAM_MODULE_ENABLED +#include "stm32h5xx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + +#ifdef HAL_SDRAM_MODULE_ENABLED +#include "stm32h5xx_hal_sdram.h" +#endif /* HAL_SDRAM_MODULE_ENABLED */ + +#ifdef HAL_MMC_MODULE_ENABLED +#include "stm32h5xx_hal_mmc.h" +#endif /* HAL_MMC_MODULE_ENABLED */ + +#ifdef HAL_NOR_MODULE_ENABLED +#include "stm32h5xx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ + +#ifdef HAL_NAND_MODULE_ENABLED +#include "stm32h5xx_hal_nand.h" +#endif /* HAL_NAND_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED +#include "stm32h5xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_I2S_MODULE_ENABLED +#include "stm32h5xx_hal_i2s.h" +#endif /* HAL_I2S_MODULE_ENABLED */ + +#ifdef HAL_I3C_MODULE_ENABLED +#include "stm32h5xx_hal_i3c.h" +#endif /* HAL_I3C_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED +#include "stm32h5xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_LPTIM_MODULE_ENABLED +#include "stm32h5xx_hal_lptim.h" +#endif /* HAL_LPTIM_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED +#include "stm32h5xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_XSPI_MODULE_ENABLED +#include "stm32h5xx_hal_xspi.h" +#endif /* HAL_XSPI_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED +#include "stm32h5xx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED +#include "stm32h5xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SAI_MODULE_ENABLED +#include "stm32h5xx_hal_sai.h" +#endif /* HAL_SAI_MODULE_ENABLED */ + +#ifdef HAL_SD_MODULE_ENABLED +#include "stm32h5xx_hal_sd.h" +#endif /* HAL_SD_MODULE_ENABLED */ + +#ifdef HAL_SMBUS_MODULE_ENABLED +#include "stm32h5xx_hal_smbus.h" +#endif /* HAL_SMBUS_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED +#include "stm32h5xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED +#include "stm32h5xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED +#include "stm32h5xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED +#include "stm32h5xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED +#include "stm32h5xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED +#include "stm32h5xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED +#include "stm32h5xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED +#include "stm32h5xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_HCD_MODULE_ENABLED +#include "stm32h5xx_hal_hcd.h" +#endif /* HAL_HCD_MODULE_ENABLED */ + +#ifdef HAL_COMP_MODULE_ENABLED +#include "stm32h5xx_hal_comp.h" +#endif /* HAL_COMP_MODULE_ENABLED */ + +#ifdef HAL_CORDIC_MODULE_ENABLED +#include "stm32h5xx_hal_cordic.h" +#endif /* HAL_CORDIC_MODULE_ENABLED */ + +#ifdef HAL_DCMI_MODULE_ENABLED +#include "stm32h5xx_hal_dcmi.h" +#endif /* HAL_DCMI_MODULE_ENABLED */ + +#ifdef HAL_EXTI_MODULE_ENABLED +#include "stm32h5xx_hal_exti.h" +#endif /* HAL_EXTI_MODULE_ENABLED */ + +#ifdef HAL_ETH_MODULE_ENABLED +#include "stm32h5xx_hal_eth.h" +#endif /* HAL_ETH_MODULE_ENABLED */ + +#ifdef HAL_FDCAN_MODULE_ENABLED +#include "stm32h5xx_hal_fdcan.h" +#endif /* HAL_FDCAN_MODULE_ENABLED */ + +#ifdef HAL_CEC_MODULE_ENABLED +#include "stm32h5xx_hal_cec.h" +#endif /* HAL_CEC_MODULE_ENABLED */ + +#ifdef HAL_FMAC_MODULE_ENABLED +#include "stm32h5xx_hal_fmac.h" +#endif /* HAL_FMAC_MODULE_ENABLED */ + +#ifdef HAL_OPAMP_MODULE_ENABLED +#include "stm32h5xx_hal_opamp.h" +#endif /* HAL_OPAMP_MODULE_ENABLED */ + +#ifdef HAL_OTFDEC_MODULE_ENABLED +#include "stm32h5xx_hal_otfdec.h" +#endif /* HAL_OTFDEC_MODULE_ENABLED */ + +#ifdef HAL_PSSI_MODULE_ENABLED +#include "stm32h5xx_hal_pssi.h" +#endif /* HAL_PSSI_MODULE_ENABLED */ + +#ifdef HAL_RAMCFG_MODULE_ENABLED +#include "stm32h5xx_hal_ramcfg.h" +#endif /* HAL_RAMCFG_MODULE_ENABLED */ + +/* Exported macro ----------------------------------------------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ +#define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ----------------------------------------------------------------------------------------------- */ +void assert_failed(uint8_t *file, uint32_t line); +#else +#define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32H5xx_HAL_CONF_H */ diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/bsp/stm32u0xx_hal_conf.h b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/bsp/stm32u0xx_hal_conf.h new file mode 100644 index 00000000000..e402e06798a --- /dev/null +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/bsp/stm32u0xx_hal_conf.h @@ -0,0 +1,335 @@ +/** + ****************************************************************************** + * @file stm32u0xx_hal_conf.h + * @author MCD Application Team + * @brief HAL configuration file. + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32U0xx_HAL_CONF_H +#define __STM32U0xx_HAL_CONF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ + +#define HAL_MODULE_ENABLED +#define HAL_ADC_MODULE_ENABLED +#define HAL_COMP_MODULE_ENABLED +#define HAL_CRC_MODULE_ENABLED +#define HAL_CRS_MODULE_ENABLED +#define HAL_CRYP_MODULE_ENABLED +#define HAL_DAC_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +#define HAL_IRDA_MODULE_ENABLED +#define HAL_IWDG_MODULE_ENABLED +#define HAL_LCD_MODULE_ENABLED +#define HAL_LPTIM_MODULE_ENABLED +#define HAL_OPAMP_MODULE_ENABLED +#define HAL_PCD_MODULE_ENABLED +#define HAL_RNG_MODULE_ENABLED +#define HAL_RTC_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +#define HAL_SMARTCARD_MODULE_ENABLED +#define HAL_TIM_MODULE_ENABLED +#define HAL_TSC_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED +#define HAL_USART_MODULE_ENABLED +#define HAL_WWDG_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_EXTI_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED + +/* ########################## Oscillator Values adaptation ####################*/ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) + #define HSE_VALUE 4000000U /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) + #define HSE_STARTUP_TIMEOUT 100U /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal Multiple Speed oscillator (MSI) default value. + * This value is the default MSI range value after Reset. + */ +#if !defined (MSI_VALUE) + #define MSI_VALUE 4000000U /*!< Value of the Internal oscillator in Hz*/ +#endif /* MSI_VALUE */ + +/** + * @brief Internal Multiple Speed oscillator (MSI) default value. + * This value is the default MSI range value after Reset. + */ +#if !defined (MSI32_VALUE) +#define MSI32_VALUE 32000000U /*!< Value of the Internal oscillator in Hz*/ +#endif /* MSI32_VALUE */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) + #define HSI_VALUE 16000000U /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal High Speed oscillator (HSI48) value for USB FS and RNG. + * This internal oscillator is mainly dedicated to provide a high precision clock to + * the USB peripheral by means of a special Clock Recovery System (CRS) circuitry. + * When the CRS is not used, the HSI48 RC oscillator runs on it default frequency + * which is subject to manufacturing process variations. + */ +#if !defined (HSI48_VALUE) + #define HSI48_VALUE 48000000U /*!< Value of the Internal High Speed oscillator for USB FS/RNG in Hz. + The real value my vary depending on manufacturing process variations.*/ +#endif /* HSI48_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) + #define LSI_VALUE 32000U /*!< LSI Typical Value in Hz*/ +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz + The real value may vary depending on the variations + in voltage and temperature.*/ +/** + * @brief External Low Speed oscillator (LSE) value. + * This value is used by the UART, RTC HAL module to compute the system frequency + */ +#if !defined (LSE_VALUE) + #define LSE_VALUE 32768U /*!< Value of the External oscillator in Hz*/ +#endif /* LSE_VALUE */ + +#if !defined (LSE_STARTUP_TIMEOUT) + #define LSE_STARTUP_TIMEOUT 5000U /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ + +#define VDD_VALUE 3300U /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY (3U) /*!< tick interrupt priority (lowest by default) */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 0U +#define INSTRUCTION_CACHE_ENABLE 1U + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ + +/* #define USE_FULL_ASSERT 1U */ + +/* ################## Register callback feature configuration ############### */ +/** + * @brief Set below the peripheral configuration to "1U" to add the support + * of HAL callback registration/unregistration feature for the HAL + * driver(s). This allows user application to provide specific callback + * functions thanks to HAL_PPP_RegisterCallback() rather than overwriting + * the default weak callback functions (see each stm32n6xx_hal_ppp.h file + * for possible callback identifiers defined in HAL_PPP_CallbackIDTypeDef + * for each PPP peripheral). + */ +#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */ +#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */ +#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */ +#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */ +#define USE_HAL_IWDG_REGISTER_CALLBACKS 0U /* IWDG register callback disabled */ +#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U /* IRDA register callback disabled */ +#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */ +#define USE_HAL_LCD_REGISTER_CALLBACKS 0U /* LCD register callback disabled */ +#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */ +#define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */ +#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */ +#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U /* SMARTCARD register callback disabled */ +#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */ +#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */ +#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */ +#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */ +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */ + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED +#include "stm32u0xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED +#include "stm32u0xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED +#include "stm32u0xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED +#include "stm32u0xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED +#include "stm32u0xx_hal_adc.h" +#include "stm32u0xx_hal_adc_ex.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_COMP_MODULE_ENABLED +#include "stm32u0xx_hal_comp.h" +#endif /* HAL_COMP_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED +#include "stm32u0xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRS_MODULE_ENABLED +#include "stm32u0xx_ll_crs.h" +#endif /* HAL_CRS_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED +#include "stm32u0xx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED +#include "stm32u0xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_EXTI_MODULE_ENABLED +#include "stm32u0xx_hal_exti.h" +#endif /* HAL_EXTI_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED +#include "stm32u0xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED +#include "stm32u0xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED +#include "stm32u0xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_LPTIM_MODULE_ENABLED +#include "stm32u0xx_hal_lptim.h" +#endif /* HAL_LPTIM_MODULE_ENABLED */ + +#ifdef HAL_LCD_MODULE_ENABLED +#include "stm32u0xx_hal_lcd.h" +#endif /* HAL_LTDC_MODULE_ENABLED */ + +#ifdef HAL_OPAMP_MODULE_ENABLED +#include "stm32u0xx_hal_opamp.h" +#endif /* HAL_OPAMP_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED +#include "stm32u0xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED +#include "stm32u0xx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED +#include "stm32u0xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED +#include "stm32u0xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED +#include "stm32u0xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_TSC_MODULE_ENABLED +#include "stm32u0xx_ll_system.h" +#include "stm32u0xx_hal_tsc.h" +#endif /* HAL_TSC_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED +#include "stm32u0xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED +#include "stm32u0xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED +#include "stm32u0xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED +#include "stm32u0xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED +#include "stm32u0xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_LCD_MODULE_ENABLED +#include "stm32u0xx_hal_lcd.h" +#endif /* HAL_LCD_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED +#include "stm32u0xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ + #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ + void assert_failed(uint8_t *file, uint32_t line); +#else + #define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32U0xx_HAL_CONF_H */ diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/cmsis/CMakeLists.txt b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/cmsis/CMakeLists.txt index 7c52a0af445..4e4f94e3147 100644 --- a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/cmsis/CMakeLists.txt +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/cmsis/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/stm32_gcc.cmake) if(NOT TEST_FAMILIES) - set(TEST_FAMILIES C0 F0 F1 F2 F3 F4 F7 G0 G4 H7 L0 L1 L4 L5 U5 WB WL) + set(TEST_FAMILIES C0 F0 F1 F2 F3 F4 F7 G0 G4 H7 L0 L1 L4 L5 U0 U5 WB WL) endif() if("MP1" IN_LIST TEST_FAMILIES) diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/cmsis/stm32h5xx_hal_conf.h b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/cmsis/stm32h5xx_hal_conf.h new file mode 100644 index 00000000000..c453c736eee --- /dev/null +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/cmsis/stm32h5xx_hal_conf.h @@ -0,0 +1,488 @@ +/** + ********************************************************************************************************************** + * @file stm32h5xx_hal_conf_template.h + * @author MCD Application Team + * @brief HAL configuration template file. + * This file should be copied to the application folder and renamed + * to stm32h5xx_hal_conf.h. + ********************************************************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ********************************************************************************************************************** + */ + +/* Define to prevent recursive inclusion -----------------------------------------------------------------------------*/ +#ifndef STM32H5xx_HAL_CONF_H +#define STM32H5xx_HAL_CONF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Exported types ----------------------------------------------------------------------------------------------------*/ +/* Exported constants ------------------------------------------------------------------------------------------------*/ + +/* ########################################### Module Selection ##################################################### */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ +#define HAL_MODULE_ENABLED +#define HAL_ADC_MODULE_ENABLED +#define HAL_CEC_MODULE_ENABLED +#define HAL_COMP_MODULE_ENABLED +#define HAL_CORDIC_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED +#define HAL_CRC_MODULE_ENABLED +#define HAL_CRYP_MODULE_ENABLED +#define HAL_DAC_MODULE_ENABLED +#define HAL_DCACHE_MODULE_ENABLED +#define HAL_DCMI_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_DTS_MODULE_ENABLED +#define HAL_EXTI_MODULE_ENABLED +#define HAL_ETH_MODULE_ENABLED +#define HAL_FDCAN_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_FMAC_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_GTZC_MODULE_ENABLED +#define HAL_HASH_MODULE_ENABLED +#define HAL_HCD_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +#define HAL_I2S_MODULE_ENABLED +#define HAL_I3C_MODULE_ENABLED +#define HAL_ICACHE_MODULE_ENABLED +#define HAL_IRDA_MODULE_ENABLED +#define HAL_IWDG_MODULE_ENABLED +#define HAL_LPTIM_MODULE_ENABLED +#define HAL_MMC_MODULE_ENABLED +#define HAL_NAND_MODULE_ENABLED +#define HAL_NOR_MODULE_ENABLED +#define HAL_OTFDEC_MODULE_ENABLED +#define HAL_OPAMP_MODULE_ENABLED +#define HAL_PCD_MODULE_ENABLED +#define HAL_PKA_MODULE_ENABLED +#define HAL_PSSI_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_RAMCFG_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_RNG_MODULE_ENABLED +#define HAL_RTC_MODULE_ENABLED +#define HAL_SAI_MODULE_ENABLED +#define HAL_SD_MODULE_ENABLED +#define HAL_SDRAM_MODULE_ENABLED +#define HAL_SMARTCARD_MODULE_ENABLED +#define HAL_SMBUS_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +#define HAL_SRAM_MODULE_ENABLED +#define HAL_TIM_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED +#define HAL_USART_MODULE_ENABLED +#define HAL_WWDG_MODULE_ENABLED +#define HAL_XSPI_MODULE_ENABLED + +/* ####################################### Oscillator Values adaptation ##############################################*/ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) +#define HSE_VALUE 25000000UL /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) +#define HSE_STARTUP_TIMEOUT 100UL /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal Core Speed oscillator (CSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when CSI is used as system clock source, directly or through the PLL). + */ +#if !defined (CSI_VALUE) +#define CSI_VALUE 4000000UL /*!< Value of the Internal oscillator in Hz*/ +#endif /* CSI_VALUE */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) +#define HSI_VALUE 64000000UL /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal High Speed oscillator (HSI48) value for USB FS, SDMMC and RNG. + * This internal oscillator is mainly dedicated to provide a high precision clock to + * the USB peripheral by means of a special Clock Recovery System (CRS) circuitry. + * When the CRS is not used, the HSI48 RC oscillator runs on it default frequency + * which is subject to manufacturing process variations. + */ +#if !defined (HSI48_VALUE) +#define HSI48_VALUE 48000000UL /*!< Value of the Internal High Speed oscillator for USB FS/SDMMC/RNG in Hz. + The real value my vary depending on manufacturing process variations.*/ +#endif /* HSI48_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) +#define LSI_VALUE 32000UL /*!< LSI Typical Value in Hz*/ +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz +The real value may vary depending on the variations +in voltage and temperature.*/ + +#if !defined (LSI_STARTUP_TIME) +#define LSI_STARTUP_TIME 130UL /*!< Time out for LSI start up, in ms */ +#endif /* LSI_STARTUP_TIME */ + +/** + * @brief External Low Speed oscillator (LSE) value. + * This value is used by the UART, RTC HAL module to compute the system frequency + */ +#if !defined (LSE_VALUE) +#define LSE_VALUE 32768UL /*!< Value of the External oscillator in Hz*/ +#endif /* LSE_VALUE */ + +#if !defined (LSE_STARTUP_TIMEOUT) +#define LSE_STARTUP_TIMEOUT 5000UL /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + + +/** + * @brief External clock source for SPI/SAI peripheral + * This value is used by the SPI/SAI HAL module to compute the SPI/SAI clock source + * frequency, this source is inserted directly through I2S_CKIN pad. + */ +#if !defined (EXTERNAL_CLOCK_VALUE) +#define EXTERNAL_CLOCK_VALUE 12288000UL /*!< Value of the External clock in Hz*/ +#endif /* EXTERNAL_CLOCK_VALUE */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ############################################ System Configuration ################################################ */ +/** + * @brief This is the HAL system configuration section + */ +#define VDD_VALUE 3300UL /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY ((1UL<<__NVIC_PRIO_BITS) - 1UL) /*!< tick interrupt priority (lowest by default) */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 0U /*!< Enable prefetch */ + +/* ############################################ Assert Selection #################################################### */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1U */ + +/* ############################################ Register callback feature configuration ############################# */ +/** + * @brief Set below the peripheral configuration to "1U" to add the support + * of HAL callback registration/unregistration feature for the HAL + * driver(s). This allows user application to provide specific callback + * functions thanks to HAL_PPP_RegisterCallback() rather than overwriting + * the default weak callback functions (see each stm32h5xx_hal_ppp.h file + * for possible callback identifiers defined in HAL_PPP_CallbackIDTypeDef + * for each PPP peripheral). + */ +#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */ +#define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */ +#define USE_HAL_COMP_REGISTER_CALLBACKS 0U /* COMP register callback disabled */ +#define USE_HAL_CORDIC_REGISTER_CALLBACKS 0U /* CORDIC register callback disabled */ +#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */ +#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */ +#define USE_HAL_DCMI_REGISTER_CALLBACKS 0U /* DCMI register callback disabled */ +#define USE_HAL_DTS_REGISTER_CALLBACKS 0U /* DTS register callback disabled */ +#define USE_HAL_ETH_REGISTER_CALLBACKS 0U /* ETH register callback disabled */ +#define USE_HAL_FDCAN_REGISTER_CALLBACKS 0U /* FDCAN register callback disabled */ +#define USE_HAL_FMAC_REGISTER_CALLBACKS 0U /* FMAC register callback disabled */ +#define USE_HAL_NOR_REGISTER_CALLBACKS 0U /* NOR register callback disabled */ +#define USE_HAL_HASH_REGISTER_CALLBACKS 0U /* HASH register callback disabled */ +#define USE_HAL_HCD_REGISTER_CALLBACKS 0U /* HCD register callback disabled */ +#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */ +#define USE_HAL_I2S_REGISTER_CALLBACKS 0U /* I2S register callback disabled */ +#define USE_HAL_I3C_REGISTER_CALLBACKS 0U /* I3C register callback disabled */ +#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U /* IRDA register callback disabled */ +#define USE_HAL_IWDG_REGISTER_CALLBACKS 0U /* IWDG register callback disabled */ +#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */ +#define USE_HAL_MMC_REGISTER_CALLBACKS 0U /* MMC register callback disabled */ +#define USE_HAL_NAND_REGISTER_CALLBACKS 0U /* NAND register callback disabled */ +#define USE_HAL_OPAMP_REGISTER_CALLBACKS 0U /* OTFDEC register callback disabled */ +#define USE_HAL_OTFDEC_REGISTER_CALLBACKS 0U /* OPAMP register callback disabled */ +#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */ +#define USE_HAL_PKA_REGISTER_CALLBACKS 0U /* PKA register callback disabled */ +#define USE_HAL_RAMCFG_REGISTER_CALLBACKS 0U /* RAMCFG register callback disabled */ +#define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */ +#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */ +#define USE_HAL_SAI_REGISTER_CALLBACKS 0U /* SAI register callback disabled */ +#define USE_HAL_SD_REGISTER_CALLBACKS 0U /* SD register callback disabled */ +#define USE_HAL_SDRAM_REGISTER_CALLBACKS 0U /* SDRAM register callback disabled */ +#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U /* SMARTCARD register callback disabled */ +#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U /* SMBUS register callback disabled */ +#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */ +#define USE_HAL_SRAM_REGISTER_CALLBACKS 0U /* SRAM register callback disabled */ +#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */ +#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */ +#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */ +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */ +#define USE_HAL_XSPI_REGISTER_CALLBACKS 0U /* XSPI register callback disabled */ + +/* ############################################ SPI peripheral configuration ######################################## */ + +/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver + * Activated: CRC code is present inside driver + * Deactivated: CRC code cleaned from driver + */ +#define USE_SPI_CRC 1U + + +/* Includes ----------------------------------------------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED +#include "stm32h5xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED +#include "stm32h5xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_ICACHE_MODULE_ENABLED +#include "stm32h5xx_hal_icache.h" +#endif /* HAL_ICACHE_MODULE_ENABLED */ + +#ifdef HAL_DCACHE_MODULE_ENABLED +#include "stm32h5xx_hal_dcache.h" +#endif /* HAL_DCACHE_MODULE_ENABLED */ + +#ifdef HAL_GTZC_MODULE_ENABLED +#include "stm32h5xx_hal_gtzc.h" +#endif /* HAL_GTZC_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED +#include "stm32h5xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_DTS_MODULE_ENABLED +#include "stm32h5xx_hal_dts.h" +#endif /* HAL_DTS_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED +#include "stm32h5xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_PKA_MODULE_ENABLED +#include "stm32h5xx_hal_pka.h" +#endif /* HAL_PKA_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED +#include "stm32h5xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED +#include "stm32h5xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED +#include "stm32h5xx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED +#include "stm32h5xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED +#include "stm32h5xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_HASH_MODULE_ENABLED +#include "stm32h5xx_hal_hash.h" +#endif /* HAL_HASH_MODULE_ENABLED */ + +#ifdef HAL_SRAM_MODULE_ENABLED +#include "stm32h5xx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + +#ifdef HAL_SDRAM_MODULE_ENABLED +#include "stm32h5xx_hal_sdram.h" +#endif /* HAL_SDRAM_MODULE_ENABLED */ + +#ifdef HAL_MMC_MODULE_ENABLED +#include "stm32h5xx_hal_mmc.h" +#endif /* HAL_MMC_MODULE_ENABLED */ + +#ifdef HAL_NOR_MODULE_ENABLED +#include "stm32h5xx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ + +#ifdef HAL_NAND_MODULE_ENABLED +#include "stm32h5xx_hal_nand.h" +#endif /* HAL_NAND_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED +#include "stm32h5xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_I2S_MODULE_ENABLED +#include "stm32h5xx_hal_i2s.h" +#endif /* HAL_I2S_MODULE_ENABLED */ + +#ifdef HAL_I3C_MODULE_ENABLED +#include "stm32h5xx_hal_i3c.h" +#endif /* HAL_I3C_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED +#include "stm32h5xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_LPTIM_MODULE_ENABLED +#include "stm32h5xx_hal_lptim.h" +#endif /* HAL_LPTIM_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED +#include "stm32h5xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_XSPI_MODULE_ENABLED +#include "stm32h5xx_hal_xspi.h" +#endif /* HAL_XSPI_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED +#include "stm32h5xx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED +#include "stm32h5xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SAI_MODULE_ENABLED +#include "stm32h5xx_hal_sai.h" +#endif /* HAL_SAI_MODULE_ENABLED */ + +#ifdef HAL_SD_MODULE_ENABLED +#include "stm32h5xx_hal_sd.h" +#endif /* HAL_SD_MODULE_ENABLED */ + +#ifdef HAL_SMBUS_MODULE_ENABLED +#include "stm32h5xx_hal_smbus.h" +#endif /* HAL_SMBUS_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED +#include "stm32h5xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED +#include "stm32h5xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED +#include "stm32h5xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED +#include "stm32h5xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED +#include "stm32h5xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED +#include "stm32h5xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED +#include "stm32h5xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED +#include "stm32h5xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_HCD_MODULE_ENABLED +#include "stm32h5xx_hal_hcd.h" +#endif /* HAL_HCD_MODULE_ENABLED */ + +#ifdef HAL_COMP_MODULE_ENABLED +#include "stm32h5xx_hal_comp.h" +#endif /* HAL_COMP_MODULE_ENABLED */ + +#ifdef HAL_CORDIC_MODULE_ENABLED +#include "stm32h5xx_hal_cordic.h" +#endif /* HAL_CORDIC_MODULE_ENABLED */ + +#ifdef HAL_DCMI_MODULE_ENABLED +#include "stm32h5xx_hal_dcmi.h" +#endif /* HAL_DCMI_MODULE_ENABLED */ + +#ifdef HAL_EXTI_MODULE_ENABLED +#include "stm32h5xx_hal_exti.h" +#endif /* HAL_EXTI_MODULE_ENABLED */ + +#ifdef HAL_ETH_MODULE_ENABLED +#include "stm32h5xx_hal_eth.h" +#endif /* HAL_ETH_MODULE_ENABLED */ + +#ifdef HAL_FDCAN_MODULE_ENABLED +#include "stm32h5xx_hal_fdcan.h" +#endif /* HAL_FDCAN_MODULE_ENABLED */ + +#ifdef HAL_CEC_MODULE_ENABLED +#include "stm32h5xx_hal_cec.h" +#endif /* HAL_CEC_MODULE_ENABLED */ + +#ifdef HAL_FMAC_MODULE_ENABLED +#include "stm32h5xx_hal_fmac.h" +#endif /* HAL_FMAC_MODULE_ENABLED */ + +#ifdef HAL_OPAMP_MODULE_ENABLED +#include "stm32h5xx_hal_opamp.h" +#endif /* HAL_OPAMP_MODULE_ENABLED */ + +#ifdef HAL_OTFDEC_MODULE_ENABLED +#include "stm32h5xx_hal_otfdec.h" +#endif /* HAL_OTFDEC_MODULE_ENABLED */ + +#ifdef HAL_PSSI_MODULE_ENABLED +#include "stm32h5xx_hal_pssi.h" +#endif /* HAL_PSSI_MODULE_ENABLED */ + +#ifdef HAL_RAMCFG_MODULE_ENABLED +#include "stm32h5xx_hal_ramcfg.h" +#endif /* HAL_RAMCFG_MODULE_ENABLED */ + +/* Exported macro ----------------------------------------------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ +#define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ----------------------------------------------------------------------------------------------- */ +void assert_failed(uint8_t *file, uint32_t line); +#else +#define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32H5xx_HAL_CONF_H */ diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/fetch/CMakeLists.txt b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/fetch/CMakeLists.txt index 3709d3822c5..641e4776264 100644 --- a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/fetch/CMakeLists.txt +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/fetch/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/stm32_gcc.cmake) if(NOT TEST_FAMILIES) - set(TEST_FAMILIES C0 F0 F1 F2 F3 F4 F7 G0 G4 H7 L0 L1 L4 L5 MP1 U5 WB WL) + set(TEST_FAMILIES C0 F0 F1 F2 F3 F4 F7 G0 G4 H7 L0 L1 L4 L5 MP1 U0 U5 WB WL) endif() # Generate the family long names list by prepending STM32 to elements in TEST_FAMILIES diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/fetch/stm32h5xx_hal_conf.h b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/fetch/stm32h5xx_hal_conf.h new file mode 100644 index 00000000000..c453c736eee --- /dev/null +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/fetch/stm32h5xx_hal_conf.h @@ -0,0 +1,488 @@ +/** + ********************************************************************************************************************** + * @file stm32h5xx_hal_conf_template.h + * @author MCD Application Team + * @brief HAL configuration template file. + * This file should be copied to the application folder and renamed + * to stm32h5xx_hal_conf.h. + ********************************************************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ********************************************************************************************************************** + */ + +/* Define to prevent recursive inclusion -----------------------------------------------------------------------------*/ +#ifndef STM32H5xx_HAL_CONF_H +#define STM32H5xx_HAL_CONF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Exported types ----------------------------------------------------------------------------------------------------*/ +/* Exported constants ------------------------------------------------------------------------------------------------*/ + +/* ########################################### Module Selection ##################################################### */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ +#define HAL_MODULE_ENABLED +#define HAL_ADC_MODULE_ENABLED +#define HAL_CEC_MODULE_ENABLED +#define HAL_COMP_MODULE_ENABLED +#define HAL_CORDIC_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED +#define HAL_CRC_MODULE_ENABLED +#define HAL_CRYP_MODULE_ENABLED +#define HAL_DAC_MODULE_ENABLED +#define HAL_DCACHE_MODULE_ENABLED +#define HAL_DCMI_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_DTS_MODULE_ENABLED +#define HAL_EXTI_MODULE_ENABLED +#define HAL_ETH_MODULE_ENABLED +#define HAL_FDCAN_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_FMAC_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_GTZC_MODULE_ENABLED +#define HAL_HASH_MODULE_ENABLED +#define HAL_HCD_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +#define HAL_I2S_MODULE_ENABLED +#define HAL_I3C_MODULE_ENABLED +#define HAL_ICACHE_MODULE_ENABLED +#define HAL_IRDA_MODULE_ENABLED +#define HAL_IWDG_MODULE_ENABLED +#define HAL_LPTIM_MODULE_ENABLED +#define HAL_MMC_MODULE_ENABLED +#define HAL_NAND_MODULE_ENABLED +#define HAL_NOR_MODULE_ENABLED +#define HAL_OTFDEC_MODULE_ENABLED +#define HAL_OPAMP_MODULE_ENABLED +#define HAL_PCD_MODULE_ENABLED +#define HAL_PKA_MODULE_ENABLED +#define HAL_PSSI_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_RAMCFG_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_RNG_MODULE_ENABLED +#define HAL_RTC_MODULE_ENABLED +#define HAL_SAI_MODULE_ENABLED +#define HAL_SD_MODULE_ENABLED +#define HAL_SDRAM_MODULE_ENABLED +#define HAL_SMARTCARD_MODULE_ENABLED +#define HAL_SMBUS_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +#define HAL_SRAM_MODULE_ENABLED +#define HAL_TIM_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED +#define HAL_USART_MODULE_ENABLED +#define HAL_WWDG_MODULE_ENABLED +#define HAL_XSPI_MODULE_ENABLED + +/* ####################################### Oscillator Values adaptation ##############################################*/ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) +#define HSE_VALUE 25000000UL /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) +#define HSE_STARTUP_TIMEOUT 100UL /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal Core Speed oscillator (CSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when CSI is used as system clock source, directly or through the PLL). + */ +#if !defined (CSI_VALUE) +#define CSI_VALUE 4000000UL /*!< Value of the Internal oscillator in Hz*/ +#endif /* CSI_VALUE */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) +#define HSI_VALUE 64000000UL /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal High Speed oscillator (HSI48) value for USB FS, SDMMC and RNG. + * This internal oscillator is mainly dedicated to provide a high precision clock to + * the USB peripheral by means of a special Clock Recovery System (CRS) circuitry. + * When the CRS is not used, the HSI48 RC oscillator runs on it default frequency + * which is subject to manufacturing process variations. + */ +#if !defined (HSI48_VALUE) +#define HSI48_VALUE 48000000UL /*!< Value of the Internal High Speed oscillator for USB FS/SDMMC/RNG in Hz. + The real value my vary depending on manufacturing process variations.*/ +#endif /* HSI48_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) +#define LSI_VALUE 32000UL /*!< LSI Typical Value in Hz*/ +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz +The real value may vary depending on the variations +in voltage and temperature.*/ + +#if !defined (LSI_STARTUP_TIME) +#define LSI_STARTUP_TIME 130UL /*!< Time out for LSI start up, in ms */ +#endif /* LSI_STARTUP_TIME */ + +/** + * @brief External Low Speed oscillator (LSE) value. + * This value is used by the UART, RTC HAL module to compute the system frequency + */ +#if !defined (LSE_VALUE) +#define LSE_VALUE 32768UL /*!< Value of the External oscillator in Hz*/ +#endif /* LSE_VALUE */ + +#if !defined (LSE_STARTUP_TIMEOUT) +#define LSE_STARTUP_TIMEOUT 5000UL /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + + +/** + * @brief External clock source for SPI/SAI peripheral + * This value is used by the SPI/SAI HAL module to compute the SPI/SAI clock source + * frequency, this source is inserted directly through I2S_CKIN pad. + */ +#if !defined (EXTERNAL_CLOCK_VALUE) +#define EXTERNAL_CLOCK_VALUE 12288000UL /*!< Value of the External clock in Hz*/ +#endif /* EXTERNAL_CLOCK_VALUE */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ############################################ System Configuration ################################################ */ +/** + * @brief This is the HAL system configuration section + */ +#define VDD_VALUE 3300UL /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY ((1UL<<__NVIC_PRIO_BITS) - 1UL) /*!< tick interrupt priority (lowest by default) */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 0U /*!< Enable prefetch */ + +/* ############################################ Assert Selection #################################################### */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1U */ + +/* ############################################ Register callback feature configuration ############################# */ +/** + * @brief Set below the peripheral configuration to "1U" to add the support + * of HAL callback registration/unregistration feature for the HAL + * driver(s). This allows user application to provide specific callback + * functions thanks to HAL_PPP_RegisterCallback() rather than overwriting + * the default weak callback functions (see each stm32h5xx_hal_ppp.h file + * for possible callback identifiers defined in HAL_PPP_CallbackIDTypeDef + * for each PPP peripheral). + */ +#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */ +#define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */ +#define USE_HAL_COMP_REGISTER_CALLBACKS 0U /* COMP register callback disabled */ +#define USE_HAL_CORDIC_REGISTER_CALLBACKS 0U /* CORDIC register callback disabled */ +#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */ +#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */ +#define USE_HAL_DCMI_REGISTER_CALLBACKS 0U /* DCMI register callback disabled */ +#define USE_HAL_DTS_REGISTER_CALLBACKS 0U /* DTS register callback disabled */ +#define USE_HAL_ETH_REGISTER_CALLBACKS 0U /* ETH register callback disabled */ +#define USE_HAL_FDCAN_REGISTER_CALLBACKS 0U /* FDCAN register callback disabled */ +#define USE_HAL_FMAC_REGISTER_CALLBACKS 0U /* FMAC register callback disabled */ +#define USE_HAL_NOR_REGISTER_CALLBACKS 0U /* NOR register callback disabled */ +#define USE_HAL_HASH_REGISTER_CALLBACKS 0U /* HASH register callback disabled */ +#define USE_HAL_HCD_REGISTER_CALLBACKS 0U /* HCD register callback disabled */ +#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */ +#define USE_HAL_I2S_REGISTER_CALLBACKS 0U /* I2S register callback disabled */ +#define USE_HAL_I3C_REGISTER_CALLBACKS 0U /* I3C register callback disabled */ +#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U /* IRDA register callback disabled */ +#define USE_HAL_IWDG_REGISTER_CALLBACKS 0U /* IWDG register callback disabled */ +#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */ +#define USE_HAL_MMC_REGISTER_CALLBACKS 0U /* MMC register callback disabled */ +#define USE_HAL_NAND_REGISTER_CALLBACKS 0U /* NAND register callback disabled */ +#define USE_HAL_OPAMP_REGISTER_CALLBACKS 0U /* OTFDEC register callback disabled */ +#define USE_HAL_OTFDEC_REGISTER_CALLBACKS 0U /* OPAMP register callback disabled */ +#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */ +#define USE_HAL_PKA_REGISTER_CALLBACKS 0U /* PKA register callback disabled */ +#define USE_HAL_RAMCFG_REGISTER_CALLBACKS 0U /* RAMCFG register callback disabled */ +#define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */ +#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */ +#define USE_HAL_SAI_REGISTER_CALLBACKS 0U /* SAI register callback disabled */ +#define USE_HAL_SD_REGISTER_CALLBACKS 0U /* SD register callback disabled */ +#define USE_HAL_SDRAM_REGISTER_CALLBACKS 0U /* SDRAM register callback disabled */ +#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U /* SMARTCARD register callback disabled */ +#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U /* SMBUS register callback disabled */ +#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */ +#define USE_HAL_SRAM_REGISTER_CALLBACKS 0U /* SRAM register callback disabled */ +#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */ +#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */ +#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */ +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */ +#define USE_HAL_XSPI_REGISTER_CALLBACKS 0U /* XSPI register callback disabled */ + +/* ############################################ SPI peripheral configuration ######################################## */ + +/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver + * Activated: CRC code is present inside driver + * Deactivated: CRC code cleaned from driver + */ +#define USE_SPI_CRC 1U + + +/* Includes ----------------------------------------------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED +#include "stm32h5xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED +#include "stm32h5xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_ICACHE_MODULE_ENABLED +#include "stm32h5xx_hal_icache.h" +#endif /* HAL_ICACHE_MODULE_ENABLED */ + +#ifdef HAL_DCACHE_MODULE_ENABLED +#include "stm32h5xx_hal_dcache.h" +#endif /* HAL_DCACHE_MODULE_ENABLED */ + +#ifdef HAL_GTZC_MODULE_ENABLED +#include "stm32h5xx_hal_gtzc.h" +#endif /* HAL_GTZC_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED +#include "stm32h5xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_DTS_MODULE_ENABLED +#include "stm32h5xx_hal_dts.h" +#endif /* HAL_DTS_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED +#include "stm32h5xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_PKA_MODULE_ENABLED +#include "stm32h5xx_hal_pka.h" +#endif /* HAL_PKA_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED +#include "stm32h5xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED +#include "stm32h5xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED +#include "stm32h5xx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED +#include "stm32h5xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED +#include "stm32h5xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_HASH_MODULE_ENABLED +#include "stm32h5xx_hal_hash.h" +#endif /* HAL_HASH_MODULE_ENABLED */ + +#ifdef HAL_SRAM_MODULE_ENABLED +#include "stm32h5xx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + +#ifdef HAL_SDRAM_MODULE_ENABLED +#include "stm32h5xx_hal_sdram.h" +#endif /* HAL_SDRAM_MODULE_ENABLED */ + +#ifdef HAL_MMC_MODULE_ENABLED +#include "stm32h5xx_hal_mmc.h" +#endif /* HAL_MMC_MODULE_ENABLED */ + +#ifdef HAL_NOR_MODULE_ENABLED +#include "stm32h5xx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ + +#ifdef HAL_NAND_MODULE_ENABLED +#include "stm32h5xx_hal_nand.h" +#endif /* HAL_NAND_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED +#include "stm32h5xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_I2S_MODULE_ENABLED +#include "stm32h5xx_hal_i2s.h" +#endif /* HAL_I2S_MODULE_ENABLED */ + +#ifdef HAL_I3C_MODULE_ENABLED +#include "stm32h5xx_hal_i3c.h" +#endif /* HAL_I3C_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED +#include "stm32h5xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_LPTIM_MODULE_ENABLED +#include "stm32h5xx_hal_lptim.h" +#endif /* HAL_LPTIM_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED +#include "stm32h5xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_XSPI_MODULE_ENABLED +#include "stm32h5xx_hal_xspi.h" +#endif /* HAL_XSPI_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED +#include "stm32h5xx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED +#include "stm32h5xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SAI_MODULE_ENABLED +#include "stm32h5xx_hal_sai.h" +#endif /* HAL_SAI_MODULE_ENABLED */ + +#ifdef HAL_SD_MODULE_ENABLED +#include "stm32h5xx_hal_sd.h" +#endif /* HAL_SD_MODULE_ENABLED */ + +#ifdef HAL_SMBUS_MODULE_ENABLED +#include "stm32h5xx_hal_smbus.h" +#endif /* HAL_SMBUS_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED +#include "stm32h5xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED +#include "stm32h5xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED +#include "stm32h5xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED +#include "stm32h5xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED +#include "stm32h5xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED +#include "stm32h5xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED +#include "stm32h5xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED +#include "stm32h5xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_HCD_MODULE_ENABLED +#include "stm32h5xx_hal_hcd.h" +#endif /* HAL_HCD_MODULE_ENABLED */ + +#ifdef HAL_COMP_MODULE_ENABLED +#include "stm32h5xx_hal_comp.h" +#endif /* HAL_COMP_MODULE_ENABLED */ + +#ifdef HAL_CORDIC_MODULE_ENABLED +#include "stm32h5xx_hal_cordic.h" +#endif /* HAL_CORDIC_MODULE_ENABLED */ + +#ifdef HAL_DCMI_MODULE_ENABLED +#include "stm32h5xx_hal_dcmi.h" +#endif /* HAL_DCMI_MODULE_ENABLED */ + +#ifdef HAL_EXTI_MODULE_ENABLED +#include "stm32h5xx_hal_exti.h" +#endif /* HAL_EXTI_MODULE_ENABLED */ + +#ifdef HAL_ETH_MODULE_ENABLED +#include "stm32h5xx_hal_eth.h" +#endif /* HAL_ETH_MODULE_ENABLED */ + +#ifdef HAL_FDCAN_MODULE_ENABLED +#include "stm32h5xx_hal_fdcan.h" +#endif /* HAL_FDCAN_MODULE_ENABLED */ + +#ifdef HAL_CEC_MODULE_ENABLED +#include "stm32h5xx_hal_cec.h" +#endif /* HAL_CEC_MODULE_ENABLED */ + +#ifdef HAL_FMAC_MODULE_ENABLED +#include "stm32h5xx_hal_fmac.h" +#endif /* HAL_FMAC_MODULE_ENABLED */ + +#ifdef HAL_OPAMP_MODULE_ENABLED +#include "stm32h5xx_hal_opamp.h" +#endif /* HAL_OPAMP_MODULE_ENABLED */ + +#ifdef HAL_OTFDEC_MODULE_ENABLED +#include "stm32h5xx_hal_otfdec.h" +#endif /* HAL_OTFDEC_MODULE_ENABLED */ + +#ifdef HAL_PSSI_MODULE_ENABLED +#include "stm32h5xx_hal_pssi.h" +#endif /* HAL_PSSI_MODULE_ENABLED */ + +#ifdef HAL_RAMCFG_MODULE_ENABLED +#include "stm32h5xx_hal_ramcfg.h" +#endif /* HAL_RAMCFG_MODULE_ENABLED */ + +/* Exported macro ----------------------------------------------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ +#define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ----------------------------------------------------------------------------------------------- */ +void assert_failed(uint8_t *file, uint32_t line); +#else +#define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32H5xx_HAL_CONF_H */ diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/fetch/stm32u0xx_hal_conf.h b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/fetch/stm32u0xx_hal_conf.h new file mode 100644 index 00000000000..e402e06798a --- /dev/null +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/fetch/stm32u0xx_hal_conf.h @@ -0,0 +1,335 @@ +/** + ****************************************************************************** + * @file stm32u0xx_hal_conf.h + * @author MCD Application Team + * @brief HAL configuration file. + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32U0xx_HAL_CONF_H +#define __STM32U0xx_HAL_CONF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ + +#define HAL_MODULE_ENABLED +#define HAL_ADC_MODULE_ENABLED +#define HAL_COMP_MODULE_ENABLED +#define HAL_CRC_MODULE_ENABLED +#define HAL_CRS_MODULE_ENABLED +#define HAL_CRYP_MODULE_ENABLED +#define HAL_DAC_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +#define HAL_IRDA_MODULE_ENABLED +#define HAL_IWDG_MODULE_ENABLED +#define HAL_LCD_MODULE_ENABLED +#define HAL_LPTIM_MODULE_ENABLED +#define HAL_OPAMP_MODULE_ENABLED +#define HAL_PCD_MODULE_ENABLED +#define HAL_RNG_MODULE_ENABLED +#define HAL_RTC_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +#define HAL_SMARTCARD_MODULE_ENABLED +#define HAL_TIM_MODULE_ENABLED +#define HAL_TSC_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED +#define HAL_USART_MODULE_ENABLED +#define HAL_WWDG_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_EXTI_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED + +/* ########################## Oscillator Values adaptation ####################*/ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) + #define HSE_VALUE 4000000U /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) + #define HSE_STARTUP_TIMEOUT 100U /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal Multiple Speed oscillator (MSI) default value. + * This value is the default MSI range value after Reset. + */ +#if !defined (MSI_VALUE) + #define MSI_VALUE 4000000U /*!< Value of the Internal oscillator in Hz*/ +#endif /* MSI_VALUE */ + +/** + * @brief Internal Multiple Speed oscillator (MSI) default value. + * This value is the default MSI range value after Reset. + */ +#if !defined (MSI32_VALUE) +#define MSI32_VALUE 32000000U /*!< Value of the Internal oscillator in Hz*/ +#endif /* MSI32_VALUE */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) + #define HSI_VALUE 16000000U /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal High Speed oscillator (HSI48) value for USB FS and RNG. + * This internal oscillator is mainly dedicated to provide a high precision clock to + * the USB peripheral by means of a special Clock Recovery System (CRS) circuitry. + * When the CRS is not used, the HSI48 RC oscillator runs on it default frequency + * which is subject to manufacturing process variations. + */ +#if !defined (HSI48_VALUE) + #define HSI48_VALUE 48000000U /*!< Value of the Internal High Speed oscillator for USB FS/RNG in Hz. + The real value my vary depending on manufacturing process variations.*/ +#endif /* HSI48_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) + #define LSI_VALUE 32000U /*!< LSI Typical Value in Hz*/ +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz + The real value may vary depending on the variations + in voltage and temperature.*/ +/** + * @brief External Low Speed oscillator (LSE) value. + * This value is used by the UART, RTC HAL module to compute the system frequency + */ +#if !defined (LSE_VALUE) + #define LSE_VALUE 32768U /*!< Value of the External oscillator in Hz*/ +#endif /* LSE_VALUE */ + +#if !defined (LSE_STARTUP_TIMEOUT) + #define LSE_STARTUP_TIMEOUT 5000U /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ + +#define VDD_VALUE 3300U /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY (3U) /*!< tick interrupt priority (lowest by default) */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 0U +#define INSTRUCTION_CACHE_ENABLE 1U + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ + +/* #define USE_FULL_ASSERT 1U */ + +/* ################## Register callback feature configuration ############### */ +/** + * @brief Set below the peripheral configuration to "1U" to add the support + * of HAL callback registration/unregistration feature for the HAL + * driver(s). This allows user application to provide specific callback + * functions thanks to HAL_PPP_RegisterCallback() rather than overwriting + * the default weak callback functions (see each stm32n6xx_hal_ppp.h file + * for possible callback identifiers defined in HAL_PPP_CallbackIDTypeDef + * for each PPP peripheral). + */ +#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */ +#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */ +#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */ +#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */ +#define USE_HAL_IWDG_REGISTER_CALLBACKS 0U /* IWDG register callback disabled */ +#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U /* IRDA register callback disabled */ +#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */ +#define USE_HAL_LCD_REGISTER_CALLBACKS 0U /* LCD register callback disabled */ +#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */ +#define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */ +#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */ +#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U /* SMARTCARD register callback disabled */ +#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */ +#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */ +#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */ +#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */ +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */ + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED +#include "stm32u0xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED +#include "stm32u0xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED +#include "stm32u0xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED +#include "stm32u0xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED +#include "stm32u0xx_hal_adc.h" +#include "stm32u0xx_hal_adc_ex.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_COMP_MODULE_ENABLED +#include "stm32u0xx_hal_comp.h" +#endif /* HAL_COMP_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED +#include "stm32u0xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRS_MODULE_ENABLED +#include "stm32u0xx_ll_crs.h" +#endif /* HAL_CRS_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED +#include "stm32u0xx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED +#include "stm32u0xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_EXTI_MODULE_ENABLED +#include "stm32u0xx_hal_exti.h" +#endif /* HAL_EXTI_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED +#include "stm32u0xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED +#include "stm32u0xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED +#include "stm32u0xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_LPTIM_MODULE_ENABLED +#include "stm32u0xx_hal_lptim.h" +#endif /* HAL_LPTIM_MODULE_ENABLED */ + +#ifdef HAL_LCD_MODULE_ENABLED +#include "stm32u0xx_hal_lcd.h" +#endif /* HAL_LTDC_MODULE_ENABLED */ + +#ifdef HAL_OPAMP_MODULE_ENABLED +#include "stm32u0xx_hal_opamp.h" +#endif /* HAL_OPAMP_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED +#include "stm32u0xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED +#include "stm32u0xx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED +#include "stm32u0xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED +#include "stm32u0xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED +#include "stm32u0xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_TSC_MODULE_ENABLED +#include "stm32u0xx_ll_system.h" +#include "stm32u0xx_hal_tsc.h" +#endif /* HAL_TSC_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED +#include "stm32u0xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED +#include "stm32u0xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED +#include "stm32u0xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED +#include "stm32u0xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED +#include "stm32u0xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_LCD_MODULE_ENABLED +#include "stm32u0xx_hal_lcd.h" +#endif /* HAL_LCD_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED +#include "stm32u0xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ + #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ + void assert_failed(uint8_t *file, uint32_t line); +#else + #define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32U0xx_HAL_CONF_H */ diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/hal/CMakeLists.txt b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/hal/CMakeLists.txt index 60530684145..c1f5da7b8cf 100644 --- a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/hal/CMakeLists.txt +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/hal/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/stm32_gcc.cmake) if(NOT TEST_FAMILIES) - set(TEST_FAMILIES C0 F0 F1 F2 F3 F4 F7 G0 G4 H7 L0 L1 L4 L5 MP1 U5 WB WL) + set(TEST_FAMILIES C0 F0 F1 F2 F3 F4 F7 G0 G4 H7 L0 L1 L4 L5 MP1 U0 U5 WB WL) endif() # Generate the family long names list by prepending STM32 to elements in TEST_FAMILIES diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/hal/stm32h5xx_hal_conf.h b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/hal/stm32h5xx_hal_conf.h new file mode 100644 index 00000000000..c453c736eee --- /dev/null +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/hal/stm32h5xx_hal_conf.h @@ -0,0 +1,488 @@ +/** + ********************************************************************************************************************** + * @file stm32h5xx_hal_conf_template.h + * @author MCD Application Team + * @brief HAL configuration template file. + * This file should be copied to the application folder and renamed + * to stm32h5xx_hal_conf.h. + ********************************************************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ********************************************************************************************************************** + */ + +/* Define to prevent recursive inclusion -----------------------------------------------------------------------------*/ +#ifndef STM32H5xx_HAL_CONF_H +#define STM32H5xx_HAL_CONF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Exported types ----------------------------------------------------------------------------------------------------*/ +/* Exported constants ------------------------------------------------------------------------------------------------*/ + +/* ########################################### Module Selection ##################################################### */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ +#define HAL_MODULE_ENABLED +#define HAL_ADC_MODULE_ENABLED +#define HAL_CEC_MODULE_ENABLED +#define HAL_COMP_MODULE_ENABLED +#define HAL_CORDIC_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED +#define HAL_CRC_MODULE_ENABLED +#define HAL_CRYP_MODULE_ENABLED +#define HAL_DAC_MODULE_ENABLED +#define HAL_DCACHE_MODULE_ENABLED +#define HAL_DCMI_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_DTS_MODULE_ENABLED +#define HAL_EXTI_MODULE_ENABLED +#define HAL_ETH_MODULE_ENABLED +#define HAL_FDCAN_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_FMAC_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_GTZC_MODULE_ENABLED +#define HAL_HASH_MODULE_ENABLED +#define HAL_HCD_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +#define HAL_I2S_MODULE_ENABLED +#define HAL_I3C_MODULE_ENABLED +#define HAL_ICACHE_MODULE_ENABLED +#define HAL_IRDA_MODULE_ENABLED +#define HAL_IWDG_MODULE_ENABLED +#define HAL_LPTIM_MODULE_ENABLED +#define HAL_MMC_MODULE_ENABLED +#define HAL_NAND_MODULE_ENABLED +#define HAL_NOR_MODULE_ENABLED +#define HAL_OTFDEC_MODULE_ENABLED +#define HAL_OPAMP_MODULE_ENABLED +#define HAL_PCD_MODULE_ENABLED +#define HAL_PKA_MODULE_ENABLED +#define HAL_PSSI_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_RAMCFG_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_RNG_MODULE_ENABLED +#define HAL_RTC_MODULE_ENABLED +#define HAL_SAI_MODULE_ENABLED +#define HAL_SD_MODULE_ENABLED +#define HAL_SDRAM_MODULE_ENABLED +#define HAL_SMARTCARD_MODULE_ENABLED +#define HAL_SMBUS_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +#define HAL_SRAM_MODULE_ENABLED +#define HAL_TIM_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED +#define HAL_USART_MODULE_ENABLED +#define HAL_WWDG_MODULE_ENABLED +#define HAL_XSPI_MODULE_ENABLED + +/* ####################################### Oscillator Values adaptation ##############################################*/ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) +#define HSE_VALUE 25000000UL /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) +#define HSE_STARTUP_TIMEOUT 100UL /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal Core Speed oscillator (CSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when CSI is used as system clock source, directly or through the PLL). + */ +#if !defined (CSI_VALUE) +#define CSI_VALUE 4000000UL /*!< Value of the Internal oscillator in Hz*/ +#endif /* CSI_VALUE */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) +#define HSI_VALUE 64000000UL /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal High Speed oscillator (HSI48) value for USB FS, SDMMC and RNG. + * This internal oscillator is mainly dedicated to provide a high precision clock to + * the USB peripheral by means of a special Clock Recovery System (CRS) circuitry. + * When the CRS is not used, the HSI48 RC oscillator runs on it default frequency + * which is subject to manufacturing process variations. + */ +#if !defined (HSI48_VALUE) +#define HSI48_VALUE 48000000UL /*!< Value of the Internal High Speed oscillator for USB FS/SDMMC/RNG in Hz. + The real value my vary depending on manufacturing process variations.*/ +#endif /* HSI48_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) +#define LSI_VALUE 32000UL /*!< LSI Typical Value in Hz*/ +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz +The real value may vary depending on the variations +in voltage and temperature.*/ + +#if !defined (LSI_STARTUP_TIME) +#define LSI_STARTUP_TIME 130UL /*!< Time out for LSI start up, in ms */ +#endif /* LSI_STARTUP_TIME */ + +/** + * @brief External Low Speed oscillator (LSE) value. + * This value is used by the UART, RTC HAL module to compute the system frequency + */ +#if !defined (LSE_VALUE) +#define LSE_VALUE 32768UL /*!< Value of the External oscillator in Hz*/ +#endif /* LSE_VALUE */ + +#if !defined (LSE_STARTUP_TIMEOUT) +#define LSE_STARTUP_TIMEOUT 5000UL /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + + +/** + * @brief External clock source for SPI/SAI peripheral + * This value is used by the SPI/SAI HAL module to compute the SPI/SAI clock source + * frequency, this source is inserted directly through I2S_CKIN pad. + */ +#if !defined (EXTERNAL_CLOCK_VALUE) +#define EXTERNAL_CLOCK_VALUE 12288000UL /*!< Value of the External clock in Hz*/ +#endif /* EXTERNAL_CLOCK_VALUE */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ############################################ System Configuration ################################################ */ +/** + * @brief This is the HAL system configuration section + */ +#define VDD_VALUE 3300UL /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY ((1UL<<__NVIC_PRIO_BITS) - 1UL) /*!< tick interrupt priority (lowest by default) */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 0U /*!< Enable prefetch */ + +/* ############################################ Assert Selection #################################################### */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1U */ + +/* ############################################ Register callback feature configuration ############################# */ +/** + * @brief Set below the peripheral configuration to "1U" to add the support + * of HAL callback registration/unregistration feature for the HAL + * driver(s). This allows user application to provide specific callback + * functions thanks to HAL_PPP_RegisterCallback() rather than overwriting + * the default weak callback functions (see each stm32h5xx_hal_ppp.h file + * for possible callback identifiers defined in HAL_PPP_CallbackIDTypeDef + * for each PPP peripheral). + */ +#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */ +#define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */ +#define USE_HAL_COMP_REGISTER_CALLBACKS 0U /* COMP register callback disabled */ +#define USE_HAL_CORDIC_REGISTER_CALLBACKS 0U /* CORDIC register callback disabled */ +#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */ +#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */ +#define USE_HAL_DCMI_REGISTER_CALLBACKS 0U /* DCMI register callback disabled */ +#define USE_HAL_DTS_REGISTER_CALLBACKS 0U /* DTS register callback disabled */ +#define USE_HAL_ETH_REGISTER_CALLBACKS 0U /* ETH register callback disabled */ +#define USE_HAL_FDCAN_REGISTER_CALLBACKS 0U /* FDCAN register callback disabled */ +#define USE_HAL_FMAC_REGISTER_CALLBACKS 0U /* FMAC register callback disabled */ +#define USE_HAL_NOR_REGISTER_CALLBACKS 0U /* NOR register callback disabled */ +#define USE_HAL_HASH_REGISTER_CALLBACKS 0U /* HASH register callback disabled */ +#define USE_HAL_HCD_REGISTER_CALLBACKS 0U /* HCD register callback disabled */ +#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */ +#define USE_HAL_I2S_REGISTER_CALLBACKS 0U /* I2S register callback disabled */ +#define USE_HAL_I3C_REGISTER_CALLBACKS 0U /* I3C register callback disabled */ +#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U /* IRDA register callback disabled */ +#define USE_HAL_IWDG_REGISTER_CALLBACKS 0U /* IWDG register callback disabled */ +#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */ +#define USE_HAL_MMC_REGISTER_CALLBACKS 0U /* MMC register callback disabled */ +#define USE_HAL_NAND_REGISTER_CALLBACKS 0U /* NAND register callback disabled */ +#define USE_HAL_OPAMP_REGISTER_CALLBACKS 0U /* OTFDEC register callback disabled */ +#define USE_HAL_OTFDEC_REGISTER_CALLBACKS 0U /* OPAMP register callback disabled */ +#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */ +#define USE_HAL_PKA_REGISTER_CALLBACKS 0U /* PKA register callback disabled */ +#define USE_HAL_RAMCFG_REGISTER_CALLBACKS 0U /* RAMCFG register callback disabled */ +#define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */ +#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */ +#define USE_HAL_SAI_REGISTER_CALLBACKS 0U /* SAI register callback disabled */ +#define USE_HAL_SD_REGISTER_CALLBACKS 0U /* SD register callback disabled */ +#define USE_HAL_SDRAM_REGISTER_CALLBACKS 0U /* SDRAM register callback disabled */ +#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U /* SMARTCARD register callback disabled */ +#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U /* SMBUS register callback disabled */ +#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */ +#define USE_HAL_SRAM_REGISTER_CALLBACKS 0U /* SRAM register callback disabled */ +#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */ +#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */ +#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */ +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */ +#define USE_HAL_XSPI_REGISTER_CALLBACKS 0U /* XSPI register callback disabled */ + +/* ############################################ SPI peripheral configuration ######################################## */ + +/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver + * Activated: CRC code is present inside driver + * Deactivated: CRC code cleaned from driver + */ +#define USE_SPI_CRC 1U + + +/* Includes ----------------------------------------------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED +#include "stm32h5xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED +#include "stm32h5xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_ICACHE_MODULE_ENABLED +#include "stm32h5xx_hal_icache.h" +#endif /* HAL_ICACHE_MODULE_ENABLED */ + +#ifdef HAL_DCACHE_MODULE_ENABLED +#include "stm32h5xx_hal_dcache.h" +#endif /* HAL_DCACHE_MODULE_ENABLED */ + +#ifdef HAL_GTZC_MODULE_ENABLED +#include "stm32h5xx_hal_gtzc.h" +#endif /* HAL_GTZC_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED +#include "stm32h5xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_DTS_MODULE_ENABLED +#include "stm32h5xx_hal_dts.h" +#endif /* HAL_DTS_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED +#include "stm32h5xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_PKA_MODULE_ENABLED +#include "stm32h5xx_hal_pka.h" +#endif /* HAL_PKA_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED +#include "stm32h5xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED +#include "stm32h5xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED +#include "stm32h5xx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED +#include "stm32h5xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED +#include "stm32h5xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_HASH_MODULE_ENABLED +#include "stm32h5xx_hal_hash.h" +#endif /* HAL_HASH_MODULE_ENABLED */ + +#ifdef HAL_SRAM_MODULE_ENABLED +#include "stm32h5xx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + +#ifdef HAL_SDRAM_MODULE_ENABLED +#include "stm32h5xx_hal_sdram.h" +#endif /* HAL_SDRAM_MODULE_ENABLED */ + +#ifdef HAL_MMC_MODULE_ENABLED +#include "stm32h5xx_hal_mmc.h" +#endif /* HAL_MMC_MODULE_ENABLED */ + +#ifdef HAL_NOR_MODULE_ENABLED +#include "stm32h5xx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ + +#ifdef HAL_NAND_MODULE_ENABLED +#include "stm32h5xx_hal_nand.h" +#endif /* HAL_NAND_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED +#include "stm32h5xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_I2S_MODULE_ENABLED +#include "stm32h5xx_hal_i2s.h" +#endif /* HAL_I2S_MODULE_ENABLED */ + +#ifdef HAL_I3C_MODULE_ENABLED +#include "stm32h5xx_hal_i3c.h" +#endif /* HAL_I3C_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED +#include "stm32h5xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_LPTIM_MODULE_ENABLED +#include "stm32h5xx_hal_lptim.h" +#endif /* HAL_LPTIM_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED +#include "stm32h5xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_XSPI_MODULE_ENABLED +#include "stm32h5xx_hal_xspi.h" +#endif /* HAL_XSPI_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED +#include "stm32h5xx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED +#include "stm32h5xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SAI_MODULE_ENABLED +#include "stm32h5xx_hal_sai.h" +#endif /* HAL_SAI_MODULE_ENABLED */ + +#ifdef HAL_SD_MODULE_ENABLED +#include "stm32h5xx_hal_sd.h" +#endif /* HAL_SD_MODULE_ENABLED */ + +#ifdef HAL_SMBUS_MODULE_ENABLED +#include "stm32h5xx_hal_smbus.h" +#endif /* HAL_SMBUS_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED +#include "stm32h5xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED +#include "stm32h5xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED +#include "stm32h5xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED +#include "stm32h5xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED +#include "stm32h5xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED +#include "stm32h5xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED +#include "stm32h5xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED +#include "stm32h5xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_HCD_MODULE_ENABLED +#include "stm32h5xx_hal_hcd.h" +#endif /* HAL_HCD_MODULE_ENABLED */ + +#ifdef HAL_COMP_MODULE_ENABLED +#include "stm32h5xx_hal_comp.h" +#endif /* HAL_COMP_MODULE_ENABLED */ + +#ifdef HAL_CORDIC_MODULE_ENABLED +#include "stm32h5xx_hal_cordic.h" +#endif /* HAL_CORDIC_MODULE_ENABLED */ + +#ifdef HAL_DCMI_MODULE_ENABLED +#include "stm32h5xx_hal_dcmi.h" +#endif /* HAL_DCMI_MODULE_ENABLED */ + +#ifdef HAL_EXTI_MODULE_ENABLED +#include "stm32h5xx_hal_exti.h" +#endif /* HAL_EXTI_MODULE_ENABLED */ + +#ifdef HAL_ETH_MODULE_ENABLED +#include "stm32h5xx_hal_eth.h" +#endif /* HAL_ETH_MODULE_ENABLED */ + +#ifdef HAL_FDCAN_MODULE_ENABLED +#include "stm32h5xx_hal_fdcan.h" +#endif /* HAL_FDCAN_MODULE_ENABLED */ + +#ifdef HAL_CEC_MODULE_ENABLED +#include "stm32h5xx_hal_cec.h" +#endif /* HAL_CEC_MODULE_ENABLED */ + +#ifdef HAL_FMAC_MODULE_ENABLED +#include "stm32h5xx_hal_fmac.h" +#endif /* HAL_FMAC_MODULE_ENABLED */ + +#ifdef HAL_OPAMP_MODULE_ENABLED +#include "stm32h5xx_hal_opamp.h" +#endif /* HAL_OPAMP_MODULE_ENABLED */ + +#ifdef HAL_OTFDEC_MODULE_ENABLED +#include "stm32h5xx_hal_otfdec.h" +#endif /* HAL_OTFDEC_MODULE_ENABLED */ + +#ifdef HAL_PSSI_MODULE_ENABLED +#include "stm32h5xx_hal_pssi.h" +#endif /* HAL_PSSI_MODULE_ENABLED */ + +#ifdef HAL_RAMCFG_MODULE_ENABLED +#include "stm32h5xx_hal_ramcfg.h" +#endif /* HAL_RAMCFG_MODULE_ENABLED */ + +/* Exported macro ----------------------------------------------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ +#define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ----------------------------------------------------------------------------------------------- */ +void assert_failed(uint8_t *file, uint32_t line); +#else +#define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32H5xx_HAL_CONF_H */ diff --git a/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/hal/stm32u0xx_hal_conf.h b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/hal/stm32u0xx_hal_conf.h new file mode 100644 index 00000000000..e402e06798a --- /dev/null +++ b/esp_flasher/lib/esp-serial-flasher/submodules/stm32-cmake/tests/hal/stm32u0xx_hal_conf.h @@ -0,0 +1,335 @@ +/** + ****************************************************************************** + * @file stm32u0xx_hal_conf.h + * @author MCD Application Team + * @brief HAL configuration file. + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32U0xx_HAL_CONF_H +#define __STM32U0xx_HAL_CONF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ + +#define HAL_MODULE_ENABLED +#define HAL_ADC_MODULE_ENABLED +#define HAL_COMP_MODULE_ENABLED +#define HAL_CRC_MODULE_ENABLED +#define HAL_CRS_MODULE_ENABLED +#define HAL_CRYP_MODULE_ENABLED +#define HAL_DAC_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +#define HAL_IRDA_MODULE_ENABLED +#define HAL_IWDG_MODULE_ENABLED +#define HAL_LCD_MODULE_ENABLED +#define HAL_LPTIM_MODULE_ENABLED +#define HAL_OPAMP_MODULE_ENABLED +#define HAL_PCD_MODULE_ENABLED +#define HAL_RNG_MODULE_ENABLED +#define HAL_RTC_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +#define HAL_SMARTCARD_MODULE_ENABLED +#define HAL_TIM_MODULE_ENABLED +#define HAL_TSC_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED +#define HAL_USART_MODULE_ENABLED +#define HAL_WWDG_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_EXTI_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED + +/* ########################## Oscillator Values adaptation ####################*/ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) + #define HSE_VALUE 4000000U /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) + #define HSE_STARTUP_TIMEOUT 100U /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal Multiple Speed oscillator (MSI) default value. + * This value is the default MSI range value after Reset. + */ +#if !defined (MSI_VALUE) + #define MSI_VALUE 4000000U /*!< Value of the Internal oscillator in Hz*/ +#endif /* MSI_VALUE */ + +/** + * @brief Internal Multiple Speed oscillator (MSI) default value. + * This value is the default MSI range value after Reset. + */ +#if !defined (MSI32_VALUE) +#define MSI32_VALUE 32000000U /*!< Value of the Internal oscillator in Hz*/ +#endif /* MSI32_VALUE */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) + #define HSI_VALUE 16000000U /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal High Speed oscillator (HSI48) value for USB FS and RNG. + * This internal oscillator is mainly dedicated to provide a high precision clock to + * the USB peripheral by means of a special Clock Recovery System (CRS) circuitry. + * When the CRS is not used, the HSI48 RC oscillator runs on it default frequency + * which is subject to manufacturing process variations. + */ +#if !defined (HSI48_VALUE) + #define HSI48_VALUE 48000000U /*!< Value of the Internal High Speed oscillator for USB FS/RNG in Hz. + The real value my vary depending on manufacturing process variations.*/ +#endif /* HSI48_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) + #define LSI_VALUE 32000U /*!< LSI Typical Value in Hz*/ +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz + The real value may vary depending on the variations + in voltage and temperature.*/ +/** + * @brief External Low Speed oscillator (LSE) value. + * This value is used by the UART, RTC HAL module to compute the system frequency + */ +#if !defined (LSE_VALUE) + #define LSE_VALUE 32768U /*!< Value of the External oscillator in Hz*/ +#endif /* LSE_VALUE */ + +#if !defined (LSE_STARTUP_TIMEOUT) + #define LSE_STARTUP_TIMEOUT 5000U /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ + +#define VDD_VALUE 3300U /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY (3U) /*!< tick interrupt priority (lowest by default) */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 0U +#define INSTRUCTION_CACHE_ENABLE 1U + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ + +/* #define USE_FULL_ASSERT 1U */ + +/* ################## Register callback feature configuration ############### */ +/** + * @brief Set below the peripheral configuration to "1U" to add the support + * of HAL callback registration/unregistration feature for the HAL + * driver(s). This allows user application to provide specific callback + * functions thanks to HAL_PPP_RegisterCallback() rather than overwriting + * the default weak callback functions (see each stm32n6xx_hal_ppp.h file + * for possible callback identifiers defined in HAL_PPP_CallbackIDTypeDef + * for each PPP peripheral). + */ +#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */ +#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */ +#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */ +#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */ +#define USE_HAL_IWDG_REGISTER_CALLBACKS 0U /* IWDG register callback disabled */ +#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U /* IRDA register callback disabled */ +#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */ +#define USE_HAL_LCD_REGISTER_CALLBACKS 0U /* LCD register callback disabled */ +#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */ +#define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */ +#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */ +#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U /* SMARTCARD register callback disabled */ +#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */ +#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */ +#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */ +#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */ +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */ + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED +#include "stm32u0xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED +#include "stm32u0xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED +#include "stm32u0xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED +#include "stm32u0xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED +#include "stm32u0xx_hal_adc.h" +#include "stm32u0xx_hal_adc_ex.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_COMP_MODULE_ENABLED +#include "stm32u0xx_hal_comp.h" +#endif /* HAL_COMP_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED +#include "stm32u0xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRS_MODULE_ENABLED +#include "stm32u0xx_ll_crs.h" +#endif /* HAL_CRS_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED +#include "stm32u0xx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED +#include "stm32u0xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_EXTI_MODULE_ENABLED +#include "stm32u0xx_hal_exti.h" +#endif /* HAL_EXTI_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED +#include "stm32u0xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED +#include "stm32u0xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED +#include "stm32u0xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_LPTIM_MODULE_ENABLED +#include "stm32u0xx_hal_lptim.h" +#endif /* HAL_LPTIM_MODULE_ENABLED */ + +#ifdef HAL_LCD_MODULE_ENABLED +#include "stm32u0xx_hal_lcd.h" +#endif /* HAL_LTDC_MODULE_ENABLED */ + +#ifdef HAL_OPAMP_MODULE_ENABLED +#include "stm32u0xx_hal_opamp.h" +#endif /* HAL_OPAMP_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED +#include "stm32u0xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED +#include "stm32u0xx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED +#include "stm32u0xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED +#include "stm32u0xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED +#include "stm32u0xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_TSC_MODULE_ENABLED +#include "stm32u0xx_ll_system.h" +#include "stm32u0xx_hal_tsc.h" +#endif /* HAL_TSC_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED +#include "stm32u0xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED +#include "stm32u0xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED +#include "stm32u0xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED +#include "stm32u0xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED +#include "stm32u0xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_LCD_MODULE_ENABLED +#include "stm32u0xx_hal_lcd.h" +#endif /* HAL_LCD_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED +#include "stm32u0xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ + #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ + void assert_failed(uint8_t *file, uint32_t line); +#else + #define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32U0xx_HAL_CONF_H */ diff --git a/esubghz_chat/application.fam b/esubghz_chat/application.fam index 6ea87cf4519..4fe5489e3a9 100644 --- a/esubghz_chat/application.fam +++ b/esubghz_chat/application.fam @@ -7,9 +7,10 @@ App( "gui", "subghz", ], - stack_size=8 * 1024, + stack_size=7 * 1024, fap_category="Sub-GHz", fap_libs=["mbedtls"], + fap_private_libs=[Lib(name="nfclegacy"), Lib(name="parity")], fap_icon="assets/chat_10px.png", fap_icon_assets="assets", fap_icon_assets_symbol="esubghz_chat", diff --git a/esubghz_chat/assets/NFC_manual_60x50.png b/esubghz_chat/assets/NFC_manual_60x50.png new file mode 100644 index 00000000000..787c0bcfe01 Binary files /dev/null and b/esubghz_chat/assets/NFC_manual_60x50.png differ diff --git a/esubghz_chat/assets/Pin_back_arrow_10x8.png b/esubghz_chat/assets/Pin_back_arrow_10x8.png new file mode 100644 index 00000000000..3bafabd1448 Binary files /dev/null and b/esubghz_chat/assets/Pin_back_arrow_10x8.png differ diff --git a/esubghz_chat/assets/WarningDolphin_45x42.png b/esubghz_chat/assets/WarningDolphin_45x42.png new file mode 100644 index 00000000000..d766ffbb444 Binary files /dev/null and b/esubghz_chat/assets/WarningDolphin_45x42.png differ diff --git a/esubghz_chat/esubghz_chat.c b/esubghz_chat/esubghz_chat.c index cf490463935..d84aa416819 100644 --- a/esubghz_chat/esubghz_chat.c +++ b/esubghz_chat/esubghz_chat.c @@ -547,6 +547,15 @@ static void chat_box_free(ESubGhzChatState* state) { } int32_t esubghz_chat(const char* args) { + if(furi_hal_nfc_is_hal_ready() != FuriHalNfcErrorNone) { + printf("NFC chip failed to start\r\n"); + return -1; + } + + furi_hal_nfc_acquire(); + furi_hal_nfc_low_power_mode_start(); + furi_hal_nfc_release(); + furry_hal_nfc_init(); /* init the crypto system */ crypto_init(); @@ -610,16 +619,20 @@ int32_t esubghz_chat(const char* args) { goto err_alloc_worker; } - // state->nfc_worker = nfc_worker_alloc(); - // if(state->nfc_worker == NULL) { - // goto err_alloc_nworker; - // } + NfcDevice* nfcdevic = nfc_device_alloc(); + state->nfc_dev_data = &nfcdevic->dev_data; + + state->nfc_worker = nfc_worker_alloc(); + if(state->nfc_worker == NULL) { + goto err_alloc_nworker; + } + + /*state->nfc_dev_data = malloc(sizeof(NfcDeviceData)); + if(state->nfc_dev_data == NULL) { + goto err_alloc_ndevdata; + }*/ - // state->nfc_dev_data = malloc(sizeof(NfcDeviceData)); - // if(state->nfc_dev_data == NULL) { - // goto err_alloc_ndevdata; - // } - // memset(state->nfc_dev_data, 0, sizeof(NfcDeviceData)); + //memset(state->nfc_dev_data, 0, sizeof(NfcDeviceData)); state->crypto_ctx = crypto_ctx_alloc(); if(state->crypto_ctx == NULL) { @@ -715,7 +728,7 @@ int32_t esubghz_chat(const char* args) { } /* if it is running, stop the NFC worker */ - // nfc_worker_stop(state->nfc_worker); + nfc_worker_stop(state->nfc_worker); err = 0; @@ -740,10 +753,12 @@ int32_t esubghz_chat(const char* args) { crypto_ctx_clear(state->crypto_ctx); /* clear nfc data */ - // if(state->nfc_dev_data->parsed_data != NULL) { - // furi_string_free(state->nfc_dev_data->parsed_data); - // } - // crypto_explicit_bzero(state->nfc_dev_data, sizeof(NfcDeviceData)); + if(state->nfc_dev_data->parsed_data != NULL) { + furi_string_free(state->nfc_dev_data->parsed_data); + } + + //nfc_device_data_clear(state->nfc_dev_data); + crypto_explicit_bzero(state->nfc_dev_data, sizeof(NfcDeviceData)); /* deinit devices */ radio_device_loader_end(state->subghz_device); @@ -758,12 +773,14 @@ int32_t esubghz_chat(const char* args) { crypto_ctx_free(state->crypto_ctx); err_alloc_crypto: - // free(state->nfc_dev_data); + //free(state->nfc_dev_data); + + //err_alloc_ndevdata: + nfc_worker_free(state->nfc_worker); - // err_alloc_ndevdata: - // nfc_worker_free(state->nfc_worker); + nfc_device_free(nfcdevic); - // err_alloc_nworker: +err_alloc_nworker: subghz_tx_rx_worker_free(state->subghz_worker); err_alloc_worker: @@ -803,5 +820,12 @@ int32_t esubghz_chat(const char* args) { FURI_LOG_I(APPLICATION_NAME, "Clean exit."); } + furry_hal_nfc_deinit(); + + // + furi_hal_nfc_acquire(); + furi_hal_nfc_low_power_mode_start(); + furi_hal_nfc_release(); + return err; } diff --git a/esubghz_chat/esubghz_chat_i.h b/esubghz_chat/esubghz_chat_i.h index e79ffe5f80f..7098da5d554 100644 --- a/esubghz_chat/esubghz_chat_i.h +++ b/esubghz_chat/esubghz_chat_i.h @@ -19,7 +19,7 @@ #include "esubghz_chat_icons.h" -#include +#include #define APPLICATION_NAME "ESubGhzChat" @@ -58,8 +58,8 @@ typedef struct { const SubGhzDevice* subghz_device; // for NFC - // NfcWorker* nfc_worker; - // NfcDeviceData* nfc_dev_data; + NfcWorker* nfc_worker; + NfcDeviceData* nfc_dev_data; // message assembly before TX FuriString* name_prefix; @@ -100,7 +100,7 @@ typedef enum { ESubGhzChatEvent_KeyMenuPassword, ESubGhzChatEvent_KeyMenuHexKey, ESubGhzChatEvent_KeyMenuGenKey, - // ESubGhzChatEvent_KeyMenuReadKeyFromNfc, + ESubGhzChatEvent_KeyMenuReadKeyFromNfc, ESubGhzChatEvent_KeyReadPopupFailed, ESubGhzChatEvent_KeyReadPopupSucceeded, ESubGhzChatEvent_PassEntered, diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_analogConfig.h b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_analogConfig.h new file mode 100644 index 00000000000..a2254960615 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_analogConfig.h @@ -0,0 +1,435 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_AnalogConfig.h + * + * \author bkam + * + * \brief RF Chip Analog Configuration Settings + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-HAL + * \brief RFAL Hardware Abstraction Layer + * @{ + * + * \addtogroup AnalogConfig + * \brief RFAL Analog Config Module + * @{ + * + */ + +#ifndef RFAL_ANALOG_CONFIG_H +#define RFAL_ANALOG_CONFIG_H + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "../platform.h" +#include "../st_errno.h" +#include "rfal_rf.h" + +/* + ****************************************************************************** + * DEFINES + ****************************************************************************** + */ + +#define RFAL_ANALOG_CONFIG_LUT_SIZE \ + (87U) /*!< Maximum number of Configuration IDs in the Loop Up Table */ +#define RFAL_ANALOG_CONFIG_LUT_NOT_FOUND \ + (0xFFU) /*!< Index value indicating no Configuration IDs found */ + +#define RFAL_ANALOG_CONFIG_TBL_SIZE \ + (1024U) /*!< Maximum number of Register-Mask-Value in the Setting List */ + +#define RFAL_ANALOG_CONFIG_POLL_LISTEN_MODE_MASK \ + (0x8000U) /*!< Mask bit of Poll Mode in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_TECH_MASK \ + (0x7F00U) /*!< Mask bits for Technology in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_BITRATE_MASK \ + (0x00F0U) /*!< Mask bits for Bit rate in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_DIRECTION_MASK \ + (0x000FU) /*!< Mask bits for Direction in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_CHIP_SPECIFIC_MASK \ + (0x00FFU) /*!< Mask bits for Chip Specific Technology */ + +#define RFAL_ANALOG_CONFIG_POLL_LISTEN_MODE_SHIFT \ + (15U) /*!< Shift value of Poll Mode in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_TECH_SHIFT \ + (8U) /*!< Shift value for Technology in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_BITRATE_SHIFT \ + (4U) /*!< Shift value for Technology in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_DIRECTION_SHIFT \ + (0U) /*!< Shift value for Direction in Analog Configuration ID */ + +#define RFAL_ANALOG_CONFIG_POLL \ + (0x0000U) /*!< Poll Mode bit setting in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_LISTEN \ + (0x8000U) /*!< Listen Mode bit setting in Analog Configuration ID */ + +#define RFAL_ANALOG_CONFIG_TECH_CHIP \ + (0x0000U) /*!< Chip-Specific bit setting in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_TECH_NFCA \ + (0x0100U) /*!< NFC-A Technology bits setting in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_TECH_NFCB \ + (0x0200U) /*!< NFC-B Technology bits setting in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_TECH_NFCF \ + (0x0400U) /*!< NFC-F Technology bits setting in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_TECH_AP2P \ + (0x0800U) /*!< AP2P Technology bits setting in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_TECH_NFCV \ + (0x1000U) /*!< NFC-V Technology bits setting in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_TECH_RFU (0x2000U) /*!< RFU for Technology bits */ + +#define RFAL_ANALOG_CONFIG_BITRATE_COMMON \ + (0x0000U) /*!< Common settings for all bit rates in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_BITRATE_106 \ + (0x0010U) /*!< 106kbits/s settings in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_BITRATE_212 \ + (0x0020U) /*!< 212kbits/s settings in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_BITRATE_424 \ + (0x0030U) /*!< 424kbits/s settings in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_BITRATE_848 \ + (0x0040U) /*!< 848kbits/s settings in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_BITRATE_1695 \ + (0x0050U) /*!< 1695kbits/s settings in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_BITRATE_3390 \ + (0x0060U) /*!< 3390kbits/s settings in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_BITRATE_6780 \ + (0x0070U) /*!< 6780kbits/s settings in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_BITRATE_1OF4 \ + (0x00C0U) /*!< 1 out of 4 for NFC-V setting in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_BITRATE_1OF256 \ + (0x00D0U) /*!< 1 out of 256 for NFC-V setting in Analog Configuration ID */ + +#define RFAL_ANALOG_CONFIG_NO_DIRECTION \ + (0x0000U) /*!< No direction setting in Analog Conf ID (Chip Specific only) */ +#define RFAL_ANALOG_CONFIG_TX \ + (0x0001U) /*!< Transmission bit setting in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_RX \ + (0x0002U) /*!< Reception bit setting in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_ANTICOL \ + (0x0003U) /*!< Anticollision setting in Analog Configuration ID */ +#define RFAL_ANALOG_CONFIG_DPO \ + (0x0004U) /*!< DPO setting in Analog Configuration ID */ + +#define RFAL_ANALOG_CONFIG_CHIP_INIT \ + (0x0000U) /*!< Chip-Specific event: Startup;Reset;Initialize */ +#define RFAL_ANALOG_CONFIG_CHIP_DEINIT \ + (0x0001U) /*!< Chip-Specific event: Deinitialize */ +#define RFAL_ANALOG_CONFIG_CHIP_FIELD_ON \ + (0x0002U) /*!< Chip-Specific event: Field On */ +#define RFAL_ANALOG_CONFIG_CHIP_FIELD_OFF \ + (0x0003U) /*!< Chip-Specific event: Field Off */ +#define RFAL_ANALOG_CONFIG_CHIP_WAKEUP_ON \ + (0x0004U) /*!< Chip-Specific event: Wake-up On */ +#define RFAL_ANALOG_CONFIG_CHIP_WAKEUP_OFF \ + (0x0005U) /*!< Chip-Specific event: Wake-up Off */ +#define RFAL_ANALOG_CONFIG_CHIP_LISTEN_ON \ + (0x0006U) /*!< Chip-Specific event: Listen On */ +#define RFAL_ANALOG_CONFIG_CHIP_LISTEN_OFF \ + (0x0007U) /*!< Chip-Specific event: Listen Off */ +#define RFAL_ANALOG_CONFIG_CHIP_POLL_COMMON \ + (0x0008U) /*!< Chip-Specific event: Poll common */ +#define RFAL_ANALOG_CONFIG_CHIP_LISTEN_COMMON \ + (0x0009U) /*!< Chip-Specific event: Listen common */ +#define RFAL_ANALOG_CONFIG_CHIP_LOWPOWER_ON \ + (0x000AU) /*!< Chip-Specific event: Low Power On */ +#define RFAL_ANALOG_CONFIG_CHIP_LOWPOWER_OFF \ + (0x000BU) /*!< Chip-Specific event: Low Power Off */ + +#define RFAL_ANALOG_CONFIG_UPDATE_LAST \ + (0x00U) /*!< Value indicating Last configuration set during update */ +#define RFAL_ANALOG_CONFIG_UPDATE_MORE \ + (0x01U) /*!< Value indicating More configuration set coming during update */ + +/* + ****************************************************************************** + * GLOBAL MACROS + ****************************************************************************** + */ + +#define RFAL_ANALOG_CONFIG_ID_GET_POLL_LISTEN(id) \ + (RFAL_ANALOG_CONFIG_POLL_LISTEN_MODE_MASK & (id)) /*!< Check if id indicates Listen mode */ + +#define RFAL_ANALOG_CONFIG_ID_GET_TECH(id) \ + (RFAL_ANALOG_CONFIG_TECH_MASK & (id)) /*!< Get the technology of Configuration ID */ +#define RFAL_ANALOG_CONFIG_ID_IS_CHIP(id) \ + (RFAL_ANALOG_CONFIG_TECH_MASK & (id)) /*!< Check if ID indicates Chip-specific */ +#define RFAL_ANALOG_CONFIG_ID_IS_NFCA(id) \ + (RFAL_ANALOG_CONFIG_TECH_NFCA & (id)) /*!< Check if ID indicates NFC-A */ +#define RFAL_ANALOG_CONFIG_ID_IS_NFCB(id) \ + (RFAL_ANALOG_CONFIG_TECH_NFCB & (id)) /*!< Check if ID indicates NFC-B */ +#define RFAL_ANALOG_CONFIG_ID_IS_NFCF(id) \ + (RFAL_ANALOG_CONFIG_TECH_NFCF & (id)) /*!< Check if ID indicates NFC-F */ +#define RFAL_ANALOG_CONFIG_ID_IS_AP2P(id) \ + (RFAL_ANALOG_CONFIG_TECH_AP2P & (id)) /*!< Check if ID indicates AP2P */ +#define RFAL_ANALOG_CONFIG_ID_IS_NFCV(id) \ + (RFAL_ANALOG_CONFIG_TECH_NFCV & (id)) /*!< Check if ID indicates NFC-V */ + +#define RFAL_ANALOG_CONFIG_ID_GET_BITRATE(id) \ + (RFAL_ANALOG_CONFIG_BITRATE_MASK & (id)) /*!< Get Bitrate of Configuration ID */ +#define RFAL_ANALOG_CONFIG_ID_IS_COMMON(id) \ + (RFAL_ANALOG_CONFIG_BITRATE_MASK & (id)) /*!< Check if ID indicates common bitrate */ +#define RFAL_ANALOG_CONFIG_ID_IS_106(id) \ + (RFAL_ANALOG_CONFIG_BITRATE_106 & (id)) /*!< Check if ID indicates 106kbits/s */ +#define RFAL_ANALOG_CONFIG_ID_IS_212(id) \ + (RFAL_ANALOG_CONFIG_BITRATE_212 & (id)) /*!< Check if ID indicates 212kbits/s */ +#define RFAL_ANALOG_CONFIG_ID_IS_424(id) \ + (RFAL_ANALOG_CONFIG_BITRATE_424 & (id)) /*!< Check if ID indicates 424kbits/s */ +#define RFAL_ANALOG_CONFIG_ID_IS_848(id) \ + (RFAL_ANALOG_CONFIG_BITRATE_848 & (id)) /*!< Check if ID indicates 848kbits/s */ +#define RFAL_ANALOG_CONFIG_ID_IS_1695(id) \ + (RFAL_ANALOG_CONFIG_BITRATE_1695 & (id)) /*!< Check if ID indicates 1695kbits/s */ +#define RFAL_ANALOG_CONFIG_ID_IS_3390(id) \ + (RFAL_ANALOG_CONFIG_BITRATE_3390 & (id)) /*!< Check if ID indicates 3390kbits/s */ +#define RFAL_ANALOG_CONFIG_ID_IS_6780(id) \ + (RFAL_ANALOG_CONFIG_BITRATE_6780 & (id)) /*!< Check if ID indicates 6780kbits/s */ +#define RFAL_ANALOG_CONFIG_ID_IS_1OF4(id) \ + (RFAL_ANALOG_CONFIG_BITRATE_1OF4 & (id)) /*!< Check if ID indicates 1 out of 4 bitrate */ +#define RFAL_ANALOG_CONFIG_ID_IS_1OF256(id) \ + (RFAL_ANALOG_CONFIG_BITRATE_1OF256 & (id)) /*!< Check if ID indicates 1 out of 256 bitrate */ + +#define RFAL_ANALOG_CONFIG_ID_GET_DIRECTION(id) \ + (RFAL_ANALOG_CONFIG_DIRECTION_MASK & (id)) /*!< Get Direction of Configuration ID */ +#define RFAL_ANALOG_CONFIG_ID_IS_TX(id) \ + (RFAL_ANALOG_CONFIG_TX & (id)) /*!< Check if id indicates TX */ +#define RFAL_ANALOG_CONFIG_ID_IS_RX(id) \ + (RFAL_ANALOG_CONFIG_RX & (id)) /*!< Check if id indicates RX */ + +#define RFAL_ANALOG_CONFIG_CONFIG_NUM(x) \ + (sizeof(x) / sizeof((x)[0])) /*!< Get Analog Config number */ + +/*! Set Analog Config ID value by: Mode, Technology, Bitrate and Direction */ +#define RFAL_ANALOG_CONFIG_ID_SET(mode, tech, br, direction) \ + (RFAL_ANALOG_CONFIG_ID_GET_POLL_LISTEN(mode) | RFAL_ANALOG_CONFIG_ID_GET_TECH(tech) | \ + RFAL_ANALOG_CONFIG_ID_GET_BITRATE(br) | RFAL_ANALOG_CONFIG_ID_GET_DIRECTION(direction)) + +/* + ****************************************************************************** + * GLOBAL DATA TYPES + ****************************************************************************** + */ + +typedef uint8_t + rfalAnalogConfigMode; /*!< Polling or Listening Mode of Configuration */ +typedef uint8_t + rfalAnalogConfigTech; /*!< Technology of Configuration */ +typedef uint8_t + rfalAnalogConfigBitrate; /*!< Bitrate of Configuration */ +typedef uint8_t + rfalAnalogConfigDirection; /*!< Transmit/Receive direction of Configuration */ + +typedef uint8_t + rfalAnalogConfigRegAddr[2]; /*!< Register Address to ST Chip */ +typedef uint8_t + rfalAnalogConfigRegMask; /*!< Register Mask Value */ +typedef uint8_t + rfalAnalogConfigRegVal; /*!< Register Value */ + +typedef uint16_t + rfalAnalogConfigId; /*!< Analog Configuration ID */ +typedef uint16_t + rfalAnalogConfigOffset; /*!< Analog Configuration offset address in the table */ +typedef uint8_t + rfalAnalogConfigNum; /*!< Number of Analog settings for the respective Configuration ID */ + +/*! Struct that contain the Register-Mask-Value set. Make sure that the whole structure size is even and unaligned! */ +typedef struct { + rfalAnalogConfigRegAddr addr; /*!< Register Address */ + rfalAnalogConfigRegMask mask; /*!< Register Mask Value */ + rfalAnalogConfigRegVal val; /*!< Register Value */ +} rfalAnalogConfigRegAddrMaskVal; + +/*! Struct that represents the Analog Configs */ +typedef struct { + uint8_t id[sizeof(rfalAnalogConfigId)]; /*!< Configuration ID */ + rfalAnalogConfigNum num; /*!< Number of Config Sets to follow */ + rfalAnalogConfigRegAddrMaskVal regSet[]; + /*!< Register-Mask-Value sets */ /* PRQA S 1060 # MISRA 18.7 - Flexible Array Members are the only meaningful way of denoting a variable length input buffer which follows a fixed header structure. */ +} rfalAnalogConfig; + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +/*! + ***************************************************************************** + * \brief Initialize the Analog Configuration + * + * Reset the Analog Configuration LUT pointer to reference to default settings. + * + ***************************************************************************** + */ +void rfalAnalogConfigInitialize(void); + +/*! + ***************************************************************************** + * \brief Indicate if the current Analog Configuration Table is complete and ready to be used. + * + * \return true if current Analog Configuration Table is complete and ready to be used. + * \return false if current Analog Configuration Table is incomplete + * + ***************************************************************************** + */ +bool rfalAnalogConfigIsReady(void); + +/*! + ***************************************************************************** + * \brief Write the whole Analog Configuration table in raw format + * + * Writes the Analog Configuration and Look Up Table with the given raw table + * + * NOTE: Function does not check the validity of the given Table contents + * + * \param[in] configTbl: location of config Table to be loaded + * \param[in] configTblSize: size of the config Table to be loaded + * + * \return ERR_NONE : if setting is updated + * \return ERR_PARAM : if configTbl is invalid + * \return ERR_NOMEM : if the given Table is bigger exceeds the max size + * \return ERR_REQUEST : if the update Configuration Id is disabled + * + ***************************************************************************** + */ +ReturnCode rfalAnalogConfigListWriteRaw(const uint8_t* configTbl, uint16_t configTblSize); + +/*! + ***************************************************************************** + * \brief Write the Analog Configuration table with new analog settings. + * + * Writes the Analog Configuration and Look Up Table with the new list of register-mask-value + * and Configuration ID respectively. + * + * NOTE: Function does not check for the validity of the Register Address. + * + * \param[in] more: 0x00 indicates it is last Configuration ID settings; + * 0x01 indicates more Configuration ID setting(s) are coming. + * \param[in] *config: reference to the configuration list of current Configuration ID. + * + * \return ERR_PARAM : if Configuration ID or parameter is invalid + * \return ERR_NOMEM : if LUT is full + * \return ERR_REQUEST : if the update Configuration Id is disabled + * \return ERR_NONE : if setting is updated + * + ***************************************************************************** + */ +ReturnCode rfalAnalogConfigListWrite(uint8_t more, const rfalAnalogConfig* config); + +/*! + ***************************************************************************** + * \brief Read the whole Analog Configuration table in raw format + * + * Reads the whole Analog Configuration Table in raw format + * + * \param[out] tblBuf: location to the buffer to place the Config Table + * \param[in] tblBufLen: length of the buffer to place the Config Table + * \param[out] configTblSize: Config Table size + * + * \return ERR_PARAM : if configTbl or configTblSize is invalid + * \return ERR_NOMEM : if configTblSize is not enough for the whole table + * \return ERR_NONE : if read is successful + * + ***************************************************************************** + */ +ReturnCode + rfalAnalogConfigListReadRaw(uint8_t* tblBuf, uint16_t tblBufLen, uint16_t* configTblSize); + +/*! + ***************************************************************************** + * \brief Read the Analog Configuration table. + * + * Read the Analog Configuration Table + * + * \param[in] configOffset: offset to the next Configuration ID in the List Table to be read. + * \param[out] more: 0x00 indicates it is last Configuration ID settings; + * 0x01 indicates more Configuration ID setting(s) are coming. + * \param[out] config: configuration id, number of configuration sets and register-mask-value sets + * \param[in] numConfig: the remaining configuration settings space available; + * + * \return ERR_NOMEM : if number of Configuration for respective Configuration ID is greater the the remaining configuration setting space available + * \return ERR_NONE : if read is successful + * + ***************************************************************************** + */ +ReturnCode rfalAnalogConfigListRead( + rfalAnalogConfigOffset* configOffset, + uint8_t* more, + rfalAnalogConfig* config, + rfalAnalogConfigNum numConfig); + +/*! + ***************************************************************************** + * \brief Set the Analog settings of indicated Configuration ID. + * + * Update the chip with indicated analog settings of indicated Configuration ID. + * + * \param[in] configId: configuration ID + * + * \return ERR_PARAM if Configuration ID is invalid + * \return ERR_INTERNAL if error updating setting to chip + * \return ERR_NONE if new settings is applied to chip + * + ***************************************************************************** + */ +ReturnCode rfalSetAnalogConfig(rfalAnalogConfigId configId); + +/*! + ***************************************************************************** + * \brief Generates Analog Config mode ID + * + * Converts RFAL mode and bitrate into Analog Config Mode ID. + * + * Update the chip with indicated analog settings of indicated Configuration ID. + * + * \param[in] md: RFAL mode format + * \param[in] br: RFAL bit rate format + * \param[in] dir: Analog Config communication direction + * + * \return Analog Config Mode ID + * + ***************************************************************************** + */ +uint16_t rfalAnalogConfigGenModeID(rfalMode md, rfalBitRate br, uint16_t dir); + +#endif /* RFAL_ANALOG_CONFIG_H */ + +/** + * @} + * + * @} + * + * @} + */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_chip.h b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_chip.h new file mode 100644 index 00000000000..e5f2dd65524 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_chip.h @@ -0,0 +1,287 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_chip.h + * + * \author Gustavo Patricio + * + * \brief RF Chip specific Layer + * + * \warning This layer, which provides direct access to RF chip, should + * only be used for debug purposes and/or advanced features + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-HAL + * \brief RFAL Hardware Abstraction Layer + * @{ + * + * \addtogroup Chip + * \brief RFAL RF Chip Module + * @{ + * + */ + +#ifndef RFAL_CHIP_H +#define RFAL_CHIP_H + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ +#include "../platform.h" +#include "../st_errno.h" +#include "rfal_rf.h" + +/***************************************************************************** + * RF Chip * + *****************************************************************************/ + +/*! + ***************************************************************************** + * \brief Writes a register on the RF Chip + * + * Checks if the given register is valid and if so, writes the value(s) + * on the RF Chip register + * + * \param[in] reg: register address to be written, or the first if len > 1 + * \param[in] values: pointer with content to be written on the register(s) + * \param[in] len: number of consecutive registers to be written + * + * + * \return ERR_PARAM : Invalid register or bad request + * \return ERR_NOTSUPP : Feature not supported + * \return ERR_NONE : Write done with no error + ***************************************************************************** + */ +ReturnCode rfalChipWriteReg(uint16_t reg, const uint8_t* values, uint8_t len); + +/*! + ***************************************************************************** + * \brief Reads a register on the RF Chip + * + * Checks if the given register is valid and if so, reads the value(s) + * of the RF Chip register(s) + * + * \param[in] reg: register address to be read, or the first if len > 1 + * \param[out] values: pointer where the register(s) read content will be placed + * \param[in] len: number of consecutive registers to be read + * + * \return ERR_PARAM : Invalid register or bad request + * \return ERR_NOTSUPP : Feature not supported + * \return ERR_NONE : Read done with no error + ***************************************************************************** + */ +ReturnCode rfalChipReadReg(uint16_t reg, uint8_t* values, uint8_t len); + +/*! + ***************************************************************************** + * \brief Change a register on the RF Chip + * + * Change the value of the register bits on the RF Chip Test set in the valueMask. + * + * \param[in] reg: register address to be modified + * \param[in] valueMask: mask value of the register bits to be changed + * \param[in] value: register value to be set + * + * \return ERR_PARAM : Invalid register or bad request + * \return ERR_NOTSUPP : Feature not supported + * \return ERR_OK : Change done with no error + ***************************************************************************** + */ +ReturnCode rfalChipChangeRegBits(uint16_t reg, uint8_t valueMask, uint8_t value); + +/*! + ***************************************************************************** + * \brief Writes a Test register on the RF Chip + * + * Writes the value on the RF Chip Test register + * + * \param[in] reg: register address to be written + * \param[in] value: value to be written on the register + * + * + * \return ERR_PARAM : Invalid register or bad request + * \return ERR_NOTSUPP : Feature not supported + * \return ERR_NONE : Write done with no error + ***************************************************************************** + */ +ReturnCode rfalChipWriteTestReg(uint16_t reg, uint8_t value); + +/*! + ***************************************************************************** + * \brief Reads a Test register on the RF Chip + * + * Reads the value of the RF Chip Test register + * + * \param[in] reg: register address to be read + * \param[out] value: pointer where the register content will be placed + * + * \return ERR_PARAM :Invalid register or bad request + * \return ERR_NOTSUPP : Feature not supported + * \return ERR_NONE : Read done with no error + ***************************************************************************** + */ +ReturnCode rfalChipReadTestReg(uint16_t reg, uint8_t* value); + +/*! + ***************************************************************************** + * \brief Change a Test register on the RF Chip + * + * Change the value of the register bits on the RF Chip Test set in the valueMask. + * + * \param[in] reg: test register address to be modified + * \param[in] valueMask: mask value of the register bits to be changed + * \param[in] value: register value to be set + * + * \return ERR_PARAM : Invalid register or bad request + * \return ERR_NOTSUPP : Feature not supported + * \return ERR_OK : Change done with no error + ***************************************************************************** + */ +ReturnCode rfalChipChangeTestRegBits(uint16_t reg, uint8_t valueMask, uint8_t value); + +/*! + ***************************************************************************** + * \brief Execute command on the RF Chip + * + * Checks if the given command is valid and if so, executes it on + * the RF Chip + * + * \param[in] cmd: direct command to be executed + * + * \return ERR_PARAM : Invalid command or bad request + * \return ERR_NOTSUPP : Feature not supported + * \return ERR_NONE : Direct command executed with no error + ***************************************************************************** + */ +ReturnCode rfalChipExecCmd(uint16_t cmd); + +/*! + ***************************************************************************** + * \brief Set RFO + * + * Sets the RFO value to be used when the field is on (unmodulated/active) + * + * \param[in] rfo : the RFO value to be used + * + * \return ERR_IO : Internal error + * \return ERR_NOTSUPP : Feature not supported + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalChipSetRFO(uint8_t rfo); + +/*! + ***************************************************************************** + * \brief Get RFO + * + * Gets the RFO value used used when the field is on (unmodulated/active) + * + * \param[out] result : the current RFO value + * + * \return ERR_IO : Internal error + * \return ERR_NOTSUPP : Feature not supported + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalChipGetRFO(uint8_t* result); + +/*! + ***************************************************************************** + * \brief Measure Amplitude + * + * Measures the RF Amplitude + * + * \param[out] result : result of RF measurement + * + * \return ERR_IO : Internal error + * \return ERR_NOTSUPP : Feature not supported + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalChipMeasureAmplitude(uint8_t* result); + +/*! + ***************************************************************************** + * \brief Measure Phase + * + * Measures the Phase + * + * \param[out] result : result of Phase measurement + * + * \return ERR_IO : Internal error + * \return ERR_NOTSUPP : Feature not supported + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalChipMeasurePhase(uint8_t* result); + +/*! + ***************************************************************************** + * \brief Measure Capacitance + * + * Measures the Capacitance + * + * \param[out] result : result of Capacitance measurement + * + * \return ERR_IO : Internal error + * \return ERR_NOTSUPP : Feature not supported + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalChipMeasureCapacitance(uint8_t* result); + +/*! + ***************************************************************************** + * \brief Measure Power Supply + * + * Measures the Power Supply + * + * \param[in] param : measurement parameter (chip specific) + * \param[out] result : result of the measurement + * + * \return ERR_IO : Internal error + * \return ERR_NOTSUPP : Feature not supported + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalChipMeasurePowerSupply(uint8_t param, uint8_t* result); + +#endif /* RFAL_CHIP_H */ + +/** + * @} + * + * @} + * + * @} + */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_crc.h b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_crc.h new file mode 100644 index 00000000000..a962761b9e4 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_crc.h @@ -0,0 +1,74 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_crc.h + * + * \author Ulrich Herrmann + * + * \brief CRC calculation module + * + */ +/*! + * + */ + +#ifndef RFAL_CRC_H_ +#define RFAL_CRC_H_ + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ +#include "../platform.h" + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ +/*! + ***************************************************************************** + * \brief Calculate CRC according to CCITT standard. + * + * This function takes \a length bytes from \a buf and calculates the CRC + * for this data. The result is returned. + * \note This implementation calculates the CRC with LSB first, i.e. all + * bytes are "read" from right to left. + * + * \param[in] preloadValue : Initial value of CRC calculation. + * \param[in] buf : buffer to calculate the CRC for. + * \param[in] length : size of the buffer. + * + * \return 16 bit long crc value. + * + ***************************************************************************** + */ +extern uint16_t rfalCrcCalculateCcitt(uint16_t preloadValue, const uint8_t* buf, uint16_t length); + +#endif /* RFAL_CRC_H_ */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_dpo.h b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_dpo.h new file mode 100644 index 00000000000..a59fbc7e0ad --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_dpo.h @@ -0,0 +1,207 @@ + +/****************************************************************************** + * @attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * $Revision: $ + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_dpo.h + * + * \author Martin Zechleitner + * + * \brief Dynamic Power adjustment + * + * This module provides an interface to perform the power adjustment dynamically + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-HAL + * \brief RFAL Hardware Abstraction Layer + * @{ + * + * \addtogroup DPO + * \brief RFAL Dynamic Power Module + * @{ + * + */ + +#ifndef RFAL_DPO_H +#define RFAL_DPO_H + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "../platform.h" +#include "../st_errno.h" + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ + +#define RFAL_DPO_TABLE_SIZE_MAX 15U /*!< Max DPO table size */ +#define RFAL_DPO_TABLE_PARAMETER 3U /*!< DPO table Parameter length */ + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + +/*! DPO table entry struct */ +typedef struct { + uint8_t rfoRes; /*!< Setting for the resistance level of the RFO */ + uint8_t inc; /*!< Threshold for incrementing the output power */ + uint8_t dec; /*!< Threshold for decrementing the output power */ +} rfalDpoEntry; + +/*! Function pointer to method doing the reference measurement */ +typedef ReturnCode (*rfalDpoMeasureFunc)(uint8_t*); + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +/*! + ***************************************************************************** + * \brief Initialize dynamic power table + * + * This function sets the internal dynamic power table to the default + * values stored in rfal_DpoTbl.h + * + ***************************************************************************** + */ +void rfalDpoInitialize(void); + +/*! + ***************************************************************************** + * \brief Set the measurement method + * + * This function sets the measurement method used for reference measurement. + * Based on the measurement the power will then be adjusted + * + * \param[in] dpoMeasureFunc: callback of measurement function + * + ***************************************************************************** + */ +void rfalDpoSetMeasureCallback(rfalDpoMeasureFunc dpoMeasureFunc); + +/*! + ***************************************************************************** + * \brief Write dynamic power table + * + * Load the dynamic power table + * + * \param[in] powerTbl: location of power Table to be loaded + * \param[in] powerTblEntries: number of entries of the power Table to be loaded + * + * \return ERR_NONE : No error + * \return ERR_PARAM : if configTbl is invalid + * \return ERR_NOMEM : if the given Table is bigger exceeds the max size + ***************************************************************************** + */ +ReturnCode rfalDpoTableWrite(rfalDpoEntry* powerTbl, uint8_t powerTblEntries); + +/*! + ***************************************************************************** + * \brief Dynamic power table Read + * + * Read the dynamic power table + * + * \param[out] tblBuf: location to the rfalDpoEntry[] to place the Table + * \param[in] tblBufEntries: number of entries available in tblBuf to place the power Table + * \param[out] tableEntries: returned number of entries actually written into tblBuf + * + * \return ERR_NONE : No error + * \return ERR_PARAM : if configTbl is invalid or parameters are invalid + ***************************************************************************** + */ +ReturnCode rfalDpoTableRead(rfalDpoEntry* tblBuf, uint8_t tblBufEntries, uint8_t* tableEntries); + +/*! + ***************************************************************************** + * \brief Dynamic power adjust + * + * It measures the current output and adjusts the power accordingly to + * the dynamic power table + * + * \return ERR_NONE : No error + * \return ERR_PARAM : if configTbl is invalid or parameters are invalid + * \return ERR_WRONG_STATE : if the current state is valid for DPO Adjustment + ***************************************************************************** + */ +ReturnCode rfalDpoAdjust(void); + +/*! + ***************************************************************************** + * \brief Get Current Dynamic power table entry + * + * Return current used DPO power table entry settings + * + * \return ERR_NONE : Current DpoEntry. This includes d_res, inc and dec + * + ***************************************************************************** + */ +rfalDpoEntry* rfalDpoGetCurrentTableEntry(void); + +/*! + ***************************************************************************** + * \brief Dynamic power set enabled state + * + * \param[in] enable: new active state + * + * Set state to enable or disable the Dynamic power adjustment + * + ***************************************************************************** + */ +void rfalDpoSetEnabled(bool enable); + +/*! + ***************************************************************************** + * \brief Get the Dynamic power enabled state + * + * Get state of the Dynamic power adjustment + * + * \return true : enabled + * \return false : disabled + ***************************************************************************** + */ +bool rfalDpoIsEnabled(void); + +#endif /* RFAL_DPO_H */ + +/** + * @} + * + * @} + * + * @} + */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_iso15693_2.h b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_iso15693_2.h new file mode 100644 index 00000000000..844c58f6611 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_iso15693_2.h @@ -0,0 +1,206 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_iso15693_2.h + * + * \author Ulrich Herrmann + * + * \brief Implementation of ISO-15693-2 + * + */ +/*! + * + */ + +#ifndef RFAL_ISO_15693_2_H +#define RFAL_ISO_15693_2_H + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ +#include "../platform.h" +#include "../st_errno.h" + +/* +****************************************************************************** +* GLOBAL DATATYPES +****************************************************************************** +*/ +/*! Enum holding possible VCD codings */ +typedef enum { ISO15693_VCD_CODING_1_4, ISO15693_VCD_CODING_1_256 } iso15693VcdCoding_t; + +/*! Enum holding possible VICC datarates */ + +/*! Configuration parameter used by #iso15693PhyConfigure */ +typedef struct { + iso15693VcdCoding_t coding; /*!< desired VCD coding */ + uint32_t + speedMode; /*!< 0: normal mode, 1: 2^1 = x2 Fast mode, 2 : 2^2 = x4 mode, 3 : 2^3 = x8 mode - all rx pulse numbers and times are divided by 1,2,4,8 */ +} iso15693PhyConfig_t; + +/*! Parameters how the stream mode should work */ +struct iso15693StreamConfig { + uint8_t useBPSK; /*!< 0: subcarrier, 1:BPSK */ + uint8_t din; /*!< the divider for the in subcarrier frequency: fc/2^din */ + uint8_t dout; /*!< the divider for the in subcarrier frequency fc/2^dout */ + uint8_t report_period_length; /*!< the length of the reporting period 2^report_period_length*/ +}; +/* +****************************************************************************** +* GLOBAL CONSTANTS +****************************************************************************** +*/ + +#define ISO15693_REQ_FLAG_TWO_SUBCARRIERS \ + 0x01U /*!< Flag indication that communication uses two subcarriers */ +#define ISO15693_REQ_FLAG_HIGH_DATARATE \ + 0x02U /*!< Flag indication that communication uses high bitrate */ +#define ISO15693_MASK_FDT_LISTEN \ + (65) /*!< t1min = 308,2us = 4192/fc = 65.5 * 64/fc */ + +/*! t1max = 323,3us = 4384/fc = 68.5 * 64/fc + * 12 = 768/fc unmodulated time of single subcarrior SoF */ +#define ISO15693_FWT (69 + 12) + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ +/*! + ***************************************************************************** + * \brief Initialize the ISO15693 phy + * + * \param[in] config : ISO15693 phy related configuration (See #iso15693PhyConfig_t) + * \param[out] needed_stream_config : return a pointer to the stream config + * needed for this iso15693 config. To be used for configure RF chip. + * + * \return ERR_IO : Error during communication. + * \return ERR_NONE : No error. + * + ***************************************************************************** + */ +extern ReturnCode iso15693PhyConfigure( + const iso15693PhyConfig_t* config, + const struct iso15693StreamConfig** needed_stream_config); + +/*! + ***************************************************************************** + * \brief Return current phy configuration + * + * This function returns current Phy configuration previously + * set by #iso15693PhyConfigure + * + * \param[out] config : ISO15693 phy configuration. + * + * \return ERR_NONE : No error. + * + ***************************************************************************** + */ +extern ReturnCode iso15693PhyGetConfiguration(iso15693PhyConfig_t* config); + +/*! + ***************************************************************************** + * \brief Code an ISO15693 compatible frame + * + * This function takes \a length bytes from \a buffer, perform proper + * encoding and sends out the frame to the ST25R391x. + * + * \param[in] buffer : data to send, modified to adapt flags. + * \param[in] length : number of bytes to send. + * \param[in] sendCrc : If set to true, CRC is appended to the frame + * \param[in] sendFlags: If set to true, flag field is sent according to + * ISO15693. + * \param[in] picopassMode : If set to true, the coding will be according to Picopass + * \param[out] subbit_total_length : Return the complete bytes which need to + * be send for the current coding + * \param[in,out] offset : Set to 0 for first transfer, function will update it to + point to next byte to be coded + * \param[out] outbuf : buffer where the function will store the coded subbit stream + * \param[out] outBufSize : the size of the output buffer + * \param[out] actOutBufSize : the amount of data stored into the buffer at this call + * + * \return ERR_IO : Error during communication. + * \return ERR_AGAIN : Data was not coded all the way. Call function again with a new/emptied buffer + * \return ERR_NO_MEM : In case outBuf is not big enough. Needs to have at + least 5 bytes for 1of4 coding and 65 bytes for 1of256 coding + * \return ERR_NONE : No error. + * + ***************************************************************************** + */ +extern ReturnCode iso15693VCDCode( + uint8_t* buffer, + uint16_t length, + bool sendCrc, + bool sendFlags, + bool picopassMode, + uint16_t* subbit_total_length, + uint16_t* offset, + uint8_t* outbuf, + uint16_t outBufSize, + uint16_t* actOutBufSize); + +/*! + ***************************************************************************** + * \brief Receive an ISO15693 compatible frame + * + * This function receives an ISO15693 frame from the ST25R391x, decodes the frame + * and writes the raw data to \a buffer. + * \note Buffer needs to be big enough to hold CRC also (+2 bytes) + * + * \param[in] inBuf : buffer with the hamming coded stream to be decoded + * \param[in] inBufLen : number of bytes to decode (=length of buffer). + * \param[out] outBuf : buffer where received data shall be written to. + * \param[in] outBufLen : Length of output buffer, should be approx twice the size of inBuf + * \param[out] outBufPos : The number of decoded bytes. Could be used in + * extended implementation to allow multiple calls + * \param[out] bitsBeforeCol : in case of ERR_COLLISION this value holds the + * number of bits in the current byte where the collision happened. + * \param[in] ignoreBits : number of bits in the beginning where collisions will be ignored + * \param[in] picopassMode : if set to true, the decoding will be according to Picopass + * + * \return ERR_COLLISION : collision occurred, data incorrect + * \return ERR_CRC : CRC error, data incorrect + * \return ERR_TIMEOUT : timeout waiting for data. + * \return ERR_NONE : No error. + * + ***************************************************************************** + */ +extern ReturnCode iso15693VICCDecode( + const uint8_t* inBuf, + uint16_t inBufLen, + uint8_t* outBuf, + uint16_t outBufLen, + uint16_t* outBufPos, + uint16_t* bitsBeforeCol, + uint16_t ignoreBits, + bool picopassMode); + +#endif /* RFAL_ISO_15693_2_H */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_isoDep.h b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_isoDep.h new file mode 100644 index 00000000000..a0fec5db08e --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_isoDep.h @@ -0,0 +1,1092 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_isoDep.h + * + * \author Gustavo Patricio + * + * \brief Implementation of ISO-DEP protocol + * + * This implementation was based on the following specs: + * - ISO/IEC 14443-4 2nd Edition 2008-07-15 + * - NFC Forum Digital Protocol 1.1 2014-01-14 + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-AL + * \brief RFAL Abstraction Layer + * @{ + * + * \addtogroup ISO-DEP + * \brief RFAL ISO-DEP Module + * @{ + * + */ + +#ifndef RFAL_ISODEP_H_ +#define RFAL_ISODEP_H_ +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "../platform.h" +#include "rfal_nfcb.h" + +/* + ****************************************************************************** + * ENABLE SWITCH + ****************************************************************************** + */ + +#ifndef RFAL_FEATURE_ISO_DEP +#define RFAL_FEATURE_ISO_DEP \ + false /*!< ISO-DEP module configuration missing. Disabled by default */ +#endif + +/* If module is disabled remove the need for the user to set lengths */ +#if !RFAL_FEATURE_ISO_DEP +#undef RFAL_FEATURE_ISO_DEP_IBLOCK_MAX_LEN +#undef RFAL_FEATURE_ISO_DEP_APDU_MAX_LEN + +#define RFAL_FEATURE_ISO_DEP_IBLOCK_MAX_LEN (1U) /*!< ISO-DEP I-Block max length, set to "none" */ +#define RFAL_FEATURE_ISO_DEP_APDU_MAX_LEN (1U) /*!< ISO-DEP APDU max length, set to "none" */ +#endif /* !RFAL_FEATURE_NFC_DEP */ + +/* + ****************************************************************************** + * DEFINES + ****************************************************************************** + */ + +#define RFAL_ISODEP_PROLOGUE_SIZE \ + (3U) /*!< Length of Prologue Field for I-Block Format */ + +#define RFAL_ISODEP_PCB_LEN \ + (1U) /*!< PCB length */ +#define RFAL_ISODEP_DID_LEN \ + (1U) /*!< DID length */ +#define RFAL_ISODEP_NAD_LEN \ + (1U) /*!< NAD length */ +#define RFAL_ISODEP_NO_DID \ + (0x00U) /*!< DID value indicating the ISO-DEP layer not to use DID */ +#define RFAL_ISODEP_NO_NAD \ + (0xFFU) /*!< NAD value indicating the ISO-DEP layer not to use NAD */ + +#define RFAL_ISODEP_FWI_MASK \ + (0xF0U) /*!< Mask bits of FWI */ +#define RFAL_ISODEP_FWI_SHIFT \ + (4U) /*!< Shift val of FWI */ +#define RFAL_ISODEP_FWI_DEFAULT \ + (4U) /*!< Default value for FWI Digital 1.0 11.6.2.17 */ +#define RFAL_ISODEP_ADV_FEATURE \ + (0x0FU) /*!< Indicate 256 Bytes FSD and Advanc Proto Feature support:NAD & DID */ + +#define RFAL_ISODEP_DID_MAX \ + (14U) /*!< Maximum DID value */ + +#define RFAL_ISODEP_BRI_MASK \ + (0x07U) /*!< Mask bits for Poll to Listen Send bitrate */ +#define RFAL_ISODEP_BSI_MASK \ + (0x70U) /*!< Mask bits for Listen to Poll Send bitrate */ +#define RFAL_ISODEP_SAME_BITRATE_MASK \ + (0x80U) /*!< Mask bit indicate only same bit rate D for both direction support */ +#define RFAL_ISODEP_BITRATE_RFU_MASK \ + (0x08U) /*!< Mask bit for RFU */ + +/*! Maximum Frame Waiting Time = ((256 * 16/fc) * 2^FWImax) = ((256*16/fc)*2^14) = (67108864)/fc = 2^26 (1/fc) */ +#define RFAL_ISODEP_MAX_FWT ((uint32_t)1U << 26) + +#define RFAL_ISODEP_FSDI_DEFAULT \ + RFAL_ISODEP_FSXI_256 /*!< Default Frame Size Integer in Poll mode */ +#define RFAL_ISODEP_FSX_KEEP (0xFFU) /*!< Flag to keep FSX from activation */ +#define RFAL_ISODEP_DEFAULT_FSCI \ + RFAL_ISODEP_FSXI_256 /*!< FSCI default value to be used in Listen Mode */ +#define RFAL_ISODEP_DEFAULT_FSC \ + RFAL_ISODEP_FSX_256 /*!< FSC default value (aligned RFAL_ISODEP_DEFAULT_FSCI) */ +#define RFAL_ISODEP_DEFAULT_SFGI (0U) /*!< SFGI Default value to be used in Listen Mode */ +#define RFAL_ISODEP_DEFAULT_FWI (8U) /*!< Default Listener FWI (Max) Digital 2.0 B7 & B3 */ + +#define RFAL_ISODEP_APDU_MAX_LEN \ + RFAL_ISODEP_FSX_1024 /*!< Max APDU length */ + +#define RFAL_ISODEP_ATTRIB_RES_MBLI_NO_INFO \ + (0x00U) /*!< MBLI indicating no information on its internal input buffer size */ +#define RFAL_ISODEP_ATTRIB_REQ_PARAM1_DEFAULT \ + (0x00U) /*!< Default values of Param 1 of ATTRIB_REQ Digital 1.0 12.6.1.3-5 */ +#define RFAL_ISODEP_ATTRIB_HLINFO_LEN \ + (32U) /*!< Maximum Size of Higher Layer Information */ +#define RFAL_ISODEP_ATS_HB_MAX_LEN \ + (15U) /*!< Maximum length of Historical Bytes Digital 1.1 13.6.2.23 */ +#define RFAL_ISODEP_ATTRIB_REQ_MIN_LEN \ + (9U) /*!< Minimum Length of ATTRIB_REQ command */ +#define RFAL_ISODEP_ATTRIB_RES_MIN_LEN \ + (1U) /*!< Minimum Length of ATTRIB_RES response */ + +#define RFAL_ISODEP_SPARAM_VALUES_MAX_LEN \ + (16U) /*!< Maximum Length of the value field on S(PARAMETERS) */ +#define RFAL_ISODEP_SPARAM_TAG_BLOCKINFO \ + (0xA0U) /*!< S(PARAMETERS) tag Block information */ +#define RFAL_ISODEP_SPARAM_TAG_BRREQ \ + (0xA1U) /*!< S(PARAMETERS) tag Bit rates Request */ +#define RFAL_ISODEP_SPARAM_TAG_BRIND \ + (0xA2U) /*!< S(PARAMETERS) tag Bit rates Indication */ +#define RFAL_ISODEP_SPARAM_TAG_BRACT \ + (0xA3U) /*!< S(PARAMETERS) tag Bit rates Activation */ +#define RFAL_ISODEP_SPARAM_TAG_BRACK \ + (0xA4U) /*!< S(PARAMETERS) tag Bit rates Acknowledgement */ + +#define RFAL_ISODEP_SPARAM_TAG_SUP_PCD2PICC \ + (0x80U) /*!< S(PARAMETERS) tag Supported bit rates from PCD to PICC */ +#define RFAL_ISODEP_SPARAM_TAG_SUP_PICC2PCD \ + (0x81U) /*!< S(PARAMETERS) tag Supported bit rates from PICC to PCD */ +#define RFAL_ISODEP_SPARAM_TAG_SUP_FRAME \ + (0x82U) /*!< S(PARAMETERS) tag Supported framing options PICC to PCD */ +#define RFAL_ISODEP_SPARAM_TAG_SEL_PCD2PICC \ + (0x83U) /*!< S(PARAMETERS) tag Selected bit rate from PCD to PICC */ +#define RFAL_ISODEP_SPARAM_TAG_SEL_PICC2PCD \ + (0x84U) /*!< S(PARAMETERS) tag Selected bit rate from PICC to PCD */ +#define RFAL_ISODEP_SPARAM_TAG_SEL_FRAME \ + (0x85U) /*!< S(PARAMETERS) tag Selected framing options PICC to PCD */ + +#define RFAL_ISODEP_SPARAM_TAG_LEN \ + (1) /*!< S(PARAMETERS) Tag Length */ +#define RFAL_ISODEP_SPARAM_TAG_BRREQ_LEN \ + (0U) /*!< S(PARAMETERS) tag Bit rates Request Length */ +#define RFAL_ISODEP_SPARAM_TAG_PICC2PCD_LEN \ + (2U) /*!< S(PARAMETERS) bit rates from PCD to PICC Length */ +#define RFAL_ISODEP_SPARAM_TAG_PCD2PICC_LEN \ + (2U) /*!< S(PARAMETERS) bit rates from PICC to PCD Length */ +#define RFAL_ISODEP_SPARAM_TAG_BRACK_LEN \ + (0U) /*!< S(PARAMETERS) tag Bit rates Acknowledgement Length */ + +#define RFAL_ISODEP_ATS_TA_DPL_212 \ + (0x01U) /*!< ATS TA DSI 212 kbps support bit mask */ +#define RFAL_ISODEP_ATS_TA_DPL_424 \ + (0x02U) /*!< ATS TA DSI 424 kbps support bit mask */ +#define RFAL_ISODEP_ATS_TA_DPL_848 \ + (0x04U) /*!< ATS TA DSI 848 kbps support bit mask */ +#define RFAL_ISODEP_ATS_TA_DLP_212 \ + (0x10U) /*!< ATS TA DSI 212 kbps support bit mask */ +#define RFAL_ISODEP_ATS_TA_DLP_424 \ + (0x20U) /*!< ATS TA DRI 424 kbps support bit mask */ +#define RFAL_ISODEP_ATS_TA_DLP_848 \ + (0x40U) /*!< ATS TA DRI 848 kbps support bit mask */ +#define RFAL_ISODEP_ATS_TA_SAME_D \ + (0x80U) /*!< ATS TA same bit both directions bit mask */ +#define RFAL_ISODEP_ATS_TB_FWI_MASK \ + (0xF0U) /*!< Mask bits for FWI (Frame Waiting Integer) in TB byte */ +#define RFAL_ISODEP_ATS_TB_SFGI_MASK \ + (0x0FU) /*!< Mask bits for SFGI (Start-Up Frame Guard Integer) in TB byte */ + +#define RFAL_ISODEP_ATS_T0_TA_PRESENCE_MASK \ + (0x10U) /*!< Mask bit for TA presence */ +#define RFAL_ISODEP_ATS_T0_TB_PRESENCE_MASK \ + (0x20U) /*!< Mask bit for TB presence */ +#define RFAL_ISODEP_ATS_T0_TC_PRESENCE_MASK \ + (0x40U) /*!< Mask bit for TC presence */ +#define RFAL_ISODEP_ATS_T0_FSCI_MASK \ + (0x0FU) /*!< Mask bit for FSCI presence */ +#define RFAL_ISODEP_ATS_T0_OFFSET \ + (0x01U) /*!< Offset of T0 in ATS Response */ + +#define RFAL_ISODEP_MAX_I_RETRYS \ + (2U) /*!< Number of retries for a I-Block Digital 2.0 16.2.5.4 */ +#define RFAL_ISODEP_MAX_R_RETRYS \ + (3U) /*!< Number of retries for a R-Block Digital 2.0 B9 - nRETRY ACK/NAK: [2,5] */ +#define RFAL_ISODEP_MAX_WTX_NACK_RETRYS \ + (3U) /*!< Number of S(WTX) replied with NACK Digital 2.0 B9 - nRETRY WTX[2,5] */ +#define RFAL_ISODEP_MAX_WTX_RETRYS \ + (20U) /*!< Number of overall S(WTX) retries Digital 2.0 16.2.5.2 */ +#define RFAL_ISODEP_MAX_WTX_RETRYS_ULTD \ + (255U) /*!< Use unlimited number of overall S(WTX) */ +#define RFAL_ISODEP_MAX_DSL_RETRYS \ + (0U) /*!< Number of retries for a S(DESELECT) Digital 2.0 B9 - nRETRY DESELECT: [0,5] */ +#define RFAL_ISODEP_RATS_RETRIES \ + (1U) /*!< RATS retries upon fail Digital 2.0 B7 - nRETRY RATS [0,1] */ + +/*! Frame Size for Proximity Card Integer definitions */ +typedef enum { + RFAL_ISODEP_FSXI_16 = + 0, /*!< Frame Size for Proximity Card Integer with 16 bytes */ + RFAL_ISODEP_FSXI_24 = + 1, /*!< Frame Size for Proximity Card Integer with 24 bytes */ + RFAL_ISODEP_FSXI_32 = + 2, /*!< Frame Size for Proximity Card Integer with 32 bytes */ + RFAL_ISODEP_FSXI_40 = + 3, /*!< Frame Size for Proximity Card Integer with 40 bytes */ + RFAL_ISODEP_FSXI_48 = + 4, /*!< Frame Size for Proximity Card Integer with 48 bytes */ + RFAL_ISODEP_FSXI_64 = + 5, /*!< Frame Size for Proximity Card Integer with 64 bytes */ + RFAL_ISODEP_FSXI_96 = + 6, /*!< Frame Size for Proximity Card Integer with 96 bytes */ + RFAL_ISODEP_FSXI_128 = + 7, /*!< Frame Size for Proximity Card Integer with 128 bytes */ + RFAL_ISODEP_FSXI_256 = + 8, /*!< Frame Size for Proximity Card Integer with 256 bytes */ + RFAL_ISODEP_FSXI_512 = + 9, /*!< Frame Size for Proximity Card Integer with 512 bytes ISO14443-3 Amd2 2012 */ + RFAL_ISODEP_FSXI_1024 = + 10, /*!< Frame Size for Proximity Card Integer with 1024 bytes ISO14443-3 Amd2 2012 */ + RFAL_ISODEP_FSXI_2048 = + 11, /*!< Frame Size for Proximity Card Integer with 2048 bytes ISO14443-3 Amd2 2012 */ + RFAL_ISODEP_FSXI_4096 = + 12 /*!< Frame Size for Proximity Card Integer with 4096 bytes ISO14443-3 Amd2 2012 */ +} rfalIsoDepFSxI; + +/*! Frame Size for Proximity Card definitions */ +typedef enum { + RFAL_ISODEP_FSX_16 = + 16, /*!< Frame Size for Proximity Card with 16 bytes */ + RFAL_ISODEP_FSX_24 = + 24, /*!< Frame Size for Proximity Card with 24 bytes */ + RFAL_ISODEP_FSX_32 = + 32, /*!< Frame Size for Proximity Card with 32 bytes */ + RFAL_ISODEP_FSX_40 = + 40, /*!< Frame Size for Proximity Card with 40 bytes */ + RFAL_ISODEP_FSX_48 = + 48, /*!< Frame Size for Proximity Card with 48 bytes */ + RFAL_ISODEP_FSX_64 = + 64, /*!< Frame Size for Proximity Card with 64 bytes */ + RFAL_ISODEP_FSX_96 = + 96, /*!< Frame Size for Proximity Card with 96 bytes */ + RFAL_ISODEP_FSX_128 = + 128, /*!< Frame Size for Proximity Card with 128 bytes */ + RFAL_ISODEP_FSX_256 = + 256, /*!< Frame Size for Proximity Card with 256 bytes */ + RFAL_ISODEP_FSX_512 = + 512, /*!< Frame Size for Proximity Card with 512 bytes ISO14443-3 Amd2 2012 */ + RFAL_ISODEP_FSX_1024 = + 1024, /*!< Frame Size for Proximity Card with 1024 bytes ISO14443-3 Amd2 2012 */ + RFAL_ISODEP_FSX_2048 = + 2048, /*!< Frame Size for Proximity Card with 2048 bytes ISO14443-3 Amd2 2012 */ + RFAL_ISODEP_FSX_4096 = + 4096, /*!< Frame Size for Proximity Card with 4096 bytes ISO14443-3 Amd2 2012 */ +} rfalIsoDepFSx; + +/* + ****************************************************************************** + * GLOBAL MACROS + ****************************************************************************** + */ + +/* + ****************************************************************************** + * GLOBAL DATA TYPES + ****************************************************************************** + */ + +/*! RATS format Digital 1.1 13.6.1 */ +typedef struct { + uint8_t CMD; /*!< RATS command byte: 0xE0 */ + uint8_t PARAM; /*!< Param indicating FSDI and DID */ +} rfalIsoDepRats; + +/*! ATS response format Digital 1.1 13.6.2 */ +typedef struct { + uint8_t TL; /*!< Length Byte, including TL byte itself */ + uint8_t T0; /*!< Format Byte T0 indicating if TA, TB, TC */ + uint8_t TA; /*!< Interface Byte TA(1) */ + uint8_t TB; /*!< Interface Byte TB(1) */ + uint8_t TC; /*!< Interface Byte TC(1) */ + uint8_t HB[RFAL_ISODEP_ATS_HB_MAX_LEN]; /*!< Historical Bytes */ +} rfalIsoDepAts; + +/*! PPS Request format (Protocol and Parameter Selection) ISO14443-4 5.3 */ +typedef struct { + uint8_t PPSS; /*!< Start Byte: [ 1101b | CID[4b] ] */ + uint8_t PPS0; /*!< Parameter 0:[ 000b | PPS1[1n] | 0001b ] */ + uint8_t PPS1; /*!< Parameter 1:[ 0000b | DSI[2b] | DRI[2b] ]*/ +} rfalIsoDepPpsReq; + +/*! PPS Response format (Protocol and Parameter Selection) ISO14443-4 5.4 */ +typedef struct { + uint8_t PPSS; /*!< Start Byte: [ 1101b | CID[4b] ] */ +} rfalIsoDepPpsRes; + +/*! ATTRIB Command Format Digital 1.1 15.6.1 */ +typedef struct { + uint8_t cmd; /*!< ATTRIB_REQ command byte */ + uint8_t nfcid0[RFAL_NFCB_NFCID0_LEN]; /*!< NFCID0 of the card to be selected */ + struct { + uint8_t PARAM1; /*!< PARAM1 of ATTRIB command */ + uint8_t PARAM2; /*!< PARAM2 of ATTRIB command */ + uint8_t PARAM3; /*!< PARAM3 of ATTRIB command */ + uint8_t PARAM4; /*!< PARAM4 of ATTRIB command */ + } Param; /*!< Parameter of ATTRIB command */ + uint8_t HLInfo[RFAL_ISODEP_ATTRIB_HLINFO_LEN]; /*!< Higher Layer Information */ +} rfalIsoDepAttribCmd; + +/*! ATTRIB Response Format Digital 1.1 15.6.2 */ +typedef struct { + uint8_t mbliDid; /*!< Contains MBLI and DID */ + uint8_t HLInfo[RFAL_ISODEP_ATTRIB_HLINFO_LEN]; /*!< Higher Layer Information */ +} rfalIsoDepAttribRes; + +/*! S(Parameters) Command Format ISO14443-4 (2016) Table 4 */ +typedef struct { + uint8_t tag; /*!< S(PARAMETERS) Tag field */ + uint8_t length; /*!< S(PARAMETERS) Length field */ + uint8_t value[RFAL_ISODEP_SPARAM_VALUES_MAX_LEN]; /*!< S(PARAMETERS) Value field */ +} rfalIsoDepSParameter; + +/*! Activation info as Poller and Listener for NFC-A and NFC-B */ +typedef union { /* PRQA S 0750 # MISRA 19.2 - Both members of the union will not be used concurrently, device is only of type A or B at a time. Thus no problem can occur. */ + + /*! NFC-A information */ + union { /* PRQA S 0750 # MISRA 19.2 - Both members of the union will not be used concurrently, device is only PCD or PICC at a time. Thus no problem can occur. */ + struct { + rfalIsoDepAts ATS; /*!< ATS response (Poller mode) */ + uint8_t ATSLen; /*!< ATS response length (Poller mode) */ + } Listener; + struct { + rfalIsoDepRats RATS; /*!< RATS request (Listener mode) */ + } Poller; + } A; + + /*! NFC-B information */ + union { /* PRQA S 0750 # MISRA 19.2 - Both members of the union will not be used concurrently, device is only PCD or PICC at a time. Thus no problem can occur. */ + struct { + rfalIsoDepAttribRes ATTRIB_RES; /*!< ATTRIB_RES (Poller mode) */ + uint8_t ATTRIB_RESLen; /*!< ATTRIB_RES length (Poller mode) */ + } Listener; + struct { + rfalIsoDepAttribCmd ATTRIB; /*!< ATTRIB request (Listener mode) */ + uint8_t ATTRIBLen; /*!< ATTRIB request length (Listener mode) */ + } Poller; + } B; +} rfalIsoDepActivation; + +/*! ISO-DEP device Info */ +typedef struct { + uint8_t FWI; /*!< Frame Waiting Integer */ + uint32_t FWT; /*!< Frame Waiting Time (1/fc) */ + uint32_t dFWT; /*!< Delta Frame Waiting Time (1/fc) */ + uint32_t SFGI; /*!< Start-up Frame Guard time Integer */ + uint32_t SFGT; /*!< Start-up Frame Guard Time (ms) */ + uint8_t FSxI; /*!< Frame Size Device/Card Integer (FSDI or FSCI) */ + uint16_t FSx; /*!< Frame Size Device/Card (FSD or FSC) */ + uint32_t MBL; /*!< Maximum Buffer Length (optional for NFC-B) */ + rfalBitRate DSI; /*!< Bit Rate coding from Listener (PICC) to Poller (PCD) */ + rfalBitRate DRI; /*!< Bit Rate coding from Poller (PCD) to Listener (PICC) */ + uint8_t DID; /*!< Device ID */ + uint8_t NAD; /*!< Node ADdress */ + bool supDID; /*!< DID supported flag */ + bool supNAD; /*!< NAD supported flag */ + bool supAdFt; /*!< Advanced Features supported flag */ +} rfalIsoDepInfo; + +/*! ISO-DEP Device structure */ +typedef struct { + rfalIsoDepActivation activation; /*!< Activation Info */ + rfalIsoDepInfo info; /*!< ISO-DEP (ISO14443-4) device Info */ +} rfalIsoDepDevice; + +/*! ATTRIB Response parameters */ +typedef struct { + uint8_t mbli; /*!< MBLI */ + uint8_t HLInfo[RFAL_ISODEP_ATTRIB_HLINFO_LEN]; /*!< Hi Layer Information */ + uint8_t HLInfoLen; /*!< Hi Layer Information Length */ +} rfalIsoDepAttribResParam; + +/*! ATS Response parameter */ +typedef struct { + uint8_t fsci; /*!< Frame Size of Proximity Card Integer */ + uint8_t fwi; /*!< Frame Waiting Time Integer */ + uint8_t sfgi; /*!< Start-Up Frame Guard Time Integer */ + bool didSupport; /*!< DID Supported */ + uint8_t ta; /*!< Max supported bitrate both direction */ + uint8_t* hb; /*!< Historical Bytes data */ + uint8_t hbLen; /*!< Historical Bytes Length */ +} rfalIsoDepAtsParam; + +/*! Structure of I-Block Buffer format from caller */ +typedef struct { + uint8_t prologue[RFAL_ISODEP_PROLOGUE_SIZE]; /*!< Prologue/SoD buffer */ + uint8_t + inf[RFAL_FEATURE_ISO_DEP_IBLOCK_MAX_LEN]; /*!< INF/Payload buffer */ +} rfalIsoDepBufFormat; + +/*! Structure of APDU Buffer format from caller */ +typedef struct { + uint8_t prologue[RFAL_ISODEP_PROLOGUE_SIZE]; /*!< Prologue/SoD buffer */ + uint8_t apdu[RFAL_FEATURE_ISO_DEP_APDU_MAX_LEN]; /*!< APDU/Payload buffer */ +} rfalIsoDepApduBufFormat; + +/*! Listen Activation Parameters Structure */ +typedef struct { + rfalIsoDepBufFormat* rxBuf; /*!< Receive Buffer struct reference */ + uint16_t* rxLen; /*!< Received INF data length in Bytes */ + bool* isRxChaining; /*!< Received data is not complete */ + rfalIsoDepDevice* isoDepDev; /*!< ISO-DEP device info */ +} rfalIsoDepListenActvParam; + +/*! Structure of parameters used on ISO DEP Transceive */ +typedef struct { + rfalIsoDepBufFormat* txBuf; /*!< Transmit Buffer struct reference */ + uint16_t txBufLen; /*!< Transmit Buffer INF field length in Bytes*/ + bool isTxChaining; /*!< Transmit data is not complete */ + rfalIsoDepBufFormat* rxBuf; /*!< Receive Buffer struct reference in Bytes */ + uint16_t* rxLen; /*!< Received INF data length in Bytes */ + bool* isRxChaining; /*!< Received data is not complete */ + uint32_t FWT; /*!< FWT to be used (ignored in Listen Mode) */ + uint32_t dFWT; /*!< Delta FWT to be used */ + uint16_t ourFSx; /*!< Our device Frame Size (FSD or FSC) */ + uint16_t FSx; /*!< Other device Frame Size (FSD or FSC) */ + uint8_t DID; /*!< Device ID (RFAL_ISODEP_NO_DID if no DID) */ +} rfalIsoDepTxRxParam; + +/*! Structure of parameters used on ISO DEP APDU Transceive */ +typedef struct { + rfalIsoDepApduBufFormat* txBuf; /*!< Transmit Buffer struct reference */ + uint16_t txBufLen; /*!< Transmit Buffer INF field length in Bytes*/ + rfalIsoDepApduBufFormat* rxBuf; /*!< Receive Buffer struct reference in Bytes */ + uint16_t* rxLen; /*!< Received INF data length in Bytes */ + rfalIsoDepBufFormat* tmpBuf; /*!< Temp buffer for Rx I-Blocks (internal) */ + uint32_t FWT; /*!< FWT to be used (ignored in Listen Mode) */ + uint32_t dFWT; /*!< Delta FWT to be used */ + uint16_t FSx; /*!< Other device Frame Size (FSD or FSC) */ + uint16_t ourFSx; /*!< Our device Frame Size (FSD or FSC) */ + uint8_t DID; /*!< Device ID (RFAL_ISODEP_NO_DID if no DID) */ +} rfalIsoDepApduTxRxParam; + +/* + ****************************************************************************** + * GLOBAL FUNCTION PROTOTYPES + ****************************************************************************** + */ + +/*! + ****************************************************************************** + * \brief Initialize the ISO-DEP protocol + * + * Initialize the ISO-DEP protocol layer with default config + ****************************************************************************** + */ +void rfalIsoDepInitialize(void); + +/*! + ****************************************************************************** + * \brief Initialize the ISO-DEP protocol + * + * Initialize the ISO-DEP protocol layer with additional parameters allowing + * to customise the protocol layer for specific behaviours + * + + * \param[in] compMode : Compliance mode to be performed + * \param[in] maxRetriesR : Number of retries for a R-Block + * Digital 2.0 B9 - nRETRY ACK/NAK: [2,5] + * \param[in] maxRetriesSnWTX : Number of retries for a S(WTX) (only in case + * of NAKs) Digital 2.0 B9 - nRETRY WTX[2,5] + * \param[in] maxRetriesSWTX : Number of overall S(WTX) retries. + * Use RFAL_ISODEP_MAX_WTX_RETRYS_ULTD for disabling + * this limit check Digital 2.0 16.2.5.2 + * \param[in] maxRetriesSDSL : Number of retries for a S(DESELECT) + * Digital 2.0 B9 - nRETRY DESELECT: [0,5] + * \param[in] maxRetriesI : Number of retries for a I-Block + * Digital 2.0 16.2.5.4 + * \param[in] maxRetriesRATS : Number of retries for RATS + * Digital 2.0 B7 - nRETRY RATS [0,1] + * + ****************************************************************************** + */ +void rfalIsoDepInitializeWithParams( + rfalComplianceMode compMode, + uint8_t maxRetriesR, + uint8_t maxRetriesSnWTX, + uint8_t maxRetriesSWTX, + uint8_t maxRetriesSDSL, + uint8_t maxRetriesI, + uint8_t maxRetriesRATS); + +/*! + ***************************************************************************** + * \brief FSxI to FSx + * + * Convert Frame Size for proximity coupling Device Integer (FSxI) to + * Frame Size for proximity coupling Device (FSx) + * + * FSD - maximum frame size for NFC Forum Device in Poll Mode + * FSC - maximum frame size for NFC Forum Device in Listen Mode + * + * FSxI = FSDI or FSCI + * FSx = FSD or FSC + * + * The FSD/FSC value includes the header and CRC + * + * \param[in] FSxI : Frame Size for proximity coupling Device Integer + * + * \return fsx : Frame Size for proximity coupling Device (FSD or FSC) + * + ***************************************************************************** + */ +uint16_t rfalIsoDepFSxI2FSx(uint8_t FSxI); + +/*! + ***************************************************************************** + * \brief FWI to FWT + * + * Convert Frame Waiting time Integer (FWI) to Frame Waiting Time (FWT) in + * 1/fc units + * + * \param[in] fwi : Frame Waiting time Integer + * + * \return fwt : Frame Waiting Time in 1/fc units + * + ***************************************************************************** + */ +uint32_t rfalIsoDepFWI2FWT(uint8_t fwi); + +/*! + ***************************************************************************** + * \brief Check if the buffer data contains a valid RATS command + * + * Check if it is a well formed RATS command with 2 bytes + * This function does not check the validity of FSDI and DID + * + * \param[in] buf : reference to buffer containing the data to be checked + * \param[in] bufLen : length of data in the buffer in bytes + * + * \return true if the data indicates a RATS command; false otherwise + ***************************************************************************** + */ +bool rfalIsoDepIsRats(const uint8_t* buf, uint8_t bufLen); + +/*! + ***************************************************************************** + * \brief Check if the buffer data contains a valid ATTRIB command + * + * Check if it is a well formed ATTRIB command, but does not check the + * validity of the information inside + * + * \param[in] buf : reference to buffer containing the data to be checked + * \param[in] bufLen : length of data in the buffer in bytes + * + * \return true if the data indicates a ATTRIB command; false otherwise + ***************************************************************************** + */ +bool rfalIsoDepIsAttrib(const uint8_t* buf, uint8_t bufLen); + +/*! + ***************************************************************************** + * \brief Start Listen Activation Handling + * + * Start Listen Activation Handling and setup to receive first I-block which may + * contain complete or partial APDU after activation is completed + * + * Pass in RATS for T4AT, or ATTRIB for T4BT, to handle ATS or ATTRIB Response respectively + * The Activation Handling handles ATS and ATTRIB Response; and additionally PPS Response + * if a PPS is received for T4AT. + * The method uses the current RFAL state machine to determine if it is expecting RATS or ATTRIB + * + * Activation is completed if PPS Response is sent or if first PDU is received in T4T-A + * Activation is completed if ATTRIB Response is sent in T4T-B + * + * \ref rfalIsoDepListenGetActivationStatus provide status if activation is completed. + * \ref rfalIsoDepStartTransceive shall be called right after activation is completed + * + * \param[in] atsParam : reference to ATS parameters + * \param[in] attribResParam : reference to ATTRIB_RES parameters + * \param[in] buf : reference to buffer containing RATS or ATTRIB + * \param[in] bufLen : length in bytes of the given buffer + * \param[in] actParam : reference to incoming reception information will be placed + * + * + * \warning Once the Activation has been completed the method + * rfalIsoDepGetTransceiveStatus() must be called. + * If activation has completed due to reception of a data block (not PPS) the + * buffer owned by the caller and passed on actParam must still contain this data. + * The first data will be processed (I-Block or S-DSL) by rfalIsoDepGetTransceiveStatus() + * inform the caller and then for the next transaction use rfalIsoDepStartTransceive() + * + * \return ERR_NONE : RATS/ATTRIB is valid and activation has started + * \return ERR_PARAM : Invalid parameters + * \return ERR_PROTO : Invalid request + * \return ERR_NOTSUPP : Feature not supported + ***************************************************************************** + */ +ReturnCode rfalIsoDepListenStartActivation( + rfalIsoDepAtsParam* atsParam, + const rfalIsoDepAttribResParam* attribResParam, + const uint8_t* buf, + uint16_t bufLen, + rfalIsoDepListenActvParam actParam); + +/*! + ***************************************************************************** + * \brief Get the current Activation Status + * + * \return ERR_NONE if Activation is already completed + * \return ERR_BUSY if Activation is ongoing + * \return ERR_LINK_LOSS if Remote Field is turned off + ***************************************************************************** + */ +ReturnCode rfalIsoDepListenGetActivationStatus(void); + +/*! + ***************************************************************************** + * \brief Get the ISO-DEP Communication Information + * + * Gets the maximum INF length in bytes based on current Frame Size + * for proximity coupling Device (FSD or FSC) excluding the header and CRC + * + * \return maximum INF length in bytes + ***************************************************************************** + */ +uint16_t rfalIsoDepGetMaxInfLen(void); + +/*! + ***************************************************************************** + * \brief ISO-DEP Start Transceive + * + * This method triggers a ISO-DEP Transceive containing a complete or + * partial APDU + * It transmits the given message and handles all protocol retransmitions, + * error handling and control messages + * + * The txBuf contains a complete or partial APDU (INF) to be transmitted + * The Prologue field will be manipulated by the Transceive + * + * If the buffer contains a partial APDU and is not the last block, + * then isTxChaining must be set to true + * + * \param[in] param: reference parameters to be used for the Transceive + * + * \return ERR_PARAM : Bad request + * \return ERR_WRONG_STATE : The module is not in a proper state + * \return ERR_NONE : The Transceive request has been started + ***************************************************************************** + */ +ReturnCode rfalIsoDepStartTransceive(rfalIsoDepTxRxParam param); + +/*! + ***************************************************************************** + * \brief Get the Transceive status + * + * Returns the status of the ISO-DEP Transceive + * + * \warning When the other device is performing chaining once a chained + * block is received the error ERR_AGAIN is sent. At this point + * caller must handle the received data immediately. + * When ERR_AGAIN is returned an ACK has already been sent to + * the other device and the next block might be incoming. + * If rfalWorker() is called frequently it will place the next + * block on the given buffer + * + * + * \return ERR_NONE : Transceive has been completed successfully + * \return ERR_BUSY : Transceive is ongoing + * \return ERR_PROTO : Protocol error occurred + * \return ERR_TIMEOUT : Timeout error occurred + * \return ERR_SLEEP_REQ : Deselect has been received and responded + * \return ERR_NOMEM : The received INF does not fit into the + * receive buffer + * \return ERR_LINK_LOSS : Communication is lost because Reader/Writer + * has turned off its field + * \return ERR_AGAIN : received one chaining block, continue to call + * this method to retrieve the remaining blocks + ***************************************************************************** + */ +ReturnCode rfalIsoDepGetTransceiveStatus(void); + +/*! + ***************************************************************************** + * \brief ISO-DEP Start APDU Transceive + * + * This method triggers a ISO-DEP Transceive containing a complete APDU + * It transmits the given message and handles all protocol retransmitions, + * error handling and control messages + * + * The txBuf contains a complete APDU to be transmitted + * The Prologue field will be manipulated by the Transceive + * + * \warning the txBuf will be modified during the transmission + * \warning the maximum RF frame which can be received is limited by param.tmpBuf + * + * \param[in] param: reference parameters to be used for the Transceive + * + * \return ERR_PARAM : Bad request + * \return ERR_WRONG_STATE : The module is not in a proper state + * \return ERR_NONE : The Transceive request has been started + ***************************************************************************** + */ +ReturnCode rfalIsoDepStartApduTransceive(rfalIsoDepApduTxRxParam param); + +/*! + ***************************************************************************** + * \brief Get the APDU Transceive status + * + * \return ERR_NONE : if Transceive has been completed successfully + * \return ERR_BUSY : if Transceive is ongoing + * \return ERR_PROTO : if a protocol error occurred + * \return ERR_TIMEOUT : if a timeout error occurred + * \return ERR_SLEEP_REQ : if Deselect is received and responded + * \return ERR_NOMEM : if the received INF does not fit into the + * receive buffer + * \return ERR_LINK_LOSS : if communication is lost because Reader/Writer + * has turned off its field + ***************************************************************************** + */ +ReturnCode rfalIsoDepGetApduTransceiveStatus(void); + +/*! + ***************************************************************************** + * \brief ISO-DEP Send RATS + * + * This sends a RATS to make a NFC-A Listen Device to enter + * ISO-DEP layer (ISO14443-4) and checks if the received ATS is valid + * + * \param[in] FSDI : Frame Size Device Integer to be used + * \param[in] DID : Device ID to be used or RFAL_ISODEP_NO_DID for not use DID + * \param[out] ats : pointer to place the ATS Response + * \param[out] atsLen : pointer to place the ATS length + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error + * \return ERR_PAR : Parity error detected + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error, ATS received + ***************************************************************************** + */ +ReturnCode rfalIsoDepRATS(rfalIsoDepFSxI FSDI, uint8_t DID, rfalIsoDepAts* ats, uint8_t* atsLen); + +/*! + ***************************************************************************** + * \brief ISO-DEP Send PPS + * + * This sends a PPS to make a NFC-A Listen Device change the communications + * bit rate from 106kbps to one of the supported bit rates + * Additionally checks if the received PPS response is valid + * + * \param[in] DID : Device ID + * \param[in] DSI : DSI code the divisor from Listener (PICC) to Poller (PCD) + * \param[in] DRI : DRI code the divisor from Poller (PCD) to Listener (PICC) + * \param[out] ppsRes : pointer to place the PPS Response + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error + * \return ERR_PAR : Parity error detected + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error, PPS Response received + ***************************************************************************** + */ +ReturnCode rfalIsoDepPPS(uint8_t DID, rfalBitRate DSI, rfalBitRate DRI, rfalIsoDepPpsRes* ppsRes); + +/*! + ***************************************************************************** + * \brief ISO-DEP Send ATTRIB + * + * This sends a ATTRIB to make a NFC-B Listen Device to enter + * ISO-DEP layer (ISO14443-4) and checks if the received ATTRIB Response is valid + * + * \param[in] nfcid0 : NFCID0 to be used for the ATTRIB + * \param[in] PARAM1 : ATTRIB PARAM1 byte (communication parameters) + * \param[in] DSI : DSI code the divisor from Listener (PICC) to Poller (PCD) + * \param[in] DRI : DRI code the divisor from Poller (PCD) to Listener (PICC) + * \param[in] FSDI : PCD's Frame Size to be announced on the ATTRIB + * \param[in] PARAM3 : ATTRIB PARAM1 byte (protocol type) + * \param[in] DID : Device ID to be used or RFAL_ISODEP_NO_DID for not use DID + * \param[in] HLInfo : pointer to Higher layer INF (NULL if none) + * \param[in] HLInfoLen : Length HLInfo + * \param[in] fwt : Frame Waiting Time to be used (from SENSB_RES) + * \param[out] attribRes : pointer to place the ATTRIB Response + * \param[out] attribResLen : pointer to place the ATTRIB Response length + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error, ATTRIB Response received + ***************************************************************************** + */ +ReturnCode rfalIsoDepATTRIB( + const uint8_t* nfcid0, + uint8_t PARAM1, + rfalBitRate DSI, + rfalBitRate DRI, + rfalIsoDepFSxI FSDI, + uint8_t PARAM3, + uint8_t DID, + const uint8_t* HLInfo, + uint8_t HLInfoLen, + uint32_t fwt, + rfalIsoDepAttribRes* attribRes, + uint8_t* attribResLen); + +/*! + ***************************************************************************** + * \brief Deselects PICC + * + * This function sends a deselect command to PICC and waits for it`s + * response in a blocking way + * + * \return ERR_NONE : Deselect successfully sent and acknowledged by PICC + * \return ERR_TIMEOUT: No response rcvd from PICC + * + ***************************************************************************** + */ +ReturnCode rfalIsoDepDeselect(void); + +/*! + ***************************************************************************** + * \brief ISO-DEP Poller Handle NFC-A Activation + * + * This performs a NFC-A Activation into ISO-DEP layer (ISO14443-4) with the given + * parameters. It sends RATS and if the higher bit rates are supported by + * both devices it additionally sends PPS + * Once Activated all details of the device are provided on isoDepDev + * + * \param[in] FSDI : Frame Size Device Integer to be used + * \param[in] DID : Device ID to be used or RFAL_ISODEP_NO_DID for not use DID + * \param[in] maxBR : Max bit rate supported by the Poller + * \param[out] isoDepDev : ISO-DEP information of the activated Listen device + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error + * \return ERR_PAR : Parity error detected + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error, activation successful + ***************************************************************************** + */ +ReturnCode rfalIsoDepPollAHandleActivation( + rfalIsoDepFSxI FSDI, + uint8_t DID, + rfalBitRate maxBR, + rfalIsoDepDevice* isoDepDev); + +/*! + ***************************************************************************** + * \brief ISO-DEP Poller Handle NFC-B Activation + * + * This performs a NFC-B Activation into ISO-DEP layer (ISO14443-4) with the given + * parameters. It sends ATTRIB and calculates supported higher bit rates of both + * devices and performs activation. + * Once Activated all details of the device are provided on isoDepDev + * + * \param[in] FSDI : Frame Size Device Integer to be used + * \param[in] DID : Device ID to be used or RFAL_ISODEP_NO_DID for not use DID + * \param[in] maxBR : Max bit rate supported by the Poller + * \param[in] PARAM1 : ATTRIB PARAM1 byte (communication parameters) + * \param[in] nfcbDev : pointer to the NFC-B Device containing the SENSB_RES + * \param[in] HLInfo : pointer to Higher layer INF (NULL if none) + * \param[in] HLInfoLen : Length HLInfo + * \param[out] isoDepDev : ISO-DEP information of the activated Listen device + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error + * \return ERR_PAR : Parity error detected + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error, activation successful + ***************************************************************************** + */ +ReturnCode rfalIsoDepPollBHandleActivation( + rfalIsoDepFSxI FSDI, + uint8_t DID, + rfalBitRate maxBR, + uint8_t PARAM1, + const rfalNfcbListenDevice* nfcbDev, + const uint8_t* HLInfo, + uint8_t HLInfoLen, + rfalIsoDepDevice* isoDepDev); + +/*! + ***************************************************************************** + * \brief ISO-DEP Poller Handle S(Parameters) + * + * This checks if PICC supports S(PARAMETERS), retrieves PICC's + * capabilities and sets the Bit Rate at the highest supported by both + * devices + * + * \param[out] isoDepDev : ISO-DEP information of the activated Listen device + * \param[in] maxTxBR : Maximum Tx bit rate supported by PCD + * \param[in] maxRxBR : Maximum Rx bit rate supported by PCD + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error, S(PARAMETERS) selection successful + ***************************************************************************** + */ +ReturnCode rfalIsoDepPollHandleSParameters( + rfalIsoDepDevice* isoDepDev, + rfalBitRate maxTxBR, + rfalBitRate maxRxBR); + +/*! + ***************************************************************************** + * \brief ISO-DEP Poller Start NFC-A Activation + * + * This starts a NFC-A Activation into ISO-DEP layer (ISO14443-4) with the given + * parameters. It sends RATS and if the higher bit rates are supported by + * both devices it additionally sends PPS + * Once Activated all details of the device are provided on isoDepDev + * + * + * \see rfalIsoDepPollAGetActivationStatus + * + * \param[in] FSDI : Frame Size Device Integer to be used + * \param[in] DID : Device ID to be used or RFAL_ISODEP_NO_DID for not use DID + * \param[in] maxBR : Max bit rate supported by the Poller + * \param[out] isoDepDev : ISO-DEP information of the activated Listen device + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error + * \return ERR_PAR : Parity error detected + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error, start of asynchronous operation successful + ***************************************************************************** + */ +ReturnCode rfalIsoDepPollAStartActivation( + rfalIsoDepFSxI FSDI, + uint8_t DID, + rfalBitRate maxBR, + rfalIsoDepDevice* isoDepDev); + +/*! + ***************************************************************************** + * \brief ISO-DEP Poller Get NFC-A Activation Status + * + * Returns the activation status started by rfalIsoDepPollAStartActivation + * + * \see rfalIsoDepPollAStartActivation + * + * \return ERR_BUSY : Operation is ongoing + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error + * \return ERR_PAR : Parity error detected + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error, activation successful + ***************************************************************************** + */ +ReturnCode rfalIsoDepPollAGetActivationStatus(void); + +/*! + ***************************************************************************** + * \brief ISO-DEP Poller Start NFC-B Activation + * + * This starts a NFC-B Activation into ISO-DEP layer (ISO14443-4) with the given + * parameters. It will send ATTRIB and calculate supported higher bit rates of both + * devices and perform activation. + * Once Activated all details of the device are provided on isoDepDev + * + * \see rfalIsoDepPollBGetActivationStatus + * + * \param[in] FSDI : Frame Size Device Integer to be used + * \param[in] DID : Device ID to be used or RFAL_ISODEP_NO_DID for not use DID + * \param[in] maxBR : Max bit rate supported by the Poller + * \param[in] PARAM1 : ATTRIB PARAM1 byte (communication parameters) + * \param[in] nfcbDev : pointer to the NFC-B Device containing the SENSB_RES + * \param[in] HLInfo : pointer to Higher layer INF (NULL if none) + * \param[in] HLInfoLen : Length HLInfo + * \param[out] isoDepDev : ISO-DEP information of the activated Listen device + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error + * \return ERR_PAR : Parity error detected + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error, start of asynchronous operation successful + ***************************************************************************** + */ +ReturnCode rfalIsoDepPollBStartActivation( + rfalIsoDepFSxI FSDI, + uint8_t DID, + rfalBitRate maxBR, + uint8_t PARAM1, + const rfalNfcbListenDevice* nfcbDev, + const uint8_t* HLInfo, + uint8_t HLInfoLen, + rfalIsoDepDevice* isoDepDev); + +/*! + ***************************************************************************** + * \brief ISO-DEP Poller Get NFC-B Activation Status + * + * Returns the activation status started by rfalIsoDepPollBStartActivation + * + * \see rfalIsoDepPollBStartActivation + * + * \return ERR_BUSY : Operation is ongoing + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error + * \return ERR_PAR : Parity error detected + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error, activation successful + ***************************************************************************** + */ +ReturnCode rfalIsoDepPollBGetActivationStatus(void); + +#endif /* RFAL_ISODEP_H_ */ + +/** + * @} + * + * @} + * + * @} + */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_nfc.h b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_nfc.h new file mode 100644 index 00000000000..a9056335e8e --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_nfc.h @@ -0,0 +1,425 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_nfc.h + * + * \brief RFAL NFC device + * + * This module provides the required features to behave as an NFC Poller + * or Listener device. It grants an easy to use interface for the following + * activities: Technology Detection, Collision Resolution, Activation, + * Data Exchange, and Deactivation + * + * This layer is influenced by (but not fully aligned with) the NFC Forum + * specifications, in particular: Activity 2.0 and NCI 2.0 + * + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-HL + * \brief RFAL Higher Layer + * @{ + * + * \addtogroup NFC + * \brief RFAL NFC Device + * @{ + * + */ + +#ifndef RFAL_NFC_H +#define RFAL_NFC_H + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ +#include "../platform.h" +#include "../st_errno.h" +#include "rfal_rf.h" +#include "rfal_nfca.h" +#include "rfal_nfcb.h" +#include "rfal_nfcf.h" +#include "rfal_nfcv.h" +#include "rfal_st25tb.h" +#include "rfal_nfcDep.h" +#include "rfal_isoDep.h" + +/* +****************************************************************************** +* GLOBAL DEFINES +****************************************************************************** +*/ + +#define RFAL_NFC_TECH_NONE 0x0000U /*!< No technology */ +#define RFAL_NFC_POLL_TECH_A 0x0001U /*!< NFC-A technology Flag */ +#define RFAL_NFC_POLL_TECH_B 0x0002U /*!< NFC-B technology Flag */ +#define RFAL_NFC_POLL_TECH_F 0x0004U /*!< NFC-F technology Flag */ +#define RFAL_NFC_POLL_TECH_V 0x0008U /*!< NFC-V technology Flag */ +#define RFAL_NFC_POLL_TECH_AP2P 0x0010U /*!< AP2P technology Flag */ +#define RFAL_NFC_POLL_TECH_ST25TB 0x0020U /*!< ST25TB technology Flag */ +#define RFAL_NFC_LISTEN_TECH_A 0x1000U /*!< NFC-V technology Flag */ +#define RFAL_NFC_LISTEN_TECH_B 0x2000U /*!< NFC-V technology Flag */ +#define RFAL_NFC_LISTEN_TECH_F 0x4000U /*!< NFC-V technology Flag */ +#define RFAL_NFC_LISTEN_TECH_AP2P 0x8000U /*!< NFC-V technology Flag */ + +/* +****************************************************************************** +* GLOBAL MACROS +****************************************************************************** +*/ + +/*! Checks if a device is currently activated */ +#define rfalNfcIsDevActivated(st) \ + (((st) >= RFAL_NFC_STATE_ACTIVATED) && ((st) < RFAL_NFC_STATE_DEACTIVATION)) + +/*! Checks if a device is in discovery */ +#define rfalNfcIsInDiscovery(st) \ + (((st) >= RFAL_NFC_STATE_START_DISCOVERY) && ((st) < RFAL_NFC_STATE_ACTIVATED)) + +/*! Checks if remote device is in Poll mode */ +#define rfalNfcIsRemDevPoller(tp) \ + (((tp) >= RFAL_NFC_POLL_TYPE_NFCA) && ((tp) <= RFAL_NFC_POLL_TYPE_AP2P)) + +/*! Checks if remote device is in Listen mode */ +#define rfalNfcIsRemDevListener(tp) \ + (((int16_t)(tp) >= (int16_t)RFAL_NFC_LISTEN_TYPE_NFCA) && ((tp) <= RFAL_NFC_LISTEN_TYPE_AP2P)) + +/* +****************************************************************************** +* GLOBAL ENUMS +****************************************************************************** +*/ + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + +/*! Main state */ +typedef enum { + RFAL_NFC_STATE_NOTINIT = 0, /*!< Not Initialized state */ + RFAL_NFC_STATE_IDLE = 1, /*!< Initialize state */ + RFAL_NFC_STATE_START_DISCOVERY = 2, /*!< Start Discovery loop state */ + RFAL_NFC_STATE_WAKEUP_MODE = 3, /*!< Wake-Up state */ + RFAL_NFC_STATE_POLL_TECHDETECT = 10, /*!< Technology Detection state */ + RFAL_NFC_STATE_POLL_COLAVOIDANCE = 11, /*!< Collision Avoidance state */ + RFAL_NFC_STATE_POLL_SELECT = 12, /*!< Wait for Selection state */ + RFAL_NFC_STATE_POLL_ACTIVATION = 13, /*!< Activation state */ + RFAL_NFC_STATE_LISTEN_TECHDETECT = 20, /*!< Listen Tech Detect */ + RFAL_NFC_STATE_LISTEN_COLAVOIDANCE = 21, /*!< Listen Collision Avoidance */ + RFAL_NFC_STATE_LISTEN_ACTIVATION = 22, /*!< Listen Activation state */ + RFAL_NFC_STATE_LISTEN_SLEEP = 23, /*!< Listen Sleep state */ + RFAL_NFC_STATE_ACTIVATED = 30, /*!< Activated state */ + RFAL_NFC_STATE_DATAEXCHANGE = 31, /*!< Data Exchange Start state */ + RFAL_NFC_STATE_DATAEXCHANGE_DONE = 33, /*!< Data Exchange terminated */ + RFAL_NFC_STATE_DEACTIVATION = 34 /*!< Deactivation state */ +} rfalNfcState; + +/*! Device type */ +typedef enum { + RFAL_NFC_LISTEN_TYPE_NFCA = 0, /*!< NFC-A Listener device type */ + RFAL_NFC_LISTEN_TYPE_NFCB = 1, /*!< NFC-B Listener device type */ + RFAL_NFC_LISTEN_TYPE_NFCF = 2, /*!< NFC-F Listener device type */ + RFAL_NFC_LISTEN_TYPE_NFCV = 3, /*!< NFC-V Listener device type */ + RFAL_NFC_LISTEN_TYPE_ST25TB = 4, /*!< ST25TB Listener device type */ + RFAL_NFC_LISTEN_TYPE_AP2P = 5, /*!< AP2P Listener device type */ + RFAL_NFC_POLL_TYPE_NFCA = 10, /*!< NFC-A Poller device type */ + RFAL_NFC_POLL_TYPE_NFCB = 11, /*!< NFC-B Poller device type */ + RFAL_NFC_POLL_TYPE_NFCF = 12, /*!< NFC-F Poller device type */ + RFAL_NFC_POLL_TYPE_NFCV = 13, /*!< NFC-V Poller device type */ + RFAL_NFC_POLL_TYPE_AP2P = 15 /*!< AP2P Poller device type */ +} rfalNfcDevType; + +/*! Device interface */ +typedef enum { + RFAL_NFC_INTERFACE_RF = 0, /*!< RF Frame interface */ + RFAL_NFC_INTERFACE_ISODEP = 1, /*!< ISO-DEP interface */ + RFAL_NFC_INTERFACE_NFCDEP = 2 /*!< NFC-DEP interface */ +} rfalNfcRfInterface; + +/*! Device struct containing all its details */ +typedef struct { + rfalNfcDevType type; /*!< Device's type */ + union { /* PRQA S 0750 # MISRA 19.2 - Members of the union will not be used concurrently, only one technology at a time */ + rfalNfcaListenDevice nfca; /*!< NFC-A Listen Device instance */ + rfalNfcbListenDevice nfcb; /*!< NFC-B Listen Device instance */ + rfalNfcfListenDevice nfcf; /*!< NFC-F Listen Device instance */ + rfalNfcvListenDevice nfcv; /*!< NFC-V Listen Device instance */ + rfalSt25tbListenDevice st25tb; /*!< ST25TB Listen Device instance*/ + } dev; /*!< Device's instance */ + + uint8_t* nfcid; /*!< Device's NFCID */ + uint8_t nfcidLen; /*!< Device's NFCID length */ + rfalNfcRfInterface rfInterface; /*!< Device's interface */ + + union { /* PRQA S 0750 # MISRA 19.2 - Members of the union will not be used concurrently, only one protocol at a time */ + rfalIsoDepDevice isoDep; /*!< ISO-DEP instance */ + rfalNfcDepDevice nfcDep; /*!< NFC-DEP instance */ + } proto; /*!< Device's protocol */ +} rfalNfcDevice; + +/*! Discovery parameters */ +typedef struct { + rfalComplianceMode compMode; /*!< Compliance mode to be used */ + uint16_t techs2Find; /*!< Technologies to search for */ + uint16_t totalDuration; /*!< Duration of a whole Poll + Listen cycle */ + uint8_t devLimit; /*!< Max number of devices */ + rfalBitRate maxBR; /*!< Max Bit rate to be used for communications */ + + rfalBitRate nfcfBR; /*!< Bit rate to poll for NFC-F */ + uint8_t + nfcid3[RFAL_NFCDEP_NFCID3_LEN]; /*!< NFCID3 to be used on the ATR_REQ/ATR_RES */ + uint8_t GB[RFAL_NFCDEP_GB_MAX_LEN]; /*!< General bytes to be used on the ATR-REQ */ + uint8_t GBLen; /*!< Length of the General Bytes */ + rfalBitRate ap2pBR; /*!< Bit rate to poll for AP2P */ + + rfalLmConfPA lmConfigPA; /*!< Configuration for Passive Listen mode NFC-A */ + rfalLmConfPF lmConfigPF; /*!< Configuration for Passive Listen mode NFC-A */ + + void (*notifyCb)(rfalNfcState st); /*!< Callback to Notify upper layer */ + + bool wakeupEnabled; /*!< Enable Wake-Up mode before polling */ + bool wakeupConfigDefault; /*!< Wake-Up mode default configuration */ + rfalWakeUpConfig wakeupConfig; /*!< Wake-Up mode configuration */ + + bool activate_after_sak; // Set device to Active mode after SAK response +} rfalNfcDiscoverParam; + +/*! Buffer union, only one interface is used at a time */ +typedef union { /* PRQA S 0750 # MISRA 19.2 - Members of the union will not be used concurrently, only one interface at a time */ + uint8_t rfBuf[RFAL_FEATURE_NFC_RF_BUF_LEN]; /*!< RF buffer */ + rfalIsoDepApduBufFormat isoDepBuf; /*!< ISO-DEP buffer format (with header/prologue) */ + rfalNfcDepPduBufFormat nfcDepBuf; /*!< NFC-DEP buffer format (with header/prologue) */ +} rfalNfcBuffer; + +/*******************************************************************************/ + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +/*! + ***************************************************************************** + * \brief RFAL NFC Worker + * + * It runs the internal state machine and runs the RFAL RF worker. + ***************************************************************************** + */ +void rfalNfcWorker(void); + +/*! + ***************************************************************************** + * \brief RFAL NFC Initialize + * + * It initializes this module and its dependencies + * + * \return ERR_WRONG_STATE : Incorrect state for this operation + * \return ERR_IO : Generic internal error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcInitialize(void); + +/*! + ***************************************************************************** + * \brief RFAL NFC Discovery + * + * It set the device in Discovery state. + * In discovery it will Poll and/or Listen for the technologies configured, + * and perform Wake-up mode if configured to do so. + * + * The device list passed on disParams must not be empty. + * The number of devices on the list is indicated by the devLimit and shall + * be at >= 1. + * + * \param[in] disParams : discovery configuration parameters + * + * \return ERR_WRONG_STATE : Incorrect state for this operation + * \return ERR_PARAM : Invalid parameters + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcDiscover(const rfalNfcDiscoverParam* disParams); + +/*! + ***************************************************************************** + * \brief RFAL NFC Get State + * + * It returns the current state + * + * \return rfalNfcState : the current state + ***************************************************************************** + */ +rfalNfcState rfalNfcGetState(void); + +/*! + ***************************************************************************** + * \brief RFAL NFC Get Devices Found + * + * It returns the location of the device list and the number of + * devices found. + * + * \param[out] devList : device list location + * \param[out] devCnt : number of devices found + * + * \return ERR_WRONG_STATE : Incorrect state for this operation + * Discovery still ongoing + * \return ERR_PARAM : Invalid parameters + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcGetDevicesFound(rfalNfcDevice** devList, uint8_t* devCnt); + +/*! + ***************************************************************************** + * \brief RFAL NFC Get Active Device + * + * It returns the location of the device current Active device + * + * \param[out] dev : device info location + * + * \return ERR_WRONG_STATE : Incorrect state for this operation + * No device activated + * \return ERR_PARAM : Invalid parameters + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcGetActiveDevice(rfalNfcDevice** dev); + +/*! + ***************************************************************************** + * \brief RFAL NFC Select Device + * + * It selects the device to be activated. + * It shall be called when more than one device has been identified to + * indiacte which device shall be active + * + * \param[in] devIdx : device index to be activated + * + * \return ERR_WRONG_STATE : Incorrect state for this operation + * Not in select state + * \return ERR_PARAM : Invalid parameters + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcSelect(uint8_t devIdx); + +/*! + ***************************************************************************** + * \brief RFAL NFC Start Data Exchange + * + * After a device has been activated, it starts a data exchange. + * It handles automatically which interface/protocol to be used and acts accordingly. + * + * In Listen mode the first frame/data shall be sent by the Reader/Initiator + * therefore this method must be called first with txDataLen set to zero + * to retrieve the rxData and rcvLen locations. + * + * + * \param[in] txData : data to be transmitted + * \param[in] txDataLen : size of the data to be transmitted + * \param[out] rxData : location of the received data after operation is completed + * \param[out] rvdLen : location of thelength of the received data + * \param[in] fwt : FWT to be used in case of RF interface. + * If ISO-DEP or NFC-DEP interface is used, this will be ignored + * + * \return ERR_WRONG_STATE : Incorrect state for this operation + * \return ERR_PARAM : Invalid parameters + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcDataExchangeStart( + uint8_t* txData, + uint16_t txDataLen, + uint8_t** rxData, + uint16_t** rvdLen, + uint32_t fwt, + uint32_t tx_flag); + +ReturnCode rfalNfcDataExchangeCustomStart( + uint8_t* txData, + uint16_t txDataLen, + uint8_t** rxData, + uint16_t** rvdLen, + uint32_t fwt, + uint32_t flags); + +/*! + ***************************************************************************** + * \brief RFAL NFC Get Data Exchange Status + * + * Gets current Data Exchange status + * + * \return ERR_NONE : Transceive done with no error + * \return ERR_BUSY : Transceive ongoing + * \return ERR_AGAIN : received one chaining block, copy received data + * and continue to call this method to retrieve the + * remaining blocks + * \return ERR_XXXX : Error occurred + * \return ERR_TIMEOUT : No response + * \return ERR_FRAMING : Framing error detected + * \return ERR_PAR : Parity error detected + * \return ERR_CRC : CRC error detected + * \return ERR_LINK_LOSS : Link Loss - External Field is Off + * \return ERR_RF_COLLISION : Collision detected + * \return ERR_IO : Internal error + ***************************************************************************** + */ +ReturnCode rfalNfcDataExchangeGetStatus(void); + +/*! + ***************************************************************************** + * \brief RFAL NFC Deactivate + * + * It triggers the deactivation procedure to terminate communications with + * remote device. At the end the field will be turned off. + * + * \param[in] discovery : TRUE if after deactivation go back into discovery + * : FALSE if after deactivation remain in idle + * + * \return ERR_WRONG_STATE : Incorrect state for this operation + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcDeactivate(bool discovery); + +#endif /* RFAL_NFC_H */ + +/** + * @} + * + * @} + * + * @} + */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_nfcDep.h b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_nfcDep.h new file mode 100644 index 00000000000..d5a1f5a7269 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_nfcDep.h @@ -0,0 +1,831 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_nfcDep.h + * + * \author Gustavo Patricio + * + * \brief Implementation of NFC-DEP protocol + * + * NFC-DEP is also known as NFCIP - Near Field Communication + * Interface and Protocol + * + * This implementation was based on the following specs: + * - NFC Forum Digital 1.1 + * - ECMA 340 3rd Edition 2013 + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-AL + * \brief RFAL Abstraction Layer + * @{ + * + * \addtogroup NFC-DEP + * \brief RFAL NFC-DEP Module + * @{ + */ + +#ifndef RFAL_NFCDEP_H_ +#define RFAL_NFCDEP_H_ + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "../platform.h" +#include "../st_errno.h" +#include "rfal_rf.h" + +/* + ****************************************************************************** + * ENABLE SWITCH + ****************************************************************************** + */ + +#ifndef RFAL_FEATURE_NFC_DEP +#define RFAL_FEATURE_NFC_DEP \ + false /*!< NFC-DEP module configuration missing. Disabled by default */ +#endif + +/* If module is disabled remove the need for the user to set lengths */ +#if !RFAL_FEATURE_NFC_DEP +#undef RFAL_FEATURE_NFC_DEP_BLOCK_MAX_LEN +#undef RFAL_FEATURE_NFC_DEP_PDU_MAX_LEN + +#define RFAL_FEATURE_NFC_DEP_BLOCK_MAX_LEN 1U /*!< NFC-DEP Block/Payload length, set to "none" */ +#define RFAL_FEATURE_NFC_DEP_PDU_MAX_LEN 1U /*!< NFC-DEP PDU length, set to "none" */ +#endif /* !RFAL_FEATURE_NFC_DEP */ + +/* + ****************************************************************************** + * DEFINES + ****************************************************************************** + */ +#define RFAL_NFCDEP_FRAME_SIZE_MAX_LEN \ + 254U /*!< Maximum Frame Size Digital 2.0 Table 90 */ +#define RFAL_NFCDEP_DEPREQ_HEADER_LEN \ + 5U /*!< DEP_REQ header length: CMD_TYPE + CMD_CMD + PBF + DID + NAD */ + +/*! Length NFCIP DEP REQ or RES header (incl LEN) */ +#define RFAL_NFCDEP_DEP_HEADER \ + (RFAL_NFCDEP_LEN_LEN + RFAL_NFCDEP_CMDTYPE_LEN + RFAL_NFCDEP_CMD_LEN + RFAL_NFCDEP_DEP_PFB_LEN) +#define RFAL_NFCDEP_HEADER \ + (RFAL_NFCDEP_CMDTYPE_LEN + RFAL_NFCDEP_CMD_LEN) /*!< NFCIP header length */ +#define RFAL_NFCDEP_SB_LEN \ + 1U /*!< SB length on NFCIP fram for NFC-A */ +#define RFAL_NFCDEP_LEN_LEN \ + 1U /*!< LEN length on NFCIP frame */ +#define RFAL_NFCDEP_CMDTYPE_LEN \ + 1U /*!< Length of the cmd type (REQ | RES) on NFCIP frame */ +#define RFAL_NFCDEP_CMD_LEN \ + 1U /*!< Length of the cmd on NFCIP frame */ +#define RFAL_NFCDEP_DID_LEN \ + 1U /*!< Length of did on NFCIP frame */ +#define RFAL_NFCDEP_DEP_PFB_LEN \ + 1U /*!< Length of the PFB field on NFCIP frame */ + +#define RFAL_NFCDEP_DSL_RLS_LEN_NO_DID \ + (RFAL_NFCDEP_LEN_LEN + RFAL_NFCDEP_CMDTYPE_LEN + \ + RFAL_NFCDEP_CMD_LEN) /*!< Length of DSL_REQ and RLS_REQ with no DID */ +#define RFAL_NFCDEP_DSL_RLS_LEN_DID \ + (RFAL_NFCDEP_DSL_RLS_LEN_NO_DID + \ + RFAL_NFCDEP_DID_LEN) /*!< Length of DSL_REQ and RLS_REQ with DID */ + +#define RFAL_NFCDEP_FS_VAL_MIN \ + 64U /*!< Minimum LR value */ +#define RFAL_NFCDEP_LR_VAL_MASK \ + 0x03U /*!< Bit mask for a LR value */ +#define RFAL_NFCDEP_PP_LR_MASK \ + 0x30U /*!< Bit mask for LR value in PP byte on a ATR REQ/RES */ +#define RFAL_NFCDEP_PP_LR_SHIFT \ + 4U /*!< Position of LR value in PP byte on a ATR REQ/RES */ + +#define RFAL_NFCDEP_DID_MAX \ + 14U /*!< Max DID value Digital 14.6.2.3 */ +#define RFAL_NFCDEP_DID_KEEP \ + 0xFFU /*!< Keep DID value already configured */ +#define RFAL_NFCDEP_DID_NO \ + 0x00U /*!< No DID shall be used */ +#define RFAL_NFCDEP_NAD_NO \ + 0x00U /*!< No NAD shall be used */ + +#define RFAL_NFCDEP_OPER_RTOX_REQ_DIS \ + 0x01U /*!< Operation config: RTOX REQ disable */ +#define RFAL_NFCDEP_OPER_RTOX_REQ_EN \ + 0x00U /*!< Operation config: RTOX REQ enable */ + +#define RFAL_NFCDEP_OPER_ATN_DIS \ + 0x00U /*!< Operation config: ATN disable */ +#define RFAL_NFCDEP_OPER_ATN_EN \ + 0x02U /*!< Operation config: ATN enable */ + +#define RFAL_NFCDEP_OPER_EMPTY_DEP_DIS \ + 0x04U /*!< Operation config: empty DEPs disable */ +#define RFAL_NFCDEP_OPER_EMPTY_DEP_EN \ + 0x00U /*!< Operation config: empty DEPs enable */ + +#define RFAL_NFCDEP_OPER_FULL_MI_DIS \ + 0x00U /*!< Operation config: full chaining DEPs disable */ +#define RFAL_NFCDEP_OPER_FULL_MI_EN \ + 0x08U /*!< Operation config: full chaining DEPs enable */ + +#define RFAL_NFCDEP_BRS_MAINTAIN \ + 0xC0U /*!< Value signalling that BR is to be maintained (no PSL) */ +#define RFAL_NFCDEP_BRS_Dx_MASK \ + 0x07U /*!< Value signalling that BR is to be maintained (no PSL) */ +#define RFAL_NFCDEP_BRS_DSI_POS \ + 3U /*!< Value signalling that BR is to be maintained (no PSL) */ + +#define RFAL_NFCDEP_WT_DELTA \ + (16U - RFAL_NFCDEP_WT_DELTA_ADJUST) /*!< NFC-DEP dWRT (adjusted) Digital 2.0 B.10 */ +#define RFAL_NFCDEP_WT_DELTA_ADJUST \ + 4U /*!< dWRT value adjustment */ + +#define RFAL_NFCDEP_ATR_REQ_NFCID3_POS \ + 2U /*!< NFCID3 offset in ATR_REQ frame */ +#define RFAL_NFCDEP_NFCID3_LEN \ + 10U /*!< NFCID3 Length */ + +#define RFAL_NFCDEP_LEN_MIN \ + 3U /*!< Minimum length byte LEN value */ +#define RFAL_NFCDEP_LEN_MAX \ + 255U /*!< Maximum length byte LEN value */ + +#define RFAL_NFCDEP_ATRRES_HEADER_LEN \ + 2U /*!< ATR RES Header Len: CmdType: 0xD5 + Cod: 0x01 */ +#define RFAL_NFCDEP_ATRRES_MIN_LEN \ + 17U /*!< Minimum length for an ATR RES */ +#define RFAL_NFCDEP_ATRRES_MAX_LEN \ + 64U /*!< Maximum length for an ATR RES Digital 1.0 14.6.1 */ +#define RFAL_NFCDEP_ATRREQ_MIN_LEN \ + 16U /*!< Minimum length for an ATR REQ */ +#define RFAL_NFCDEP_ATRREQ_MAX_LEN \ + RFAL_NFCDEP_ATRRES_MAX_LEN /*!< Maximum length for an ATR REQ Digital 1.0 14.6.1 */ + +#define RFAL_NFCDEP_GB_MAX_LEN \ + (RFAL_NFCDEP_ATRREQ_MAX_LEN - \ + RFAL_NFCDEP_ATRREQ_MIN_LEN) /*!< Maximum length the General Bytes on ATR Digital 1.1 16.6.3 */ + +#define RFAL_NFCDEP_WT_INI_DEFAULT \ + RFAL_NFCDEP_WT_INI_MAX /*!< WT Initiator default value Digital 1.0 14.6.3.8 */ +#define RFAL_NFCDEP_WT_INI_MIN 0U /*!< WT Initiator minimum value Digital 1.0 14.6.3.8 */ +#define RFAL_NFCDEP_WT_INI_MAX 14U /*!< WT Initiator maximum value Digital 1.0 14.6.3.8 A.10 */ +#define RFAL_NFCDEP_RWT_INI_MAX \ + rfalNfcDepWT2RWT(RFAL_NFCDEP_WT_INI_MAX) /*!< RWT Initiator maximum value */ + +#define RFAL_NFCDEP_WT_TRG_MAX_D10 8U /*!< WT target max Digital 1.0 14.6.3.8 A.10 */ +#define RFAL_NFCDEP_WT_TRG_MAX_D11 14U /*!< WT target max Digital 1.1 16.6.3.9 A.9 */ +#define RFAL_NFCDEP_WT_TRG_MAX_L13 10U /*!< WT target max [LLCP] 1.3 6.2.1 */ +#define RFAL_NFCDEP_WT_TRG_MAX \ + RFAL_NFCDEP_WT_TRG_MAX_D11 /*!< WT target max Digital x.x | LLCP x.x */ +#define RFAL_NFCDEP_RWT_TRG_MAX \ + rfalNfcDepWT2RWT(RFAL_NFCDEP_WT_TRG_MAX) /*!< RWT Initiator maximum value */ + +/*! Maximum Frame Waiting Time = ((256 * 16/fc)*2^FWImax) = ((256*16/fc)*2^14) = (1048576 / 64)/fc = (100000h*64)/fc */ +#define RFAL_NFCDEP_MAX_FWT ((uint32_t)1U << 20) + +#define RFAL_NFCDEP_WT_MASK \ + 0x0FU /*!< Bit mask for the Wait Time value */ + +#define RFAL_NFCDEP_BR_MASK_106 \ + 0x01U /*!< Enable mask bit rate 106 */ +#define RFAL_NFCDEP_BR_MASK_212 \ + 0x02U /*!< Enable mask bit rate 242 */ +#define RFAL_NFCDEP_BR_MASK_424 \ + 0x04U /*!< Enable mask bit rate 424 */ + +/* + ****************************************************************************** + * GLOBAL MACROS + ****************************************************************************** + */ + +#define rfalNfcDepWT2RWT(wt) \ + ((uint32_t)1U \ + << (((uint32_t)(wt) & RFAL_NFCDEP_WT_MASK) + \ + 12U)) /*!< Converts WT value to RWT (1/fc) */ + +/*! Returns the BRS value from the given bit rate */ +#define rfalNfcDepDx2BRS(br) \ + ((((uint8_t)(br) & RFAL_NFCDEP_BRS_Dx_MASK) << RFAL_NFCDEP_BRS_DSI_POS) | \ + ((uint8_t)(br) & RFAL_NFCDEP_BRS_Dx_MASK)) + +#define rfalNfcDepBRS2DRI(brs) \ + (uint8_t)( \ + (uint8_t)(brs) & \ + RFAL_NFCDEP_BRS_Dx_MASK) /*!< Returns the DRI value from the given BRS byte */ +#define rfalNfcDepBRS2DSI(brs) \ + (uint8_t)( \ + ((uint8_t)(brs) >> RFAL_NFCDEP_BRS_DSI_POS) & \ + RFAL_NFCDEP_BRS_Dx_MASK) /*!< Returns the DSI value from the given BRS byte */ + +#define rfalNfcDepPP2LR(PPx) \ + (((uint8_t)(PPx) & RFAL_NFCDEP_PP_LR_MASK) >> \ + RFAL_NFCDEP_PP_LR_SHIFT) /*!< Returns the LR value from the given PPx byte */ +#define rfalNfcDepLR2PP(LRx) \ + (((uint8_t)(LRx) << RFAL_NFCDEP_PP_LR_SHIFT) & \ + RFAL_NFCDEP_PP_LR_MASK) /*!< Returns the PP byte with the given LRx value */ + +/*! Returns the Frame size value from the given LRx value */ +#define rfalNfcDepLR2FS(LRx) \ + (uint16_t)( \ + MIN((RFAL_NFCDEP_FS_VAL_MIN * ((uint16_t)(LRx) + 1U)), RFAL_NFCDEP_FRAME_SIZE_MAX_LEN)) + +/*! + * Despite DIGITAL 1.0 14.6.2.1 stating that the last two bytes may filled with + * any value, some devices (Samsung Google Nexus) only accept when these are 0 */ +#define rfalNfcDepSetNFCID(dst, src, len) \ + ST_MEMSET((dst), 0x00, RFAL_NFCDEP_NFCID3_LEN); \ + if((len) > 0U) { \ + ST_MEMCPY((dst), (src), (len)); \ + } + +/* + ****************************************************************************** + * GLOBAL ENUMERATIONS + ****************************************************************************** + */ + +/*! Enumeration of NFC-DEP bit rate in ATR Digital 1.0 Table 93 and 94 */ +enum { + RFAL_NFCDEP_Bx_NO_HIGH_BR = 0x00, /*!< Peer supports no high bit rates */ + RFAL_NFCDEP_Bx_08_848 = 0x01, /*!< Peer also supports 848 */ + RFAL_NFCDEP_Bx_16_1695 = 0x02, /*!< Peer also supports 1695 */ + RFAL_NFCDEP_Bx_32_3390 = 0x04, /*!< Peer also supports 3390 */ + RFAL_NFCDEP_Bx_64_6780 = 0x08 /*!< Peer also supports 6780 */ +}; + +/*! Enumeration of NFC-DEP bit rate Divider in PSL Digital 1.0 Table 100 */ +enum { + RFAL_NFCDEP_Dx_01_106 = RFAL_BR_106, /*!< Divisor D = 1 : bit rate = 106 */ + RFAL_NFCDEP_Dx_02_212 = RFAL_BR_212, /*!< Divisor D = 2 : bit rate = 212 */ + RFAL_NFCDEP_Dx_04_424 = RFAL_BR_424, /*!< Divisor D = 4 : bit rate = 424 */ + RFAL_NFCDEP_Dx_08_848 = RFAL_BR_848, /*!< Divisor D = 8 : bit rate = 848 */ + RFAL_NFCDEP_Dx_16_1695 = RFAL_BR_1695, /*!< Divisor D = 16 : bit rate = 1695 */ + RFAL_NFCDEP_Dx_32_3390 = RFAL_BR_3390, /*!< Divisor D = 32 : bit rate = 3390 */ + RFAL_NFCDEP_Dx_64_6780 = RFAL_BR_6780 /*!< Divisor D = 64 : bit rate = 6780 */ +}; + +/*! Enumeration of NFC-DEP Length Reduction (LR) Digital 1.0 Table 91 */ +enum { + RFAL_NFCDEP_LR_64 = 0x00, /*!< Maximum payload size is 64 bytes */ + RFAL_NFCDEP_LR_128 = 0x01, /*!< Maximum payload size is 128 bytes */ + RFAL_NFCDEP_LR_192 = 0x02, /*!< Maximum payload size is 192 bytes */ + RFAL_NFCDEP_LR_254 = 0x03 /*!< Maximum payload size is 254 bytes */ +}; + +/* + ****************************************************************************** + * GLOBAL DATA TYPES + ****************************************************************************** + */ + +/*! NFC-DEP callback to check if upper layer has deactivation pending */ +typedef bool (*rfalNfcDepDeactCallback)(void); + +/*! Enumeration of the nfcip communication modes */ +typedef enum { + RFAL_NFCDEP_COMM_PASSIVE, /*!< Passive communication mode */ + RFAL_NFCDEP_COMM_ACTIVE /*!< Active communication mode */ +} rfalNfcDepCommMode; + +/*! Enumeration of the nfcip roles */ +typedef enum { + RFAL_NFCDEP_ROLE_INITIATOR, /*!< Perform as Initiator */ + RFAL_NFCDEP_ROLE_TARGET /*!< Perform as Target */ +} rfalNfcDepRole; + +/*! Struct that holds all NFCIP configs */ +typedef struct { + rfalNfcDepRole role; /*!< Current NFCIP role */ + rfalNfcDepCommMode commMode; /*!< Current NFCIP communication mode */ + uint8_t oper; /*!< Operation config similar to NCI 1.0 Table 81 */ + + uint8_t did; /*!< Current Device ID (DID) */ + uint8_t nad; /*!< Current Node Addressing (NAD) */ + uint8_t bs; /*!< Bit rate in Sending Direction */ + uint8_t br; /*!< Bit rate in Receiving Direction */ + uint8_t nfcid[RFAL_NFCDEP_NFCID3_LEN]; /*!< Pointer to the NFCID to be used */ + uint8_t nfcidLen; /*!< Length of the given NFCID in nfcid */ + uint8_t gb[RFAL_NFCDEP_GB_MAX_LEN]; /*!< Pointer General Bytes (GB) to be used */ + uint8_t gbLen; /*!< Length of the given GB in gb */ + uint8_t lr; /*!< Length Reduction (LR) to be used */ + uint8_t to; /*!< Timeout (TO) to be used */ + uint32_t fwt; /*!< Frame Waiting Time (FWT) to be used */ + uint32_t dFwt; /*!< Delta Frame Waiting Time (dFWT) to be used */ +} rfalNfcDepConfigs; + +/*! ATR_REQ command Digital 1.1 16.6.2 */ +typedef struct { + uint8_t CMD1; /*!< Command format 0xD4 */ + uint8_t CMD2; /*!< Command Value */ + uint8_t NFCID3[RFAL_NFCDEP_NFCID3_LEN]; /*!< NFCID3 value */ + uint8_t DID; /*!< DID */ + uint8_t BSi; /*!< Sending Bitrate for Initiator */ + uint8_t BRi; /*!< Receiving Bitrate for Initiator */ + uint8_t PPi; /*!< Optional Parameters presence indicator */ + uint8_t GBi[RFAL_NFCDEP_GB_MAX_LEN]; /*!< General Bytes */ +} rfalNfcDepAtrReq; + +/*! ATR_RES response Digital 1.1 16.6.3 */ +typedef struct { + uint8_t CMD1; /*!< Response Byte 0xD5 */ + uint8_t CMD2; /*!< Command Value */ + uint8_t NFCID3[RFAL_NFCDEP_NFCID3_LEN]; /*!< NFCID3 value */ + uint8_t DID; /*!< DID */ + uint8_t BSt; /*!< Sending Bitrate for Initiator */ + uint8_t BRt; /*!< Receiving Bitrate for Initiator */ + uint8_t TO; /*!< Timeout */ + uint8_t PPt; /*!< Optional Parameters presence indicator */ + uint8_t GBt[RFAL_NFCDEP_GB_MAX_LEN]; /*!< General Bytes */ +} rfalNfcDepAtrRes; + +/*! Structure of transmit I-PDU Buffer format from caller */ +typedef struct { + uint8_t prologue[RFAL_NFCDEP_DEPREQ_HEADER_LEN]; /*!< Prologue space for NFC-DEP header*/ + uint8_t inf[RFAL_FEATURE_NFC_DEP_BLOCK_MAX_LEN]; /*!< INF | Data area of the buffer */ +} rfalNfcDepBufFormat; + +/*! Structure of APDU Buffer format from caller */ +typedef struct { + uint8_t prologue[RFAL_NFCDEP_DEPREQ_HEADER_LEN]; /*!< Prologue/SoD buffer */ + uint8_t pdu[RFAL_FEATURE_NFC_DEP_PDU_MAX_LEN]; /*!< Complete PDU/Payload buffer */ +} rfalNfcDepPduBufFormat; + +/*! Activation info as Initiator and Target */ +typedef union { /* PRQA S 0750 # MISRA 19.2 - Both members of the union will not be used concurrently , device is only initiatior or target a time. No problem can occur. */ + struct { + rfalNfcDepAtrRes ATR_RES; /*!< ATR RES (Initiator mode) */ + uint8_t ATR_RESLen; /*!< ATR RES length (Initiator mode) */ + } Target; /*!< Target */ + struct { + rfalNfcDepAtrReq ATR_REQ; /*!< ATR REQ (Target mode) */ + uint8_t ATR_REQLen; /*!< ATR REQ length (Target mode) */ + } Initiator; /*!< Initiator */ +} rfalNfcDepActivation; + +/*! NFC-DEP device Info */ +typedef struct { + uint8_t GBLen; /*!< General Bytes length */ + uint8_t WT; /*!< WT to be used (ignored in Listen Mode) */ + uint32_t FWT; /*!< FWT to be used (1/fc)(ignored Listen Mode) */ + uint32_t dFWT; /*!< Delta FWT to be used (1/fc) */ + uint8_t LR; /*!< Length Reduction coding the max payload */ + uint16_t FS; /*!< Frame Size */ + rfalBitRate DSI; /*!< Bit Rate coding from Initiator to Target */ + rfalBitRate DRI; /*!< Bit Rate coding from Target to Initiator */ + uint8_t DID; /*!< Device ID (RFAL_NFCDEP_DID_NO if no DID) */ + uint8_t NAD; /*!< Node ADdress (RFAL_NFCDEP_NAD_NO if no NAD)*/ +} rfalNfcDepInfo; + +/*! NFC-DEP Device structure */ +typedef struct { + rfalNfcDepActivation activation; /*!< Activation Info */ + rfalNfcDepInfo info; /*!< NFC-DEP device Info */ +} rfalNfcDepDevice; + +/*! NFCIP Protocol structure for P2P Target + * + * operParam : derives from NFC-Forum NCI NFC-DEP Operation Parameter + * NCI 1.1 Table 86: NFC-DEP Operation Parameter + * and it's a bit mask composed as: + * [ 0000b + * | Chain SHALL use max. Transport Data Byte[1b] + * | I-PDU with no Transport Data SHALL NOT be sent [1b] + * | NFC-DEP Target SHALL NOT send RTOX request [1b] + * ] + * + */ +typedef struct { + rfalNfcDepCommMode commMode; /*!< Initiator in Active P2P or Passive P2P*/ + uint8_t operParam; /*!< NFC-DEP Operation Parameter */ + uint8_t* nfcid; /*!< Initiator's NFCID2 or NFCID3 */ + uint8_t nfcidLen; /*!< Initiator's NFCID length (NFCID2/3) */ + uint8_t DID; /*!< Initiator's Device ID DID */ + uint8_t NAD; /*!< Initiator's Node ID NAD */ + uint8_t BS; /*!< Initiator's Bit Rates supported in Tx */ + uint8_t BR; /*!< Initiator's Bit Rates supported in Rx */ + uint8_t LR; /*!< Initiator's Length reduction */ + uint8_t* GB; /*!< Initiator's General Bytes (Gi) */ + uint8_t GBLen; /*!< Initiator's General Bytes length */ +} rfalNfcDepAtrParam; + +/*! Structure of parameters to be passed in for nfcDepListenStartActivation */ +typedef struct { + rfalNfcDepBufFormat* rxBuf; /*!< Receive Buffer struct reference */ + uint16_t* rxLen; /*!< Receive INF data length in bytes */ + bool* isRxChaining; /*!< Received data is not complete */ + rfalNfcDepDevice* nfcDepDev; /*!< NFC-DEP device info */ +} rfalNfcDepListenActvParam; + +/*! NFCIP Protocol structure for P2P Target + * + * operParam : derives from NFC-Forum NCI NFC-DEP Operation Parameter + * NCI 1.1 Table 86: NFC-DEP Operation Parameter + * and it's a bit mask composed as: + * [ 0000b + * | Chain SHALL use max. Transport Data Byte[1b] + * | I-PDU with no Transport Data SHALL NOT be sent [1b] + * | NFC-DEP Target SHALL NOT send RTOX request [1b] + * ] + * + */ +typedef struct { + rfalNfcDepCommMode commMode; /*!< Target in Active P2P or Passive P2P */ + uint8_t nfcid3[RFAL_NFCDEP_NFCID3_LEN]; /*!< Target's NFCID3 */ + uint8_t bst; /*!< Target's Bit Rates supported in Tx */ + uint8_t brt; /*!< Target's Bit Rates supported in Rx */ + uint8_t to; /*!< Target's timeout (TO) value */ + uint8_t ppt; /*!< Target's Presence optional Params(PPt)*/ + uint8_t GBt[RFAL_NFCDEP_GB_MAX_LEN]; /*!< Target's General Bytes (Gt) */ + uint8_t GBtLen; /*!< Target's General Bytes length */ + uint8_t operParam; /*!< NFC-DEP Operation Parameter */ +} rfalNfcDepTargetParam; + +/*! Structure of parameters to be passed in for nfcDepStartIpduTransceive */ +typedef struct { + rfalNfcDepBufFormat* txBuf; /*!< Transmit Buffer struct reference */ + uint16_t txBufLen; /*!< Transmit Buffer INF field length in bytes */ + bool isTxChaining; /*!< Transmit data is not complete */ + rfalNfcDepBufFormat* rxBuf; /*!< Receive Buffer struct reference */ + uint16_t* rxLen; /*!< Receive INF data length */ + bool* isRxChaining; /*!< Received data is not complete */ + uint32_t FWT; /*!< FWT to be used (ignored in Listen Mode) */ + uint32_t dFWT; /*!< Delta FWT to be used */ + uint16_t FSx; /*!< Other device Frame Size (FSD or FSC) */ + uint8_t DID; /*!< Device ID (RFAL_ISODEP_NO_DID if no DID) */ +} rfalNfcDepTxRxParam; + +/*! Structure of parameters used on NFC DEP PDU Transceive */ +typedef struct { + rfalNfcDepPduBufFormat* txBuf; /*!< Transmit Buffer struct reference */ + uint16_t txBufLen; /*!< Transmit Buffer INF field length in Bytes*/ + rfalNfcDepPduBufFormat* rxBuf; /*!< Receive Buffer struct reference in Bytes */ + uint16_t* rxLen; /*!< Received INF data length in Bytes */ + rfalNfcDepBufFormat* tmpBuf; /*!< Temp buffer for single PDUs (internal) */ + uint32_t FWT; /*!< FWT to be used (ignored in Listen Mode) */ + uint32_t dFWT; /*!< Delta FWT to be used */ + uint16_t FSx; /*!< Other device Frame Size (FSD or FSC) */ + uint8_t DID; /*!< Device ID (RFAL_ISODEP_NO_DID if no DID) */ +} rfalNfcDepPduTxRxParam; + +/* + * ***************************************************************************** + * GLOBAL VARIABLE DECLARATIONS + ****************************************************************************** + */ + +/* + ****************************************************************************** + * GLOBAL FUNCTION PROTOTYPES + ****************************************************************************** + */ + +/*! + ****************************************************************************** + * \brief NFCIP Initialize + * + * This method resets all NFC-DEP inner states, counters and context and sets + * default values + * + ****************************************************************************** + */ +void rfalNfcDepInitialize(void); + +/*! + ****************************************************************************** + * \brief Set deactivating callback + * + * Sets the deactivating callback so that nfcip layer can check if upper layer + * has a deactivation pending, and not perform error recovery upon specific + * errors + * + * \param[in] pFunc : method pointer to deactivation flag check + ****************************************************************************** + */ +void rfalNfcDepSetDeactivatingCallback(rfalNfcDepDeactCallback pFunc); + +/*! + ****************************************************************************** + * \brief Calculate Response Waiting Time + * + * Calculates the Response Waiting Time (RWT) from the given Waiting Time (WT) + * + * \param[in] wt : the WT value to calculate RWT + * + * \return RWT value in 1/fc + ****************************************************************************** + */ +uint32_t rfalNfcDepCalculateRWT(uint8_t wt); + +/*! + ****************************************************************************** + * \brief NFC-DEP Initiator ATR (Attribute Request) + * + * This method configures the NFC-DEP layer with given parameters and then + * sends an ATR to the Target with and checks for a valid response response + * + * \param[in] param : parameters to initialize and compose the ATR + * \param[out] atrRes : location to store the ATR_RES + * \param[out] atrResLen : length of the ATR_RES received + * + * \return ERR_NONE : No error + * \return ERR_TIMEOUT : Timeout occurred + * \return ERR_PROTO : Protocol error occurred + ****************************************************************************** + */ +ReturnCode + rfalNfcDepATR(const rfalNfcDepAtrParam* param, rfalNfcDepAtrRes* atrRes, uint8_t* atrResLen); + +/*! + ****************************************************************************** + * \brief NFC-DEP Initiator PSL (Parameter Selection) + * + * This method sends a PSL to the Target with the given parameters and checks + * for a valid response response + * + * The parameters must be coded according to Digital 1.1 16.7.1 + * + * \param[in] BRS : the selected Bit Rates for Initiator and Target + * \param[in] FSL : the maximum length of Commands and Responses + * + * \return ERR_NONE : No error + * \return ERR_TIMEOUT : Timeout occurred + * \return ERR_PROTO : Protocol error occurred + ****************************************************************************** + */ +ReturnCode rfalNfcDepPSL(uint8_t BRS, uint8_t FSL); + +/*! + ****************************************************************************** + * \brief NFC-DEP Initiator DSL (Deselect) + * + * This method checks if the NFCIP module is configured as initiator and if + * so sends a DSL REQ, waits the target's response and checks it + * + * In case of performing as target no action is taken + * + * \return ERR_NONE : No error + * \return ERR_TIMEOUT : Timeout occurred + * \return ERR_MAX_RERUNS : Timeout occurred + * \return ERR_PROTO : Protocol error occurred + ****************************************************************************** + */ +ReturnCode rfalNfcDepDSL(void); + +/*! + ****************************************************************************** + * \brief NFC-DEP Initiator RLS (Release) + * + * This method checks if the NFCIP module is configured as initiator and if + * so sends a RLS REQ, waits target's response and checks it + * + * In case of performing as target no action is taken + * + * \return ERR_NONE : No error + * \return ERR_TIMEOUT : Timeout occurred + * \return ERR_MAX_RERUNS : Timeout occurred + * \return ERR_PROTO : Protocol error occurred + ****************************************************************************** + */ +ReturnCode rfalNfcDepRLS(void); + +/*! + ***************************************************************************** + * \brief NFC-DEP Initiator Handle Activation + * + * This performs a Activation into NFC-DEP layer with the given + * parameters. It sends ATR_REQ and if the higher bit rates are supported by + * both devices it additionally sends PSL + * Once Activated all details of the device are provided on nfcDepDev + * + * \param[in] param : required parameters to initialize and send ATR_REQ + * \param[in] desiredBR : Desired bit rate supported by the Poller + * \param[out] nfcDepDev : NFC-DEP information of the activated Listen device + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error + * \return ERR_PAR : Parity error detected + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error, activation successful + ***************************************************************************** + */ +ReturnCode rfalNfcDepInitiatorHandleActivation( + rfalNfcDepAtrParam* param, + rfalBitRate desiredBR, + rfalNfcDepDevice* nfcDepDev); + +/*! + ****************************************************************************** + * \brief Check if buffer contains valid ATR_REQ + * + * This method checks if the given ATR_REQ is valid + * + * + * \param[in] buf : buffer holding Initiator's received request + * \param[in] bufLen : size of the msg contained on the buf in Bytes + * \param[out] nfcid3 : pointer to where the NFCID3 may be outputted, + * nfcid3 has NFCF_SENSF_NFCID3_LEN as length + * Pass NULL if output parameter not desired + * + * \return true : Valid ATR_REQ received, the ATR_RES has been computed in txBuf + * \return false : Invalid protocol request + * + ****************************************************************************** + */ +bool rfalNfcDepIsAtrReq(const uint8_t* buf, uint16_t bufLen, uint8_t* nfcid3); + +/*! + ****************************************************************************** + * \brief Check is Target has received ATR + * + * This method checks if the NFCIP module is configured as target and if a + * ATR REQ has been received ( whether is in activation or in data exchange) + * + * \return true : a ATR has already been received + * \return false : no ATR has been received + ****************************************************************************** + */ +bool rfalNfcDepTargetRcvdATR(void); + +/*! + ***************************************************************************** + * \brief NFCDEP Start Listen Activation Handling + * + * Start Activation Handling and setup to receive first frame which may + * contain complete or partial DEP-REQ after activation is completed + * + * Pass in ATR_REQ for NFC-DEP to handle ATR_RES. The Activation Handling + * handles ATR_RES and PSL_RES if a PSL_REQ is received + * + * Activation is completed if PSL_RES is sent or if first I-PDU is received + * + * \ref rfalNfcDepListenGetActivationStatus() provide status of the + * ongoing activation + * + * \warning nfcDepGetTransceiveStatus() shall be called right after activation + * is completed (i.e. rfalNfcDepListenGetActivationStatus() return ERR_NONE) + * to check for first received frame. + * + * \param[in] param : Target parameters to be used + * \param[in] atrReq : reference to buffer containing ATR_REQ + * \param[in] atrReqLength: Length of ATR_REQ + * \param[out] rxParam : references to buffer, length and chaining indication + * for first complete LLCP to be received + * + * \return ERR_NONE : ATR_REQ is valid and activation ongoing + * \return ERR_PARAM : ATR_REQ or other params are invalid + * \return ERR_LINK_LOSS : Remote Field is turned off + ***************************************************************************** + */ +ReturnCode rfalNfcDepListenStartActivation( + const rfalNfcDepTargetParam* param, + const uint8_t* atrReq, + uint16_t atrReqLength, + rfalNfcDepListenActvParam rxParam); + +/*! + ***************************************************************************** + * \brief Get the current NFC-DEP Activation Status + * + * \return ERR_NONE : Activation has completed successfully + * \return ERR_BUSY : Activation is ongoing + * \return ERR_LINK_LOSS : Remote Field was turned off + ***************************************************************************** + */ +ReturnCode rfalNfcDepListenGetActivationStatus(void); + +/*! + ***************************************************************************** + * \brief Start Transceive + * + * Transceives a complete or partial DEP block + * + * The txBuf contains complete or partial of DEP to be transmitted. + * The Prologue field of the I-PDU is handled internally + * + * If the buffer contains partial LLCP and is not the last block, then + * isTxChaining must be set to true + * + * \param[in] param: reference parameters to be used for the Transceive + * + * \return ERR_PARAM : Bad request + * \return ERR_WRONG_STATE : The module is not in a proper state + * \return ERR_NONE : The Transceive request has been started + ***************************************************************************** + */ +ReturnCode rfalNfcDepStartTransceive(const rfalNfcDepTxRxParam* param); + +/*! + ***************************************************************************** + * \brief Return the Transceive status + * + * Returns the status of the NFC-DEP Transceive + * + * \warning When the other device is performing chaining once a chained + * block is received the error ERR_AGAIN is sent. At this point + * caller must handle the received data immediately. + * When ERR_AGAIN is returned an ACK has already been sent to + * the other device and the next block might be incoming. + * If rfalWorker() is called frequently it will place the next + * block on the given buffer + * + * \return ERR_NONE : Transceive has been completed successfully + * \return ERR_BUSY : Transceive is ongoing + * \return ERR_PROTO : Protocol error occurred + * \return ERR_TIMEOUT : Timeout error occurred + * \return ERR_SLEEP_REQ : Deselect has been received and responded + * \return ERR_NOMEM : The received I-PDU does not fit into the + * receive buffer + * \return ERR_LINK_LOSS : Communication is lost because Reader/Writer + * has turned off its field + * \return ERR_AGAIN : received one chaining block, continue to call + * this method to retrieve the remaining blocks + ***************************************************************************** + */ +ReturnCode rfalNfcDepGetTransceiveStatus(void); + +/*! + ***************************************************************************** + * \brief Start PDU Transceive + * + * This method triggers a NFC-DEP Transceive containing a complete PDU + * It transmits the given message and handles all protocol retransmitions, + * error handling and control messages + * + * The txBuf contains a complete PDU to be transmitted + * The Prologue field will be manipulated by the Transceive + * + * \warning the txBuf will be modified during the transmission + * \warning the maximum RF frame which can be received is limited by param.tmpBuf + * + * \param[in] param: reference parameters to be used for the Transceive + * + * \return ERR_PARAM : Bad request + * \return ERR_WRONG_STATE : The module is not in a proper state + * \return ERR_NONE : The Transceive request has been started + ***************************************************************************** + */ +ReturnCode rfalNfcDepStartPduTransceive(rfalNfcDepPduTxRxParam param); + +/*! + ***************************************************************************** + * \brief Return the PSU Transceive status + * + * Returns the status of the NFC-DEP PDU Transceive + * + * + * \return ERR_NONE : Transceive has been completed successfully + * \return ERR_BUSY : Transceive is ongoing + * \return ERR_PROTO : Protocol error occurred + * \return ERR_TIMEOUT : Timeout error occurred + * \return ERR_SLEEP_REQ : Deselect has been received and responded + * \return ERR_NOMEM : The received I-PDU does not fit into the + * receive buffer + * \return ERR_LINK_LOSS : Communication is lost because Reader/Writer + * has turned off its field + ***************************************************************************** + */ +ReturnCode rfalNfcDepGetPduTransceiveStatus(void); + +#endif /* RFAL_NFCDEP_H_ */ + +/** + * @} + * + * @} + * + * @} + */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_nfca.h b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_nfca.h new file mode 100644 index 00000000000..f7c5143077b --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_nfca.h @@ -0,0 +1,497 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_nfca.h + * + * \author Gustavo Patricio + * + * \brief Provides several NFC-A convenience methods and definitions + * + * It provides a Poller (ISO14443A PCD) interface and as well as + * some NFC-A Listener (ISO14443A PICC) helpers. + * + * The definitions and helpers methods provided by this module are only + * up to ISO14443-3 layer + * + * + * An usage example is provided here: \ref exampleRfalNfca.c + * \example exampleRfalNfca.c + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-AL + * \brief RFAL Abstraction Layer + * @{ + * + * \addtogroup NFC-A + * \brief RFAL NFC-A Module + * @{ + * + */ + +#ifndef RFAL_NFCA_H +#define RFAL_NFCA_H + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "../platform.h" +#include "../st_errno.h" +#include "rfal_rf.h" +#include "rfal_t1t.h" + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ + +#define RFAL_NFCA_CASCADE_1_UID_LEN \ + 4U /*!< UID length of cascade level 1 only tag */ +#define RFAL_NFCA_CASCADE_2_UID_LEN \ + 7U /*!< UID length of cascade level 2 only tag */ +#define RFAL_NFCA_CASCADE_3_UID_LEN \ + 10U /*!< UID length of cascade level 3 only tag */ + +#define RFAL_NFCA_SENS_RES_PLATFORM_MASK \ + 0x0FU /*!< SENS_RES (ATQA) platform configuration mask Digital 1.1 Table 10 */ +#define RFAL_NFCA_SENS_RES_PLATFORM_T1T \ + 0x0CU /*!< SENS_RES (ATQA) T1T platform configuration Digital 1.1 Table 10 */ + +#define RFAL_NFCA_SEL_RES_CONF_MASK \ + 0x60U /*!< SEL_RES (SAK) platform configuration mask Digital 1.1 Table 19 */ +#define RFAL_NFCA_SEL_RES_CONF_T2T \ + 0x00U /*!< SEL_RES (SAK) T2T configuration Digital 1.1 Table 19 */ +#define RFAL_NFCA_SEL_RES_CONF_T4T \ + 0x20U /*!< SEL_RES (SAK) T4T configuration Digital 1.1 Table 19 */ +#define RFAL_NFCA_SEL_RES_CONF_NFCDEP \ + 0x40U /*!< SEL_RES (SAK) NFC-DEP configuration Digital 1.1 Table 19 */ +#define RFAL_NFCA_SEL_RES_CONF_T4T_NFCDEP \ + 0x60U /*!< SEL_RES (SAK) T4T and NFC-DEP configuration Digital 1.1 Table 19 */ + +/*! NFC-A minimum FDT(listen) = ((n * 128 + (84)) / fc) with n_min = 9 Digital 1.1 6.10.1 + * = (1236)/fc + * Relax with 3etu: (3*128)/fc as with multiple NFC-A cards, response may take longer (JCOP cards) + * = (1236 + 384)/fc = 1620 / fc */ +#define RFAL_NFCA_FDTMIN 1620U +/* + ****************************************************************************** + * GLOBAL MACROS + ****************************************************************************** + */ + +/*! Checks if device is a T1T given its SENS_RES */ +#define rfalNfcaIsSensResT1T(sensRes) \ + ((((rfalNfcaSensRes*)(sensRes))->platformInfo & RFAL_NFCA_SENS_RES_PLATFORM_MASK) == \ + RFAL_NFCA_SENS_RES_PLATFORM_T1T) + +/*! Checks if device is a T2T given its SENS_RES */ +#define rfalNfcaIsSelResT2T(selRes) \ + ((((rfalNfcaSelRes*)(selRes))->sak & RFAL_NFCA_SEL_RES_CONF_MASK) == \ + RFAL_NFCA_SEL_RES_CONF_T2T) + +/*! Checks if device is a T4T given its SENS_RES */ +#define rfalNfcaIsSelResT4T(selRes) \ + ((((rfalNfcaSelRes*)(selRes))->sak & RFAL_NFCA_SEL_RES_CONF_MASK) == \ + RFAL_NFCA_SEL_RES_CONF_T4T) + +/*! Checks if device supports NFC-DEP protocol given its SENS_RES */ +#define rfalNfcaIsSelResNFCDEP(selRes) \ + ((((rfalNfcaSelRes*)(selRes))->sak & RFAL_NFCA_SEL_RES_CONF_MASK) == \ + RFAL_NFCA_SEL_RES_CONF_NFCDEP) + +/*! Checks if device supports ISO-DEP and NFC-DEP protocol given its SENS_RES */ +#define rfalNfcaIsSelResT4TNFCDEP(selRes) \ + ((((rfalNfcaSelRes*)(selRes))->sak & RFAL_NFCA_SEL_RES_CONF_MASK) == \ + RFAL_NFCA_SEL_RES_CONF_T4T_NFCDEP) + +/*! Checks if a NFC-A listener device supports multiple protocols (ISO-DEP and NFC-DEP) */ +#define rfalNfcaLisDevIsMultiProto(lisDev) \ + (((rfalNfcaListenDevice*)(lisDev))->type == RFAL_NFCA_T4T_NFCDEP) + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + +/*! NFC-A Listen device types */ +typedef enum { + RFAL_NFCA_T1T = + 0x01, /* Device configured for T1T Digital 1.1 Table 9 */ + RFAL_NFCA_T2T = + 0x00, /* Device configured for T2T Digital 1.1 Table 19 */ + RFAL_NFCA_T4T = + 0x20, /* Device configured for T4T Digital 1.1 Table 19 */ + RFAL_NFCA_NFCDEP = + 0x40, /* Device configured for NFC-DEP Digital 1.1 Table 19 */ + RFAL_NFCA_T4T_NFCDEP = + 0x60 /* Device configured for NFC-DEP and T4T Digital 1.1 Table 19 */ +} rfalNfcaListenDeviceType; + +/*! SENS_RES (ATQA) format Digital 1.1 6.6.3 & Table 7 */ +typedef struct { + uint8_t + anticollisionInfo; /*!< SENS_RES Anticollision Information */ + uint8_t + platformInfo; /*!< SENS_RES Platform Information */ +} rfalNfcaSensRes; + +/*! SDD_REQ (Anticollision) format Digital 1.1 6.7.1 & Table 11 */ +typedef struct { + uint8_t + selCmd; /*!< SDD_REQ SEL_CMD: cascade Level */ + uint8_t + selPar; /*!< SDD_REQ SEL_PAR: Byte Count[4b] | Bit Count[4b] (NVB: Number of Valid Bits)*/ +} rfalNfcaSddReq; + +/*! SDD_RES (UID CLn) format Digital 1.1 6.7.2 & Table 15 */ +typedef struct { + uint8_t nfcid1 + [RFAL_NFCA_CASCADE_1_UID_LEN]; /*!< NFCID1 cascade level NFCID */ + uint8_t bcc; /*!< BCC Exclusive-OR over first 4 bytes of SDD_RES */ +} rfalNfcaSddRes; + +/*! SEL_REQ (Select) format Digital 1.1 6.8.1 & Table 17 */ +typedef struct { + uint8_t + selCmd; /*!< SDD_REQ SEL_CMD: cascade Level */ + uint8_t + selPar; /*!< SDD_REQ SEL_PAR: Byte Count[4b] | Bit Count[4b] (NVB: Number of Valid Bits)*/ + uint8_t nfcid1 + [RFAL_NFCA_CASCADE_1_UID_LEN]; /*!< NFCID1 data */ + uint8_t bcc; /*!< Checksum calculated as exclusive-OR over the 4 bytes of NFCID1 CLn */ +} rfalNfcaSelReq; + +/*! SEL_RES (SAK) format Digital 1.1 6.8.2 & Table 19 */ +typedef struct { + uint8_t sak; /*!< Select Acknowledge */ +} rfalNfcaSelRes; + +/*! NFC-A listener device (PICC) struct */ +typedef struct { + rfalNfcaListenDeviceType + type; /*!< NFC-A Listen device type */ + rfalNfcaSensRes + sensRes; /*!< SENS_RES (ATQA) */ + rfalNfcaSelRes + selRes; /*!< SEL_RES (SAK) */ + uint8_t + nfcId1Len; /*!< NFCID1 Length */ + uint8_t nfcId1 + [RFAL_NFCA_CASCADE_3_UID_LEN]; /*!< NFCID1 (UID) */ +#ifdef RFAL_FEATURE_T1T + rfalT1TRidRes + ridRes; /*!< RID_RES */ +#endif /* RFAL_FEATURE_T1T */ + bool isSleep; /*!< Device sleeping flag */ +} rfalNfcaListenDevice; + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +/*! + ***************************************************************************** + * \brief Initialize NFC-A Poller mode + * + * This methods configures RFAL RF layer to perform as a + * NFC-A Poller/RW (ISO14443A PCD) including all default timings and bit rate + * to 106 kbps + + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcaPollerInitialize(void); + +/*! + ***************************************************************************** + * \brief NFC-A Poller Check Presence + * + * This method checks if a NFC-A Listen device (PICC) is present on the field + * by sending an ALL_REQ (WUPA) or SENS_REQ (REQA) + * + * \param[in] cmd : Indicate if to send an ALL_REQ or a SENS_REQ + * \param[out] sensRes : If received, the SENS_RES + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_RF_COLLISION : Collision detected one or more device in the field + * \return ERR_PAR : Parity error detected, one or more device in the field + * \return ERR_CRC : CRC error detected, one or more device in the field + * \return ERR_FRAMING : Framing error detected, one or more device in the field + * \return ERR_PROTO : Protocol error detected, one or more device in the field + * \return ERR_TIMEOUT : Timeout error, no listener device detected + * \return ERR_NONE : No error, one or more device in the field + ***************************************************************************** + */ +ReturnCode rfalNfcaPollerCheckPresence(rfal14443AShortFrameCmd cmd, rfalNfcaSensRes* sensRes); + +/*! + ***************************************************************************** + * \brief NFC-A Poller Select + * + * This method selects a NFC-A Listener device (PICC) + * + * \param[in] nfcid1 : Listener device NFCID1 to be selected + * \param[in] nfcidLen : Length of the NFCID1 to be selected + * \param[out] selRes : pointer to place the SEL_RES + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error + * \return ERR_PAR : Parity error detected + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error, SEL_RES received + ***************************************************************************** + */ +ReturnCode rfalNfcaPollerSelect(const uint8_t* nfcid1, uint8_t nfcidLen, rfalNfcaSelRes* selRes); + +/*! + ***************************************************************************** + * \brief NFC-A Poller Sleep + * + * This method sends a SLP_REQ (HLTA) + * No response is expected afterwards Digital 1.1 6.9.2.1 + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcaPollerSleep(void); + +/*! + ***************************************************************************** + * \brief NFC-A Technology Detection + * + * This method performs NFC-A Technology Detection as defined in the spec + * given in the compliance mode + * + * \param[in] compMode : compliance mode to be performed + * \param[out] sensRes : location to store the SENS_RES, if received + * + * When compMode is set to ISO compliance a SLP_REQ (HLTA) is not sent + * after detection. When set to EMV a ALL_REQ (WUPA) is sent instead of + * a SENS_REQ (REQA) + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_NONE : No error, one or more device in the field + ***************************************************************************** + */ +ReturnCode + rfalNfcaPollerTechnologyDetection(rfalComplianceMode compMode, rfalNfcaSensRes* sensRes); + +/*! + ***************************************************************************** + * \brief NFC-A Poller Collision Resolution + * + * Collision resolution for one NFC-A Listener device/card (PICC) as + * defined in Activity 2.1 9.3.4 + * + * This method executes anti collision loop and select the device with higher NFCID1 + * + * When devLimit = 0 it is configured to perform collision detection only. Once a collision + * is detected the collision resolution is aborted immediately. If only one device is found + * with no collisions, it will properly resolved. + * + * \param[in] devLimit : device limit value (CON_DEVICES_LIMIT) + * \param[out] collPending : pointer to collision pending flag (INT_COLL_PEND) + * \param[out] selRes : location to store the last Select Response from listener device (PICC) + * \param[out] nfcId1 : location to store the NFCID1 (UID), ensure RFAL_NFCA_CASCADE_3_UID_LEN + * \param[out] nfcId1Len : pointer to length of NFCID1 (UID) + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_PROTO : Card length invalid + * \return ERR_IGNORE : conDevLimit is 0 and there is a collision + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcaPollerSingleCollisionResolution( + uint8_t devLimit, + bool* collPending, + rfalNfcaSelRes* selRes, + uint8_t* nfcId1, + uint8_t* nfcId1Len); + +/*! + ***************************************************************************** + * \brief NFC-A Poller Full Collision Resolution + * + * Performs a full Collision resolution as defined in Activity 2.1 9.3.4 + * + * \param[in] compMode : compliance mode to be performed + * \param[in] devLimit : device limit value, and size nfcaDevList + * \param[out] nfcaDevList : NFC-A listener device info + * \param[out] devCnt : Devices found counter + * + * When compMode is set to ISO compliance it assumes that the device is + * not sleeping and therefore no ALL_REQ (WUPA) is sent at the beginning. + * When compMode is set to NFC compliance an additional ALL_REQ (WUPA) is sent + * at the beginning. + * + * + * When devLimit = 0 it is configured to perform collision detection only. Once a collision + * is detected the collision resolution is aborted immediately. If only one device is found + * with no collisions, it will properly resolved. + * + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcaPollerFullCollisionResolution( + rfalComplianceMode compMode, + uint8_t devLimit, + rfalNfcaListenDevice* nfcaDevList, + uint8_t* devCnt); + +/*! + ***************************************************************************** + * \brief NFC-A Poller Full Collision Resolution with Sleep + * + * Performs a full Collision resolution similar to rfalNfcaPollerFullCollisionResolution + * but an additional SLP_REQ (HLTA) -> SENS_RES (REQA) is sent regardless if there + * was a collision. + * This proprietary behaviour ensures proper activation of certain devices that suffer + * from influence of Type B commands as foreseen in ISO14443-3 5.2.3 or were somehow + * not detected by the first round of collision resolution + * + * \param[in] devLimit : device limit value, and size nfcaDevList + * \param[out] nfcaDevList : NFC-A listener device info + * \param[out] devCnt : Devices found counter + * + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcaPollerSleepFullCollisionResolution( + uint8_t devLimit, + rfalNfcaListenDevice* nfcaDevList, + uint8_t* devCnt); + +/*! + ***************************************************************************** + * \brief NFC-A Poller Start Full Collision Resolution + * + * This method starts the full Collision resolution as defined + * in Activity 1.0 or 1.1 9.3.4 + * + * \param[in] compMode : compliance mode to be performed + * \param[in] devLimit : device limit value, and size nfcaDevList + * \param[out] nfcaDevList : NFC-A listener device info + * \param[out] devCnt : Devices found counter + * + * When compMode is set to ISO compliance it assumes that the device is + * not sleeping and therefore no ALL_REQ (WUPA) is sent at the beginning. + * When compMode is set to NFC compliance an additional ALL_REQ (WUPA) is sent at + * the beginning. + * + * + * When devLimit = 0 it is configured to perform collision detection only. Once a collision + * is detected the collision resolution is aborted immediately. If only one device is found + * with no collisions, it will properly resolved. + * + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcaPollerStartFullCollisionResolution( + rfalComplianceMode compMode, + uint8_t devLimit, + rfalNfcaListenDevice* nfcaDevList, + uint8_t* devCnt); + +/*! + ***************************************************************************** + * \brief NFC-A Get Full Collision Resolution Status + * + * Returns the Collision Resolution status + * + * \return ERR_BUSY : Operation is ongoing + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error + * \return ERR_PAR : Parity error detected + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error, activation successful + ***************************************************************************** + */ +ReturnCode rfalNfcaPollerGetFullCollisionResolutionStatus(void); + +/*! + ***************************************************************************** + * \brief NFC-A Listener is SLP_REQ + * + * Checks if the given buffer contains valid NFC-A SLP_REQ (HALT) + * + * \param[in] buf: buffer containing data + * \param[in] bufLen: length of the data in buffer to be checked + * + * \return true if data in buf contains a SLP_REQ ; false otherwise + ***************************************************************************** + */ +bool rfalNfcaListenerIsSleepReq(const uint8_t* buf, uint16_t bufLen); + +#endif /* RFAL_NFCA_H */ + +/** + * @} + * + * @} + * + * @} + */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_nfcb.h b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_nfcb.h new file mode 100644 index 00000000000..d7ed9a41d8c --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_nfcb.h @@ -0,0 +1,425 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_nfcb.h + * + * \author Gustavo Patricio + * + * \brief Implementation of NFC-B (ISO14443B) helpers + * + * It provides a NFC-B Poller (ISO14443B PCD) interface and + * also provides some NFC-B Listener (ISO14443B PICC) helpers + * + * The definitions and helpers methods provided by this module are only + * up to ISO14443-3 layer (excluding ATTRIB) + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-AL + * \brief RFAL Abstraction Layer + * @{ + * + * \addtogroup NFC-B + * \brief RFAL NFC-B Module + * @{ + * + */ + +#ifndef RFAL_NFCB_H +#define RFAL_NFCB_H + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "../platform.h" +#include "../st_errno.h" +#include "rfal_rf.h" + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ + +#define RFAL_NFCB_FWTSENSB 7680U /*!< NFC-B FWT(SENSB) Digital 2.0 B.3 */ +#define RFAL_NFCB_DFWT 49152U /*!< NFC-B dFWT Delta 2.0 7.9.1.3 & B.3 */ +#define RFAL_NFCB_DTPOLL_10 rfalConvMsTo1fc(20) /*!< NFC-B Delta Tb Poll Digital 1.0 A.2 */ +#define RFAL_NFCB_DTPOLL_20 rfalConvMsTo1fc(17) /*!< NFC-B Delta Tb Poll Digital 2.1 B.3 */ + +#define RFAL_NFCB_AFI 0x00U /*!< NFC-B default Application Family Digital 1.1 7.6.1.1 */ +#define RFAL_NFCB_PARAM 0x00U /*!< NFC-B default SENSB_REQ PARAM */ +#define RFAL_NFCB_CRC_LEN 2U /*!< NFC-B CRC length and CRC_B(AID) Digital 1.1 Table 28 */ +#define RFAL_NFCB_NFCID0_LEN 4U /*!< Length of NFC-B NFCID0 */ +#define RFAL_NFCB_CMD_LEN 1U /*!< Length of NFC-B Command */ + +#define RFAL_NFCB_SENSB_RES_LEN 12U /*!< Standard length of SENSB_RES without SFGI byte */ +#define RFAL_NFCB_SENSB_RES_EXT_LEN \ + 13U /*!< Extended length of SENSB_RES with SFGI byte */ + +#define RFAL_NFCB_SENSB_REQ_ADV_FEATURE \ + 0x20U /*!< Bit mask for Advance Feature in SENSB_REQ */ +#define RFAL_NFCB_SENSB_RES_FSCI_MASK \ + 0x0FU /*!< Bit mask for FSCI value in SENSB_RES */ +#define RFAL_NFCB_SENSB_RES_FSCI_SHIFT \ + 4U /*!< Shift for FSCI value in SENSB_RES */ +#define RFAL_NFCB_SENSB_RES_PROTO_RFU_MASK \ + 0x08U /*!< Bit mask for Protocol Type RFU in SENSB_RES */ +#define RFAL_NFCB_SENSB_RES_PROTO_TR2_MASK \ + 0x03U /*!< Bit mask for Protocol Type TR2 in SENSB_RES */ +#define RFAL_NFCB_SENSB_RES_PROTO_TR2_SHIFT \ + 1U /*!< Shift for Protocol Type TR2 in SENSB_RES */ +#define RFAL_NFCB_SENSB_RES_PROTO_ISO_MASK \ + 0x01U /*!< Bit mask Protocol Type ISO14443 Compliant in SENSB_RES */ +#define RFAL_NFCB_SENSB_RES_FWI_MASK \ + 0x0FU /*!< Bit mask for FWI value in SENSB_RES */ +#define RFAL_NFCB_SENSB_RES_FWI_SHIFT \ + 4U /*!< Bit mask for FWI value in SENSB_RES */ +#define RFAL_NFCB_SENSB_RES_ADC_MASK \ + 0x0CU /*!< Bit mask for ADC value in SENSB_RES */ +#define RFAL_NFCB_SENSB_RES_ADC_ADV_FEATURE_MASK \ + 0x08U /*!< Bit mask for ADC.Advanced Proto Features in SENSB_RES */ +#define RFAL_NFCB_SENSB_RES_ADC_PROPRIETARY_MASK \ + 0x04U /*!< Bit mask for ADC.Proprietary Application in SENSB_RES */ +#define RFAL_NFCB_SENSB_RES_FO_DID_MASK \ + 0x01U /*!< Bit mask for DID in SENSB_RES */ +#define RFAL_NFCB_SENSB_RES_FO_NAD_MASK \ + 0x02U /*!< Bit mask for DID in SENSB_RES */ +#define RFAL_NFCB_SENSB_RES_FO_MASK \ + 0x03U /*!< Bit mask for FO value in SENSB_RES (NAD and DID) */ +#define RFAL_NFCB_SENSB_RES_SFGI_MASK \ + 0x0FU /*!< Bit mask for SFGI in SENSB_RES */ +#define RFAL_NFCB_SENSB_RES_SFGI_SHIFT \ + 4U /*!< Shift for SFGI in SENSB_RES */ + +/* +****************************************************************************** +* GLOBAL MACROS +****************************************************************************** +*/ + +/*! Get device's FSCI given its SENSB_RES Digital 1.1 7.6.2 */ +#define rfalNfcbGetFSCI(sensbRes) \ + ((((rfalNfcbSensbRes*)(sensbRes))->protInfo.FsciProType >> RFAL_NFCB_SENSB_RES_FSCI_SHIFT) & \ + RFAL_NFCB_SENSB_RES_FSCI_MASK) + +/*! Checks if the given NFC-B device indicates ISO-DEP support */ +#define rfalNfcbIsIsoDepSupported(dev) \ + ((((rfalNfcbListenDevice*)(dev))->sensbRes.protInfo.FsciProType & \ + RFAL_NFCB_SENSB_RES_PROTO_ISO_MASK) != 0U) + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + +/*! SENSB_REQ and ALLB_REQ param Digital 1.1 7.6.1 */ +typedef enum { + RFAL_NFCB_SENS_CMD_ALLB_REQ = 0x08, /*!< ALLB_REQ (WUPB) */ + RFAL_NFCB_SENS_CMD_SENSB_REQ = 0x00 /*!< SENSB_REQ (REQB) */ +} rfalNfcbSensCmd; + +/*! Number of Slots (NI) codes used for NFC-B anti collision Digital 1.1 Table 26 */ +typedef enum { + RFAL_NFCB_SLOT_NUM_1 = 0, /*!< N=0 : 1 slot */ + RFAL_NFCB_SLOT_NUM_2 = 1, /*!< N=1 : 2 slots */ + RFAL_NFCB_SLOT_NUM_4 = 2, /*!< N=2 : 4 slots */ + RFAL_NFCB_SLOT_NUM_8 = 3, /*!< N=3 : 8 slots */ + RFAL_NFCB_SLOT_NUM_16 = 4 /*!< N=4 : 16 slots */ +} rfalNfcbSlots; + +/*! SENSB_RES (ATQB) Application Data Format Digital 1.1 Table 28 */ +typedef struct { + uint8_t AFI; /*!< Application Family Identifier */ + uint8_t CRC_B[RFAL_NFCB_CRC_LEN]; /*!< CRC_B of AID */ + uint8_t numApps; /*!< Number of Applications */ +} rfalNfcbSensbResAppData; + +/*! SENSB_RES Protocol Info format Digital 1.1 Table 29 */ +typedef struct { + uint8_t + BRC; /*!< Bit Rate Capability */ + uint8_t + FsciProType; /*!< Frame Size Card Integer [4b] | Protocol Type[4 bits] */ + uint8_t + FwiAdcFo; /*!< Frame Waiting Integer [4b] | Application Data Coding [2b] | Frame Options [2b] */ + uint8_t + SFGI; /*!< Optional: Start-Up Frame Guard Time Integer[4b] | RFU [4b] */ +} rfalNfcbSensbResProtocolInfo; + +/*! SENSB_RES format Digital 1.1 7.6.2 */ +typedef struct { + uint8_t cmd; /*!< SENSB_RES: 50h */ + uint8_t nfcid0[RFAL_NFCB_NFCID0_LEN]; /*!< NFC Identifier (PUPI)*/ + rfalNfcbSensbResAppData appData; /*!< Application Data */ + rfalNfcbSensbResProtocolInfo protInfo; /*!< Protocol Information */ +} rfalNfcbSensbRes; + +/*! NFC-B listener device (PICC) struct */ +typedef struct { + uint8_t sensbResLen; /*!< SENSB_RES length */ + rfalNfcbSensbRes sensbRes; /*!< SENSB_RES */ + bool isSleep; /*!< Device sleeping flag */ +} rfalNfcbListenDevice; + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +/*! + ***************************************************************************** + * \brief Initialize NFC-B Poller mode + * + * This methods configures RFAL RF layer to perform as a + * NFC-B Poller/RW (ISO14443B PCD) including all default timings + * + * It sets NFC-B parameters (AFI, PARAM) to default values + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcbPollerInitialize(void); + +/*! + ***************************************************************************** + * \brief Set NFC-B Poller parameters + * + * This methods configures RFAL RF layer to perform as a + * NFCA Poller/RW (ISO14443A PCD) including all default timings + * + * Additionally configures NFC-B specific parameters to be used on the + * following communications + * + * \param[in] AFI : Application Family Identifier to be used + * \param[in] PARAM : PARAM to be used, it announces whether Advanced + * Features or Extended SENSB_RES is supported + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcbPollerInitializeWithParams(uint8_t AFI, uint8_t PARAM); + +/*! + ***************************************************************************** + * \brief NFC-B Poller Check Presence + * + * This method checks if a NFC-B Listen device (PICC) is present on the field + * by sending an ALLB_REQ (WUPB) or SENSB_REQ (REQB) + * + * \param[in] cmd : Indicate if to send an ALL_REQ or a SENS_REQ + * \param[in] slots : The number of slots to be announced + * \param[out] sensbRes : If received, the SENSB_RES + * \param[out] sensbResLen : If received, the SENSB_RES length + * + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error, no listener device detected + * \return ERR_RF_COLLISION : Collision detected one or more device in the field + * \return ERR_PAR : Parity error detected, one or more device in the field + * \return ERR_CRC : CRC error detected, one or more device in the field + * \return ERR_FRAMING : Framing error detected, one or more device in the field + * \return ERR_PROTO : Protocol error detected, invalid SENSB_RES received + * \return ERR_NONE : No error, SENSB_RES received + ***************************************************************************** + */ +ReturnCode rfalNfcbPollerCheckPresence( + rfalNfcbSensCmd cmd, + rfalNfcbSlots slots, + rfalNfcbSensbRes* sensbRes, + uint8_t* sensbResLen); + +/*! + ***************************************************************************** + * \brief NFC-B Poller Sleep + * + * This function is used to send the SLPB_REQ (HLTB) command to put the PICC with + * the given NFCID0 to state HALT so that they do not reply to further SENSB_REQ + * commands (only to ALLB_REQ) + * + * \param[in] nfcid0 : NFCID of the device to be put to Sleep + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcbPollerSleep(const uint8_t* nfcid0); + +/*! + ***************************************************************************** + * \brief NFC-B Poller Slot Marker + * + * This method selects a NFC-B Slot marker frame + * + * \param[in] slotCode : Slot Code [1-15] + * \param[out] sensbRes : If received, the SENSB_RES + * \param[out] sensbResLen : If received, the SENSB_RES length + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error + * \return ERR_PAR : Parity error detected + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error, SEL_RES received + ***************************************************************************** + */ +ReturnCode + rfalNfcbPollerSlotMarker(uint8_t slotCode, rfalNfcbSensbRes* sensbRes, uint8_t* sensbResLen); + +/*! + ***************************************************************************** + * \brief NFC-B Technology Detection + * + * This method performs NFC-B Technology Detection as defined in the spec + * given in the compliance mode + * + * \param[in] compMode : compliance mode to be performed + * \param[out] sensbRes : location to store the SENSB_RES, if received + * \param[out] sensbResLen : length of the SENSB_RES, if received + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_NONE : No error, one or more device in the field + ***************************************************************************** + */ +ReturnCode rfalNfcbPollerTechnologyDetection( + rfalComplianceMode compMode, + rfalNfcbSensbRes* sensbRes, + uint8_t* sensbResLen); + +/*! + ***************************************************************************** + * \brief NFC-B Poller Collision Resolution + * + * NFC-B Collision resolution Listener device/card (PICC) as + * defined in Activity 1.1 9.3.5 + * + * This function is used to perform collision resolution for detection in case + * of multiple NFC Forum Devices with Technology B detected. + * Target with valid SENSB_RES will be stored in devInfo and nfcbDevCount incremented. + * + * \param[in] compMode : compliance mode to be performed + * \param[in] devLimit : device limit value, and size nfcbDevList + * \param[out] nfcbDevList : NFC-B listener device info + * \param[out] devCnt : devices found counter + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcbPollerCollisionResolution( + rfalComplianceMode compMode, + uint8_t devLimit, + rfalNfcbListenDevice* nfcbDevList, + uint8_t* devCnt); + +/*! + ***************************************************************************** + * \brief NFC-B Poller Collision Resolution Slotted + * + * NFC-B Collision resolution Listener device/card (PICC). The sequence can + * be configured to be according to NFC Forum Activity 1.1 9.3.5, ISO10373 + * or EMVCo + * + * This function is used to perform collision resolution for detection in case + * of multiple NFC Forum Devices with Technology B are detected. + * Target with valid SENSB_RES will be stored in devInfo and nfcbDevCount incremented. + * + * This method provides the means to perform a collision resolution loop with specific + * initial and end number of slots. This allows to user to start the loop already with + * greater number of slots, and or limit the end number of slots. At the end a flag + * indicating whether there were collisions pending is returned. + * + * If RFAL_COMPLIANCE_MODE_ISO is used \a initSlots must be set to RFAL_NFCB_SLOT_NUM_1 + * + * + * \param[in] compMode : compliance mode to be performed + * \param[in] devLimit : device limit value, and size nfcbDevList + * \param[in] initSlots : number of slots to open initially + * \param[in] endSlots : number of slots when to stop collision resolution + * \param[out] nfcbDevList : NFC-B listener device info + * \param[out] devCnt : devices found counter + * \param[out] colPending : flag indicating whether collision are still pending + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcbPollerSlottedCollisionResolution( + rfalComplianceMode compMode, + uint8_t devLimit, + rfalNfcbSlots initSlots, + rfalNfcbSlots endSlots, + rfalNfcbListenDevice* nfcbDevList, + uint8_t* devCnt, + bool* colPending); + +/*! + ***************************************************************************** + * \brief NFC-B TR2 code to FDT + * + * Converts the TR2 code as defined in Digital 1.1 Table 33 Minimum + * TR2 Coding to Frame Delay Time (FDT) in 1/Fc + * + * \param[in] tr2Code : TR2 code as defined in Digital 1.1 Table 33 + * + * \return FDT in 1/Fc + ***************************************************************************** + */ +uint32_t rfalNfcbTR2ToFDT(uint8_t tr2Code); + +#endif /* RFAL_NFCB_H */ + +/** + * @} + * + * @} + * + * @} + */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_nfcf.h b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_nfcf.h new file mode 100644 index 00000000000..cc5197e369b --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_nfcf.h @@ -0,0 +1,403 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_nfcf.h + * + * \author Gustavo Patricio + * + * \brief Implementation of NFC-F Poller (FeliCa PCD) device + * + * The definitions and helpers methods provided by this module are + * aligned with NFC-F (FeliCa - JIS X6319-4) + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-AL + * \brief RFAL Abstraction Layer + * @{ + * + * \addtogroup NFC-F + * \brief RFAL NFC-F Module + * @{ + * + */ + +#ifndef RFAL_NFCF_H +#define RFAL_NFCF_H + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "../platform.h" +#include "../st_errno.h" +#include "rfal_rf.h" + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ + +#define RFAL_NFCF_NFCID2_LEN 8U /*!< NFCID2 (FeliCa IDm) length */ +#define RFAL_NFCF_SENSF_RES_LEN_MIN 16U /*!< SENSF_RES minimum length */ +#define RFAL_NFCF_SENSF_RES_LEN_MAX 18U /*!< SENSF_RES maximum length */ +#define RFAL_NFCF_SENSF_RES_PAD0_LEN 2U /*!< SENSF_RES PAD0 length */ +#define RFAL_NFCF_SENSF_RES_PAD1_LEN 2U /*!< SENSF_RES PAD1 length */ +#define RFAL_NFCF_SENSF_RES_RD_LEN 2U /*!< SENSF_RES Request Data length */ +#define RFAL_NFCF_SENSF_RES_BYTE1 1U /*!< SENSF_RES first byte value */ +#define RFAL_NFCF_SENSF_SC_LEN 2U /*!< Felica SENSF_REQ System Code length */ +#define RFAL_NFCF_SENSF_PARAMS_SC1_POS 0U /*!< System Code byte1 position in the SENSF_REQ */ +#define RFAL_NFCF_SENSF_PARAMS_SC2_POS 1U /*!< System Code byte2 position in the SENSF_REQ */ +#define RFAL_NFCF_SENSF_PARAMS_RC_POS 2U /*!< Request Code position in the SENSF_REQ */ +#define RFAL_NFCF_SENSF_PARAMS_TSN_POS 3U /*!< Time Slot Number position in the SENSF_REQ */ +#define RFAL_NFCF_POLL_MAXCARDS 16U /*!< Max number slots/cards 16 */ + +#define RFAL_NFCF_CMD_POS 0U /*!< Command/Response code length */ +#define RFAL_NFCF_CMD_LEN 1U /*!< Command/Response code length */ +#define RFAL_NFCF_LENGTH_LEN 1U /*!< LEN field length */ +#define RFAL_NFCF_HEADER_LEN (RFAL_NFCF_LENGTH_LEN + RFAL_NFCF_CMD_LEN) /*!< Header length*/ + +#define RFAL_NFCF_SENSF_NFCID2_BYTE1_POS \ + 0U /*!< NFCID2 byte1 position */ +#define RFAL_NFCF_SENSF_NFCID2_BYTE2_POS \ + 1U /*!< NFCID2 byte2 position */ + +#define RFAL_NFCF_SENSF_NFCID2_PROT_TYPE_LEN \ + 2U /*!< NFCID2 length for byte 1 and byte 2 indicating NFC-DEP or T3T support */ +#define RFAL_NFCF_SENSF_NFCID2_BYTE1_NFCDEP \ + 0x01U /*!< NFCID2 byte1 NFC-DEP support Digital 1.0 Table 44 */ +#define RFAL_NFCF_SENSF_NFCID2_BYTE2_NFCDEP \ + 0xFEU /*!< NFCID2 byte2 NFC-DEP support Digital 1.0 Table 44 */ + +#define RFAL_NFCF_SYSTEMCODE \ + 0xFFFFU /*!< SENSF_RES Default System Code Digital 1.0 6.6.1.1 */ + +#define RFAL_NFCF_BLOCK_LEN \ + 16U /*!< NFCF T3T Block size T3T 1.0 4.1 */ +#define RFAL_NFCF_CHECKUPDATE_RES_ST1_POS \ + 9U /*!< Check|Update Res Status Flag 1 position T3T 1.0 Table 8 */ +#define RFAL_NFCF_CHECKUPDATE_RES_ST2_POS \ + 10U /*!< Check|Update Res Status Flag 2 position T3T 1.0 Table 8 */ +#define RFAL_NFCF_CHECKUPDATE_RES_NOB_POS \ + 11U /*!< Check|Update Res Number of Blocks position T3T 1.0 Table 8 */ + +#define RFAL_NFCF_STATUS_FLAG_SUCCESS \ + 0x00U /*!< Check response Number of Blocks position T3T 1.0 Table 11 */ +#define RFAL_NFCF_STATUS_FLAG_ERROR \ + 0xFFU /*!< Check response Number of Blocks position T3T 1.0 Table 11 */ + +#define RFAL_NFCF_BLOCKLISTELEM_LEN \ + 0x80U /*!< Block List Element Length bit (2|3 bytes) T3T 1.0 5.6.1 */ + +#define RFAL_NFCF_SERVICECODE_RDONLY \ + 0x000BU /*!< NDEF Service Code as Read-Only T3T 1.0 7.2.1 */ +#define RFAL_NFCF_SERVICECODE_RDWR \ + 0x0009U /*!< NDEF Service Code as Read and Write T3T 1.0 7.2.1 */ + +/*! NFC-F Felica command set JIS X6319-4 9.1 */ +enum { + RFAL_NFCF_CMD_POLLING = + 0x00, /*!< SENSF_REQ (Felica Poll/REQC command to identify a card ) */ + RFAL_NFCF_CMD_POLLING_RES = + 0x01, /*!< SENSF_RES (Felica Poll/REQC command response ) */ + RFAL_NFCF_CMD_REQUEST_SERVICE = + 0x02, /*!< verify the existence of Area and Service */ + RFAL_NFCF_CMD_REQUEST_RESPONSE = + 0x04, /*!< verify the existence of a card */ + RFAL_NFCF_CMD_READ_WITHOUT_ENCRYPTION = + 0x06, /*!< read Block Data from a Service that requires no authentication */ + RFAL_NFCF_CMD_READ_WITHOUT_ENCRYPTION_RES = + 0x07, /*!< read Block Data response from a Service with no authentication */ + RFAL_NFCF_CMD_WRITE_WITHOUT_ENCRYPTION = + 0x08, /*!< write Block Data to a Service that requires no authentication */ + RFAL_NFCF_CMD_WRITE_WITHOUT_ENCRYPTION_RES = + 0x09, /*!< write Block Data response to a Service with no authentication */ + RFAL_NFCF_CMD_REQUEST_SYSTEM_CODE = + 0x0c, /*!< acquire the System Code registered to a card */ + RFAL_NFCF_CMD_AUTHENTICATION1 = + 0x10, /*!< authenticate a card */ + RFAL_NFCF_CMD_AUTHENTICATION2 = + 0x12, /*!< allow a card to authenticate a Reader/Writer */ + RFAL_NFCF_CMD_READ = + 0x14, /*!< read Block Data from a Service that requires authentication */ + RFAL_NFCF_CMD_WRITE = + 0x16, /*!< write Block Data to a Service that requires authentication */ +}; + +/* + ****************************************************************************** + * GLOBAL MACROS + ****************************************************************************** + */ + +/*! Checks if the given NFC-F device indicates NFC-DEP support */ +#define rfalNfcfIsNfcDepSupported(dev) \ + ((((rfalNfcfListenDevice*)(dev))->sensfRes.NFCID2[RFAL_NFCF_SENSF_NFCID2_BYTE1_POS] == \ + RFAL_NFCF_SENSF_NFCID2_BYTE1_NFCDEP) && \ + (((rfalNfcfListenDevice*)(dev))->sensfRes.NFCID2[RFAL_NFCF_SENSF_NFCID2_BYTE2_POS] == \ + RFAL_NFCF_SENSF_NFCID2_BYTE2_NFCDEP)) + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + +/*! NFC-F SENSF_RES format Digital 1.1 8.6.2 */ +typedef struct { + uint8_t CMD; /*!< Command Code: 01h */ + uint8_t NFCID2[RFAL_NFCF_NFCID2_LEN]; /*!< NFCID2 */ + uint8_t PAD0[RFAL_NFCF_SENSF_RES_PAD0_LEN]; /*!< PAD0 */ + uint8_t PAD1[RFAL_NFCF_SENSF_RES_PAD1_LEN]; /*!< PAD1 */ + uint8_t MRTIcheck; /*!< MRTIcheck */ + uint8_t MRTIupdate; /*!< MRTIupdate */ + uint8_t PAD2; /*!< PAD2 */ + uint8_t RD[RFAL_NFCF_SENSF_RES_RD_LEN]; /*!< Request Data */ +} rfalNfcfSensfRes; + +/*! NFC-F poller device (PCD) struct */ +typedef struct { + uint8_t NFCID2[RFAL_NFCF_NFCID2_LEN]; /*!< NFCID2 */ +} rfalNfcfPollDevice; + +/*! NFC-F listener device (PICC) struct */ +typedef struct { + uint8_t sensfResLen; /*!< SENF_RES length */ + rfalNfcfSensfRes sensfRes; /*!< SENF_RES */ +} rfalNfcfListenDevice; + +typedef uint16_t rfalNfcfServ; /*!< NFC-F Service Code */ + +/*! NFC-F Block List Element (2 or 3 bytes element) T3T 1.0 5.6.1 */ +typedef struct { + uint8_t conf; /*!< Access Mode | Serv Code List Order */ + uint16_t blockNum; /*!< Block Number */ +} rfalNfcfBlockListElem; + +/*! Check Update Service list and Block list parameter */ +typedef struct { + uint8_t numServ; /*!< Number of Services */ + rfalNfcfServ* servList; /*!< Service Code List */ + uint8_t numBlock; /*!< Number of Blocks */ + rfalNfcfBlockListElem* blockList; /*!< Block Number List */ +} rfalNfcfServBlockListParam; + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +/*! + ***************************************************************************** + * \brief Initialize NFC-F Poller mode + * + * This methods configures RFAL RF layer to perform as a + * NFC-F Poller/RW (FeliCa PCD) including all default timings + * + * \param[in] bitRate : NFC-F bitrate to be initialize (212 or 424) + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_PARAM : Incorrect bitrate + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcfPollerInitialize(rfalBitRate bitRate); + +/*! + ***************************************************************************** + * \brief NFC-F Poller Check Presence + * + * This function sends a Poll/SENSF command according to NFC Activity spec + * It detects if a NCF-F device is within range + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error, no listener device detected + * \return ERR_NONE : No error and some NFC-F device was detected + * + ***************************************************************************** + */ +ReturnCode rfalNfcfPollerCheckPresence(void); + +/*! + ***************************************************************************** + * \brief NFC-F Poller Poll + * + * This function sends to all PICCs in field the POLL command with the given + * number of slots. + * + * \param[in] slots : the number of slots to be performed + * \param[in] sysCode : as given in FeliCa poll command + * \param[in] reqCode : FeliCa communication parameters + * \param[out] cardList : Parameter of type rfalFeliCaPollRes which will hold the cards found + * \param[out] devCnt : actual number of cards found + * \param[out] collisions : number of collisions encountered + * + * \warning the list cardList has to be as big as the number of slots for the Poll + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error, no listener device detected + * \return ERR_NONE : No error and some NFC-F device was detected + * + ***************************************************************************** + */ +ReturnCode rfalNfcfPollerPoll( + rfalFeliCaPollSlots slots, + uint16_t sysCode, + uint8_t reqCode, + rfalFeliCaPollRes* cardList, + uint8_t* devCnt, + uint8_t* collisions); + +/*! + ***************************************************************************** + * \brief NFC-F Poller Full Collision Resolution + * + * Performs a full Collision resolution as defined in Activity 1.1 9.3.4 + * + * \param[in] compMode : compliance mode to be performed + * \param[in] devLimit : device limit value, and size nfcaDevList + * \param[out] nfcfDevList : NFC-F listener devices list + * \param[out] devCnt : Devices found counter + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcfPollerCollisionResolution( + rfalComplianceMode compMode, + uint8_t devLimit, + rfalNfcfListenDevice* nfcfDevList, + uint8_t* devCnt); + +/*! + ***************************************************************************** + * \brief NFC-F Poller Check/Read + * + * It computes a Check / Read command according to T3T 1.0 and JIS X6319-4 and + * sends it to PICC. If successfully, the rxBuf will contain the the number of + * blocks in the first byte followed by the blocks data. + * + * \param[in] nfcid2 : nfcid2 of the device + * \param[in] servBlock : parameter containing the list of Services and + * Blocks to be addressed by this command + * \param[out] rxBuf : buffer to place check/read data + * \param[in] rxBufLen : size of the rxBuf + * \param[out] rcvdLen : length of data placed in rxBuf + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_REQUEST : The request was executed with error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcfPollerCheck( + const uint8_t* nfcid2, + const rfalNfcfServBlockListParam* servBlock, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvdLen); + +/*! + ***************************************************************************** + * \brief NFC-F Poller Update/Write + * + * It computes a Update / Write command according to T3T 1.0 and JIS X6319-4 and + * sends it to PICC. + * + * \param[in] nfcid2 : nfcid2 of the device + * \param[in] servBlock : parameter containing the list of Services and + * Blocks to be addressed by this command + * \param[in] txBuf : buffer where the request will be composed + * \param[in] txBufLen : size of txBuf + * \param[in] blockData : data to written on the given block(s) + * \param[out] rxBuf : buffer to place check/read data + * \param[in] rxBufLen : size of the rxBuf + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_REQUEST : The request was executed with error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalNfcfPollerUpdate( + const uint8_t* nfcid2, + const rfalNfcfServBlockListParam* servBlock, + uint8_t* txBuf, + uint16_t txBufLen, + const uint8_t* blockData, + uint8_t* rxBuf, + uint16_t rxBufLen); + +/*! + ***************************************************************************** + * \brief NFC-F Listener is T3T Request + * + * This method checks if the given data is a valid T3T command (Read or Write) + * and in case a valid request has been received it may output the request's NFCID2 + * + * \param[in] buf : buffer holding Initiator's received command + * \param[in] bufLen : length of received command in bytes + * \param[out] nfcid2 : pointer to where the NFCID2 may be outputted, + * nfcid2 has NFCF_SENSF_NFCID2_LEN as length + * Pass NULL if output parameter not desired + * + * \return true : Valid T3T command (Read or Write) received + * \return false : Invalid protocol request + * + ***************************************************************************** + */ +bool rfalNfcfListenerIsT3TReq(const uint8_t* buf, uint16_t bufLen, uint8_t* nfcid2); + +#endif /* RFAL_NFCF_H */ + +/** + * @} + * + * @} + * + * @} + */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_nfcv.h b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_nfcv.h new file mode 100644 index 00000000000..e8ab097d6d2 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_nfcv.h @@ -0,0 +1,923 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_nfcv.h + * + * \author Gustavo Patricio + * + * \brief Implementation of NFC-V Poller (ISO15693) device + * + * The definitions and helpers methods provided by this module + * are aligned with NFC-V Digital 2.1 + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-AL + * \brief RFAL Abstraction Layer + * @{ + * + * \addtogroup NFC-V + * \brief RFAL NFC-V Module + * @{ + * + */ + +#ifndef RFAL_NFCV_H +#define RFAL_NFCV_H + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "../platform.h" +#include "../st_errno.h" +#include "rfal_rf.h" + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ + +#define RFAL_NFCV_UID_LEN 8U /*!< NFC-V UID length */ +#define RFAL_NFCV_MAX_BLOCK_LEN \ + 32U /*!< Max Block size: can be of up to 256 bits ISO 15693 2000 5 */ +#define RFAL_NFCV_BNO_LEN 1U /*!< NFC-V Block Number length */ +#define RFAL_NFCV_CRC_LEN 2U /*!< NFC-V CRC length */ +#define RFAL_NFCV_MAX_GEN_DATA_LEN \ + (RFAL_NFCV_MAX_BLOCK_LEN + RFAL_NFCV_BNO_LEN + RFAL_NFCV_UID_LEN) /*!
© COPYRIGHT 2020 STMicroelectronics
+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_rf.h + * + * \author Gustavo Patricio + * + * \brief RF Abstraction Layer (RFAL) + * + * RFAL (RF Abstraction Layer) provides several functionalities required to + * perform RF/NFC communications.
The RFAL encapsulates the different + * RF ICs (ST25R3911, ST25R391x, etc) into a common and easy to use interface. + * + * It provides interfaces to configure the RF IC, set/get timings, modes, bit rates, + * specific handlings, execute listen mode, etc. + * + * Furthermore it provides a common interface to perform a Transceive operations. + * The Transceive can be executed in a blocking or non blocking way.
+ * Additionally few specific Transceive methods are available to cope with the + * specifics of these particular operations. + * + * The most common interfaces are: + *
  rfalInitialize() + *
  rfalSetFDTPoll() + *
  rfalSetFDTListen() + *
  rfalSetGT() + *
  rfalSetBitRate() + *
  rfalSetMode() + *
  rfalFieldOnAndStartGT() + *
  rfalFieldOff() + *
  rfalStartTransceive() + *
  rfalGetTransceiveStatus() + *
  rfalTransceiveBlockingTxRx() + * + * An usage example is provided here: \ref exampleRfalPoller.c + * \example exampleRfalPoller.c + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-HAL + * \brief RFAL Hardware Abstraction Layer + * @{ + * + * \addtogroup RF + * \brief RFAL RF Abstraction Layer + * @{ + * + */ + +#ifndef RFAL_RF_H +#define RFAL_RF_H + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ +#include "../platform.h" +#include "../st_errno.h" +#include "../source/st25r3916/rfal_features.h" + +/* +****************************************************************************** +* GLOBAL DEFINES +****************************************************************************** +*/ +#define RFAL_VERSION 0x020200U /*!< RFAL Current Version: v2.2.0 */ + +#define RFAL_FWT_NONE 0xFFFFFFFFU /*!< Disabled FWT: Wait forever for a response */ +#define RFAL_GT_NONE RFAL_TIMING_NONE /*!< Disabled GT: No GT will be applied after Field On */ + +#define RFAL_TIMING_NONE 0x00U /*!< Timing disabled | Don't apply */ + +#define RFAL_1FC_IN_4096FC \ + (uint32_t)4096U /*!< Number of 1/fc cycles in one 4096/fc */ +#define RFAL_1FC_IN_512FC (uint32_t)512U /*!< Number of 1/fc cycles in one 512/fc */ +#define RFAL_1FC_IN_64FC (uint32_t)64U /*!< Number of 1/fc cycles in one 64/fc */ +#define RFAL_1FC_IN_8FC (uint32_t)8U /*!< Number of 1/fc cycles in one 8/fc */ +#define RFAL_US_IN_MS (uint32_t)1000U /*!< Number of us in one ms */ +#define RFAL_1MS_IN_1FC (uint32_t)13560U /*!< Number of 1/fc cycles in 1ms */ +#define RFAL_BITS_IN_BYTE (uint16_t)8U /*!< Number of bits in one byte */ + +#define RFAL_CRC_LEN 2U /*!< RF CRC LEN */ + +/*! Default TxRx flags: Tx CRC automatic, Rx CRC removed, NFCIP1 mode off, AGC On, Tx Parity automatic, Rx Parity removed */ +#define RFAL_TXRX_FLAGS_DEFAULT \ + ((uint32_t)RFAL_TXRX_FLAGS_CRC_TX_AUTO | (uint32_t)RFAL_TXRX_FLAGS_CRC_RX_REMV | \ + (uint32_t)RFAL_TXRX_FLAGS_NFCIP1_OFF | (uint32_t)RFAL_TXRX_FLAGS_AGC_ON | \ + (uint32_t)RFAL_TXRX_FLAGS_PAR_RX_REMV | (uint32_t)RFAL_TXRX_FLAGS_PAR_TX_AUTO | \ + (uint32_t)RFAL_TXRX_FLAGS_NFCV_FLAG_AUTO) +#define RFAL_TXRX_FLAGS_RAW \ + ((uint32_t)RFAL_TXRX_FLAGS_CRC_TX_MANUAL | (uint32_t)RFAL_TXRX_FLAGS_CRC_RX_KEEP | \ + (uint32_t)RFAL_TXRX_FLAGS_NFCIP1_OFF | (uint32_t)RFAL_TXRX_FLAGS_AGC_ON | \ + (uint32_t)RFAL_TXRX_FLAGS_PAR_RX_KEEP | (uint32_t)RFAL_TXRX_FLAGS_PAR_TX_NONE | \ + (uint32_t)RFAL_TXRX_FLAGS_NFCV_FLAG_AUTO) + +#define RFAL_LM_MASK_NFCA \ + ((uint32_t)1U \ + << (uint8_t)RFAL_MODE_LISTEN_NFCA) /*!< Bitmask for Listen Mode enabling NFCA */ +#define RFAL_LM_MASK_NFCB \ + ((uint32_t)1U \ + << (uint8_t)RFAL_MODE_LISTEN_NFCB) /*!< Bitmask for Listen Mode enabling NFCB */ +#define RFAL_LM_MASK_NFCF \ + ((uint32_t)1U \ + << (uint8_t)RFAL_MODE_LISTEN_NFCF) /*!< Bitmask for Listen Mode enabling NFCF */ +#define RFAL_LM_MASK_ACTIVE_P2P \ + ((uint32_t)1U \ + << (uint8_t)RFAL_MODE_LISTEN_ACTIVE_P2P) /*!< Bitmask for Listen Mode enabling AP2P */ + +#define RFAL_LM_SENS_RES_LEN 2U /*!< NFC-A SENS_RES (ATQA) length */ +#define RFAL_LM_SENSB_RES_LEN 13U /*!< NFC-B SENSB_RES (ATQB) length */ +#define RFAL_LM_SENSF_RES_LEN 19U /*!< NFC-F SENSF_RES length */ +#define RFAL_LM_SENSF_SC_LEN 2U /*!< NFC-F System Code length */ + +#define RFAL_NFCID3_LEN 10U /*!< NFCID3 length */ +#define RFAL_NFCID2_LEN 8U /*!< NFCID2 length */ +#define RFAL_NFCID1_TRIPLE_LEN 10U /*!< NFCID1 length */ +#define RFAL_NFCID1_DOUBLE_LEN 7U /*!< NFCID1 length */ +#define RFAL_NFCID1_SINGLE_LEN 4U /*!< NFCID1 length */ + +/* +****************************************************************************** +* GLOBAL MACROS +****************************************************************************** +*/ + +/*! Returns the maximum supported bit rate for RW mode. Caller must check if mode is supported before, as even if mode is not supported will return the min */ +#define rfalGetMaxBrRW() \ + (((RFAL_SUPPORT_BR_RW_6780) ? \ + RFAL_BR_6780 : \ + ((RFAL_SUPPORT_BR_RW_3390) ? \ + RFAL_BR_3390 : \ + ((RFAL_SUPPORT_BR_RW_1695) ? \ + RFAL_BR_1695 : \ + ((RFAL_SUPPORT_BR_RW_848) ? \ + RFAL_BR_848 : \ + ((RFAL_SUPPORT_BR_RW_424) ? \ + RFAL_BR_424 : \ + ((RFAL_SUPPORT_BR_RW_212) ? RFAL_BR_212 : RFAL_BR_106))))))) + +/*! Returns the maximum supported bit rate for AP2P mode. Caller must check if mode is supported before, as even if mode is not supported will return the min */ +#define rfalGetMaxBrAP2P() \ + (((RFAL_SUPPORT_BR_AP2P_848) ? \ + RFAL_BR_848 : \ + ((RFAL_SUPPORT_BR_AP2P_424) ? \ + RFAL_BR_424 : \ + ((RFAL_SUPPORT_BR_AP2P_212) ? RFAL_BR_212 : RFAL_BR_106)))) + +/*! Returns the maximum supported bit rate for CE-A mode. Caller must check if mode is supported before, as even if mode is not supported will return the min */ +#define rfalGetMaxBrCEA() \ + (((RFAL_SUPPORT_BR_CE_A_848) ? \ + RFAL_BR_848 : \ + ((RFAL_SUPPORT_BR_CE_A_424) ? \ + RFAL_BR_424 : \ + ((RFAL_SUPPORT_BR_CE_A_212) ? RFAL_BR_212 : RFAL_BR_106)))) + +/*! Returns the maximum supported bit rate for CE-B mode. Caller must check if mode is supported before, as even if mode is not supported will return the min */ +#define rfalGetMaxBrCEB() \ + (((RFAL_SUPPORT_BR_CE_B_848) ? \ + RFAL_BR_848 : \ + ((RFAL_SUPPORT_BR_CE_B_424) ? \ + RFAL_BR_424 : \ + ((RFAL_SUPPORT_BR_CE_B_212) ? RFAL_BR_212 : RFAL_BR_106)))) + +/*! Returns the maximum supported bit rate for CE-F mode. Caller must check if mode is supported before, as even if mode is not supported will return the min */ +#define rfalGetMaxBrCEF() (((RFAL_SUPPORT_BR_CE_F_424) ? RFAL_BR_424 : RFAL_BR_212)) + +#define rfalIsModeActiveComm(md) \ + (((md) == RFAL_MODE_POLL_ACTIVE_P2P) || \ + ((md) == RFAL_MODE_LISTEN_ACTIVE_P2P)) /*!< Checks if mode md is Active Communication */ +#define rfalIsModePassiveComm(md) \ + (!rfalIsModeActiveComm(md)) /*!< Checks if mode md is Passive Communication */ +#define rfalIsModePassiveListen(md) \ + (((md) == RFAL_MODE_LISTEN_NFCA) || ((md) == RFAL_MODE_LISTEN_NFCB) || \ + ((md) == RFAL_MODE_LISTEN_NFCF)) /*!< Checks if mode md is Passive Listen */ +#define rfalIsModePassivePoll(md) \ + (rfalIsModePassiveComm(md) && \ + !rfalIsModePassiveListen(md)) /*!< Checks if mode md is Passive Poll */ + +#define rfalConv1fcTo8fc(t) \ + (uint32_t)((uint32_t)(t) / RFAL_1FC_IN_8FC) /*!< Converts the given t from 1/fc to 8/fc */ +#define rfalConv8fcTo1fc(t) \ + (uint32_t)((uint32_t)(t) * RFAL_1FC_IN_8FC) /*!< Converts the given t from 8/fc to 1/fc */ + +#define rfalConv1fcTo64fc(t) \ + (uint32_t)((uint32_t)(t) / RFAL_1FC_IN_64FC) /*!< Converts the given t from 1/fc to 64/fc */ +#define rfalConv64fcTo1fc(t) \ + (uint32_t)((uint32_t)(t) * RFAL_1FC_IN_64FC) /*!< Converts the given t from 64/fc to 1/fc */ + +#define rfalConv1fcTo512fc(t) \ + (uint32_t)( \ + (uint32_t)(t) / RFAL_1FC_IN_512FC) /*!< Converts the given t from 1/fc to 512/fc */ +#define rfalConv512fcTo1fc(t) \ + (uint32_t)( \ + (uint32_t)(t) * RFAL_1FC_IN_512FC) /*!< Converts the given t from 512/fc to 1/fc */ + +#define rfalConv1fcTo4096fc(t) \ + (uint32_t)( \ + (uint32_t)(t) / RFAL_1FC_IN_4096FC) /*!< Converts the given t from 1/fc to 4096/fc */ +#define rfalConv4096fcTo1fc(t) \ + (uint32_t)( \ + (uint32_t)(t) * RFAL_1FC_IN_4096FC) /*!< Converts the given t from 4096/fc to 1/fc */ + +#define rfalConv1fcToMs(t) \ + (uint32_t)((uint32_t)(t) / RFAL_1MS_IN_1FC) /*!< Converts the given t from 1/fc to ms */ +#define rfalConvMsTo1fc(t) \ + (uint32_t)((uint32_t)(t) * RFAL_1MS_IN_1FC) /*!< Converts the given t from ms to 1/fc */ + +#define rfalConv1fcToUs(t) \ + (uint32_t)( \ + ((uint32_t)(t) * RFAL_US_IN_MS) / \ + RFAL_1MS_IN_1FC) /*!< Converts the given t from 1/fc to us */ +#define rfalConvUsTo1fc(t) \ + (uint32_t)( \ + ((uint32_t)(t) * RFAL_1MS_IN_1FC) / \ + RFAL_US_IN_MS) /*!< Converts the given t from us to 1/fc */ + +#define rfalConv64fcToMs(t) \ + (uint32_t)( \ + (uint32_t)(t) / \ + (RFAL_1MS_IN_1FC / RFAL_1FC_IN_64FC)) /*!< Converts the given t from 64/fc to ms */ +#define rfalConvMsTo64fc(t) \ + (uint32_t)( \ + (uint32_t)(t) * \ + (RFAL_1MS_IN_1FC / RFAL_1FC_IN_64FC)) /*!< Converts the given t from ms to 64/fc */ + +#define rfalConvBitsToBytes(n) \ + (uint16_t)( \ + ((uint16_t)(n) + (RFAL_BITS_IN_BYTE - 1U)) / \ + (RFAL_BITS_IN_BYTE)) /*!< Converts the given n from bits to bytes */ +#define rfalConvBytesToBits(n) \ + (uint32_t)( \ + (uint32_t)(n) * (RFAL_BITS_IN_BYTE)) /*!< Converts the given n from bytes to bits */ + +/*! Computes a Transceive context \a ctx with default flags and the lengths + * in bytes with the given arguments + * \a ctx : Transceive context to be assigned + * \a tB : txBuf the pointer to the buffer to be sent + * \a tBL : txBuf length in bytes + * \a rB : rxBuf the pointer to the buffer to place the received frame + * \a rBL : rxBuf length in bytes + * \a rBL : rxBuf length in bytes + * \a t : FWT to be used on this transceive in 1/fc + */ +#define rfalCreateByteTxRxContext(ctx, tB, tBL, rB, rBL, rdL, t) \ + (ctx).txBuf = (uint8_t*)(tB); \ + (ctx).txBufLen = (uint16_t)rfalConvBytesToBits(tBL); \ + (ctx).rxBuf = (uint8_t*)(rB); \ + (ctx).rxBufLen = (uint16_t)rfalConvBytesToBits(rBL); \ + (ctx).rxRcvdLen = (uint16_t*)(rdL); \ + (ctx).flags = (uint32_t)RFAL_TXRX_FLAGS_DEFAULT; \ + (ctx).fwt = (uint32_t)(t); + +/*! Computes a Transceive context \a ctx using lengths in bytes + * with the given flags and arguments + * \a ctx : Transceive context to be assigned + * \a tB : txBuf the pointer to the buffer to be sent + * \a tBL : txBuf length in bytes + * \a rB : rxBuf the pointer to the buffer to place the received frame + * \a rBL : rxBuf length in bytes + * \a rBL : rxBuf length in bytes + * \a t : FWT to be used on this transceive in 1/fc + */ +#define rfalCreateByteFlagsTxRxContext(ctx, tB, tBL, rB, rBL, rdL, fl, t) \ + (ctx).txBuf = (uint8_t*)(tB); \ + (ctx).txBufLen = (uint16_t)rfalConvBytesToBits(tBL); \ + (ctx).rxBuf = (uint8_t*)(rB); \ + (ctx).rxBufLen = (uint16_t)rfalConvBytesToBits(rBL); \ + (ctx).rxRcvdLen = (uint16_t*)(rdL); \ + (ctx).flags = (uint32_t)(fl); \ + (ctx).fwt = (uint32_t)(t); + +#define rfalLogE(...) \ + platformLog(__VA_ARGS__) /*!< Macro for the error log method */ +#define rfalLogW(...) \ + platformLog(__VA_ARGS__) /*!< Macro for the warning log method */ +#define rfalLogI(...) \ + platformLog(__VA_ARGS__) /*!< Macro for the info log method */ +#define rfalLogD(...) \ + platformLog(__VA_ARGS__) /*!< Macro for the debug log method */ + +/* +****************************************************************************** +* GLOBAL ENUMS +****************************************************************************** +*/ + +/* RFAL Guard Time (GT) default values */ +#define RFAL_GT_NFCA \ + rfalConvMsTo1fc( \ + 5U) /*!< GTA Digital 2.0 6.10.4.1 & B.2 */ +#define RFAL_GT_NFCB \ + rfalConvMsTo1fc( \ + 5U) /*!< GTB Digital 2.0 7.9.4.1 & B.3 */ +#define RFAL_GT_NFCF \ + rfalConvMsTo1fc( \ + 20U) /*!< GTF Digital 2.0 8.7.4.1 & B.4 */ +#define RFAL_GT_NFCV \ + rfalConvMsTo1fc( \ + 5U) /*!< GTV Digital 2.0 9.7.5.1 & B.5 */ +#define RFAL_GT_PICOPASS \ + rfalConvMsTo1fc( \ + 1U) /*!< GT Picopass */ +#define RFAL_GT_AP2P \ + rfalConvMsTo1fc( \ + 5U) /*!< TIRFG Ecma 340 11.1.1 */ +#define RFAL_GT_AP2P_ADJUSTED \ + rfalConvMsTo1fc( \ + 5U + \ + 25U) /*!< Adjusted GT for greater interoperability (Sony XPERIA P, Nokia N9, Huawei P2) */ + +/* RFAL Frame Delay Time (FDT) Listen default values */ +#define RFAL_FDT_LISTEN_NFCA_POLLER \ + 1172U /*!< FDTA,LISTEN,MIN (n=9) Last bit: Logic "1" - tnn,min/2 Digital 1.1 6.10 ; EMV CCP Spec Book D v2.01 4.8.1.3 */ +#define RFAL_FDT_LISTEN_NFCB_POLLER \ + 1008U /*!< TR0B,MIN Digital 1.1 7.1.3 & A.3 ; EMV CCP Spec Book D v2.01 4.8.1.3 & Table A.5 */ +#define RFAL_FDT_LISTEN_NFCF_POLLER \ + 2672U /*!< TR0F,LISTEN,MIN Digital 1.1 8.7.1.1 & A.4 */ +#define RFAL_FDT_LISTEN_NFCV_POLLER \ + 4310U /*!< FDTV,LISTEN,MIN t1 min Digital 2.1 B.5 ; ISO15693-3 2009 9.1 */ +#define RFAL_FDT_LISTEN_PICOPASS_POLLER \ + 3400U /*!< ISO15693 t1 min - observed adjustment */ +#define RFAL_FDT_LISTEN_AP2P_POLLER \ + 64U /*!< FDT AP2P No actual FDTListen is required as fields switch and collision avoidance */ +#define RFAL_FDT_LISTEN_NFCA_LISTENER \ + 1172U /*!< FDTA,LISTEN,MIN Digital 1.1 6.10 */ +#define RFAL_FDT_LISTEN_NFCB_LISTENER \ + 1024U /*!< TR0B,MIN Digital 1.1 7.1.3 & A.3 ; EMV CCP Spec Book D v2.01 4.8.1.3 & Table A.5 */ +#define RFAL_FDT_LISTEN_NFCF_LISTENER \ + 2688U /*!< TR0F,LISTEN,MIN Digital 2.1 8.7.1.1 & B.4 */ +#define RFAL_FDT_LISTEN_AP2P_LISTENER \ + 64U /*!< FDT AP2P No actual FDTListen exists as fields switch and collision avoidance */ + +/* RFAL Frame Delay Time (FDT) Poll default values */ +#define RFAL_FDT_POLL_NFCA_POLLER \ + 6780U /*!< FDTA,POLL,MIN Digital 1.1 6.10.3.1 & A.2 */ +#define RFAL_FDT_POLL_NFCA_T1T_POLLER \ + 384U /*!< RRDDT1T,MIN,B1 Digital 1.1 10.7.1 & A.5 */ +#define RFAL_FDT_POLL_NFCB_POLLER \ + 6780U /*!< FDTB,POLL,MIN = TR2B,MIN,DEFAULT Digital 1.1 7.9.3 & A.3 ; EMVCo 3.0 FDTB,PCD,MIN Table A.5 */ +#define RFAL_FDT_POLL_NFCF_POLLER \ + 6800U /*!< FDTF,POLL,MIN Digital 2.1 8.7.3 & B.4 */ +#define RFAL_FDT_POLL_NFCV_POLLER \ + 4192U /*!< FDTV,POLL Digital 2.1 9.7.3.1 & B.5 */ +#define RFAL_FDT_POLL_PICOPASS_POLLER \ + 1790U /*!< FDT Max */ +#define RFAL_FDT_POLL_AP2P_POLLER \ + 0U /*!< FDT AP2P No actual FDTPoll exists as fields switch and collision avoidance */ + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + +/*! RFAL modes */ +typedef enum { + RFAL_MODE_NONE = 0, /*!< No mode selected/defined */ + RFAL_MODE_POLL_NFCA = + 1, /*!< Mode to perform as NFCA (ISO14443A) Poller (PCD) */ + RFAL_MODE_POLL_NFCA_T1T = + 2, /*!< Mode to perform as NFCA T1T (Topaz) Poller (PCD) */ + RFAL_MODE_POLL_NFCB = + 3, /*!< Mode to perform as NFCB (ISO14443B) Poller (PCD) */ + RFAL_MODE_POLL_B_PRIME = + 4, /*!< Mode to perform as B' Calypso (Innovatron) (PCD) */ + RFAL_MODE_POLL_B_CTS = + 5, /*!< Mode to perform as CTS Poller (PCD) */ + RFAL_MODE_POLL_NFCF = + 6, /*!< Mode to perform as NFCF (FeliCa) Poller (PCD) */ + RFAL_MODE_POLL_NFCV = + 7, /*!< Mode to perform as NFCV (ISO15963) Poller (PCD) */ + RFAL_MODE_POLL_PICOPASS = + 8, /*!< Mode to perform as PicoPass / iClass Poller (PCD) */ + RFAL_MODE_POLL_ACTIVE_P2P = + 9, /*!< Mode to perform as Active P2P (ISO18092) Initiator */ + RFAL_MODE_LISTEN_NFCA = + 10, /*!< Mode to perform as NFCA (ISO14443A) Listener (PICC) */ + RFAL_MODE_LISTEN_NFCB = + 11, /*!< Mode to perform as NFCA (ISO14443B) Listener (PICC) */ + RFAL_MODE_LISTEN_NFCF = + 12, /*!< Mode to perform as NFCA (ISO15963) Listener (PICC) */ + RFAL_MODE_LISTEN_ACTIVE_P2P = + 13 /*!< Mode to perform as Active P2P (ISO18092) Target */ +} rfalMode; + +/*! RFAL Bit rates */ +typedef enum { + RFAL_BR_106 = 0, /*!< Bit Rate 106 kbit/s (fc/128) */ + RFAL_BR_212 = 1, /*!< Bit Rate 212 kbit/s (fc/64) */ + RFAL_BR_424 = 2, /*!< Bit Rate 424 kbit/s (fc/32) */ + RFAL_BR_848 = 3, /*!< Bit Rate 848 kbit/s (fc/16) */ + RFAL_BR_1695 = 4, /*!< Bit Rate 1695 kbit/s (fc/8) */ + RFAL_BR_3390 = 5, /*!< Bit Rate 3390 kbit/s (fc/4) */ + RFAL_BR_6780 = 6, /*!< Bit Rate 6780 kbit/s (fc/2) */ + RFAL_BR_13560 = 7, /*!< Bit Rate 13560 kbit/s (fc) */ + RFAL_BR_52p97 = 0xEB, /*!< Bit Rate 52.97 kbit/s (fc/256) Fast Mode VICC->VCD */ + RFAL_BR_26p48 = 0xEC, /*!< Bit Rate 26,48 kbit/s (fc/512) NFCV VICC->VCD & VCD->VICC 1of4 */ + RFAL_BR_1p66 = 0xED, /*!< Bit Rate 1,66 kbit/s (fc/8192) NFCV VCD->VICC 1of256 */ + RFAL_BR_KEEP = 0xFF /*!< Value indicating to keep the same previous bit rate */ +} rfalBitRate; + +/*! RFAL Compliance modes for upper modules */ +typedef enum { + RFAL_COMPLIANCE_MODE_NFC, /*!< Perform with NFC Forum 1.1 compliance */ + RFAL_COMPLIANCE_MODE_EMV, /*!< Perform with EMVCo compliance */ + RFAL_COMPLIANCE_MODE_ISO /*!< Perform with ISO10373 compliance */ +} rfalComplianceMode; + +/*! RFAL main states flags */ +typedef enum { + RFAL_STATE_IDLE = 0, + RFAL_STATE_INIT = 1, + RFAL_STATE_MODE_SET = 2, + + RFAL_STATE_TXRX = 3, + RFAL_STATE_LM = 4, + RFAL_STATE_WUM = 5 + +} rfalState; + +/*! RFAL transceive states */ +typedef enum { + RFAL_TXRX_STATE_IDLE = 0, + RFAL_TXRX_STATE_INIT = 1, + RFAL_TXRX_STATE_START = 2, + + RFAL_TXRX_STATE_TX_IDLE = 11, + RFAL_TXRX_STATE_TX_WAIT_GT = 12, + RFAL_TXRX_STATE_TX_WAIT_FDT = 13, + RFAL_TXRX_STATE_TX_TRANSMIT = 14, + RFAL_TXRX_STATE_TX_WAIT_WL = 15, + RFAL_TXRX_STATE_TX_RELOAD_FIFO = 16, + RFAL_TXRX_STATE_TX_WAIT_TXE = 17, + RFAL_TXRX_STATE_TX_DONE = 18, + RFAL_TXRX_STATE_TX_FAIL = 19, + + RFAL_TXRX_STATE_RX_IDLE = 81, + RFAL_TXRX_STATE_RX_WAIT_EON = 82, + RFAL_TXRX_STATE_RX_WAIT_RXS = 83, + RFAL_TXRX_STATE_RX_WAIT_RXE = 84, + RFAL_TXRX_STATE_RX_READ_FIFO = 85, + RFAL_TXRX_STATE_RX_ERR_CHECK = 86, + RFAL_TXRX_STATE_RX_READ_DATA = 87, + RFAL_TXRX_STATE_RX_WAIT_EOF = 88, + RFAL_TXRX_STATE_RX_DONE = 89, + RFAL_TXRX_STATE_RX_FAIL = 90, + +} rfalTransceiveState; + +/*! RFAL transceive flags */ +enum { + RFAL_TXRX_FLAGS_CRC_TX_AUTO = + (0U + << 0), /*!< CRC will be generated automatic upon transmission */ + RFAL_TXRX_FLAGS_CRC_TX_MANUAL = + (1U + << 0), /*!< CRC was calculated manually, included in txBuffer */ + RFAL_TXRX_FLAGS_CRC_RX_KEEP = + (1U + << 1), /*!< Upon Reception keep the CRC in rxBuffer (reflected on rcvd length) */ + RFAL_TXRX_FLAGS_CRC_RX_REMV = + (0U + << 1), /*!< Enable CRC check and remove the CRC from rxBuffer */ + RFAL_TXRX_FLAGS_NFCIP1_ON = + (1U + << 2), /*!< Enable NFCIP1 mode: Add SB(F0) and LEN bytes during Tx and skip SB(F0) byte during Rx */ + RFAL_TXRX_FLAGS_NFCIP1_OFF = + (0U + << 2), /*!< Disable NFCIP1 mode: do not append protocol bytes while Tx nor skip while Rx */ + RFAL_TXRX_FLAGS_AGC_OFF = + (1U + << 3), /*!< Disable Automatic Gain Control, improving multiple devices collision detection */ + RFAL_TXRX_FLAGS_AGC_ON = + (0U + << 3), /*!< Enable Automatic Gain Control, improving single device reception */ + RFAL_TXRX_FLAGS_PAR_RX_KEEP = + (1U + << 4), /*!< Disable Parity and CRC check and keep the Parity and CRC bits in the received buffer */ + RFAL_TXRX_FLAGS_PAR_RX_REMV = + (0U + << 0), /*!< Enable Parity check and remove the parity bits from the received buffer */ + RFAL_TXRX_FLAGS_PAR_TX_NONE = + (1U + << 5), /*!< Disable automatic Parity generation (ISO14443A) and use the one provided in the buffer*/ + RFAL_TXRX_FLAGS_PAR_TX_AUTO = + (0U + << 5), /*!< Enable automatic Parity generation (ISO14443A) */ + RFAL_TXRX_FLAGS_NFCV_FLAG_MANUAL = + (1U + << 6), /*!< Disable automatic adaption of flag byte (ISO15693) according to current comm params */ + RFAL_TXRX_FLAGS_NFCV_FLAG_AUTO = + (0U + << 6), /*!< Enable automatic adaption of flag byte (ISO115693) according to current comm params */ +}; + +/*! RFAL error handling */ +typedef enum { + RFAL_ERRORHANDLING_NONE = + 0, /*!< No special error handling will be performed */ + RFAL_ERRORHANDLING_NFC = + 1, /*!< Error handling set to perform as NFC compliant device */ + RFAL_ERRORHANDLING_EMVCO = + 2 /*!< Error handling set to perform as EMVCo compliant device */ +} rfalEHandling; + +/*! Struct that holds all context to be used on a Transceive */ +typedef struct { + uint8_t* txBuf; /*!< (In) Buffer where outgoing message is located */ + uint16_t txBufLen; /*!< (In) Length of the outgoing message in bits */ + + uint8_t* rxBuf; /*!< (Out) Buffer where incoming message will be placed */ + uint16_t rxBufLen; /*!< (In) Maximum length of the incoming message in bits */ + uint16_t* rxRcvdLen; /*!< (Out) Actual received length in bits */ + + uint32_t flags; /*!< (In) TransceiveFlags indication special handling */ + uint32_t fwt; /*!< (In) Frame Waiting Time in 1/fc */ +} rfalTransceiveContext; + +/*! System callback to indicate an event that requires a system reRun */ +typedef void (*rfalUpperLayerCallback)(void); + +/*! Callback to be executed before a Transceive */ +typedef void (*rfalPreTxRxCallback)(void* context); + +/*! Callback to be executed after a Transceive */ +typedef void (*rfalPostTxRxCallback)(void* context); + +/** Callback to be executed on each RFAL state change */ +typedef void (*RfalStateChangedCallback)(void* context); + +/*******************************************************************************/ +/* ISO14443A */ +/*******************************************************************************/ + +/*! RFAL ISO 14443A Short Frame Command */ +typedef enum { + RFAL_14443A_SHORTFRAME_CMD_WUPA = 0x52, /*!< ISO14443A WUPA / NFC-A ALL_REQ */ + RFAL_14443A_SHORTFRAME_CMD_REQA = 0x26 /*!< ISO14443A REQA / NFC-A SENS_REQ */ +} rfal14443AShortFrameCmd; + +/*******************************************************************************/ + +/*******************************************************************************/ +/* FeliCa */ +/*******************************************************************************/ + +#define RFAL_FELICA_LEN_LEN \ + 1U /*!< FeliCa LEN byte length */ +#define RFAL_FELICA_POLL_REQ_LEN \ + (RFAL_FELICA_LEN_LEN + 1U + 2U + 1U + \ + 1U) /*!< FeliCa Poll Request length (LEN + CMD + SC + RC + TSN) */ +#define RFAL_FELICA_POLL_RES_LEN \ + (RFAL_FELICA_LEN_LEN + 1U + 8U + 8U + \ + 2U) /*!< Maximum FeliCa Poll Response length (LEN + CMD + NFCID2 + PAD + RD) */ +#define RFAL_FELICA_POLL_MAX_SLOTS \ + 16U /*!< Maximum number of slots (TSN) on FeliCa Poll */ + +/*! NFC-F RC (Request Code) codes NFC Forum Digital 1.1 Table 42 */ +enum { + RFAL_FELICA_POLL_RC_NO_REQUEST = + 0x00, /*!< RC: No System Code information requested */ + RFAL_FELICA_POLL_RC_SYSTEM_CODE = + 0x01, /*!< RC: System Code information requested */ + RFAL_FELICA_POLL_RC_COM_PERFORMANCE = + 0x02 /*!< RC: Advanced protocol features supported */ +}; + +/*! NFC-F TSN (Time Slot Number) codes NFC Forum Digital 1.1 Table 43 */ +typedef enum { + RFAL_FELICA_1_SLOT = 0, /*!< TSN with number of Time Slots: 1 */ + RFAL_FELICA_2_SLOTS = 1, /*!< TSN with number of Time Slots: 2 */ + RFAL_FELICA_4_SLOTS = 3, /*!< TSN with number of Time Slots: 4 */ + RFAL_FELICA_8_SLOTS = 7, /*!< TSN with number of Time Slots: 8 */ + RFAL_FELICA_16_SLOTS = 15 /*!< TSN with number of Time Slots: 16 */ +} rfalFeliCaPollSlots; + +/*! NFCF Poll Response NFC Forum Digital 1.1 Table 44 */ +typedef uint8_t rfalFeliCaPollRes[RFAL_FELICA_POLL_RES_LEN]; + +/*******************************************************************************/ + +/*******************************************************************************/ +/* Listen Mode */ +/*******************************************************************************/ + +/*! RFAL Listen Mode NFCID Length */ +typedef enum { + RFAL_LM_NFCID_LEN_04 = RFAL_NFCID1_SINGLE_LEN, /*!< Listen mode indicates 4 byte NFCID */ + RFAL_LM_NFCID_LEN_07 = RFAL_NFCID1_DOUBLE_LEN, /*!< Listen mode indicates 7 byte NFCID */ + RFAL_LM_NFCID_LEN_10 = RFAL_NFCID1_TRIPLE_LEN, /*!< Listen mode indicates 10 byte NFCID */ +} rfalLmNfcidLen; + +/*! RFAL Listen Mode States */ +typedef enum { + RFAL_LM_STATE_NOT_INIT = 0x00, /*!< Not Initialized state */ + RFAL_LM_STATE_POWER_OFF = 0x01, /*!< Power Off state */ + RFAL_LM_STATE_IDLE = 0x02, /*!< Idle state Activity 1.1 5.2 */ + RFAL_LM_STATE_READY_A = 0x03, /*!< Ready A state Activity 1.1 5.3 5.4 & 5.5 */ + RFAL_LM_STATE_READY_B = 0x04, /*!< Ready B state Activity 1.1 5.11 5.12 */ + RFAL_LM_STATE_READY_F = 0x05, /*!< Ready F state Activity 1.1 5.15 */ + RFAL_LM_STATE_ACTIVE_A = 0x06, /*!< Active A state Activity 1.1 5.6 */ + RFAL_LM_STATE_CARDEMU_4A = 0x07, /*!< Card Emulation 4A state Activity 1.1 5.10 */ + RFAL_LM_STATE_CARDEMU_4B = 0x08, /*!< Card Emulation 4B state Activity 1.1 5.14 */ + RFAL_LM_STATE_CARDEMU_3 = 0x09, /*!< Card Emulation 3 state Activity 1.1 5.18 */ + RFAL_LM_STATE_TARGET_A = 0x0A, /*!< Target A state Activity 1.1 5.9 */ + RFAL_LM_STATE_TARGET_F = 0x0B, /*!< Target F state Activity 1.1 5.17 */ + RFAL_LM_STATE_SLEEP_A = 0x0C, /*!< Sleep A state Activity 1.1 5.7 */ + RFAL_LM_STATE_SLEEP_B = 0x0D, /*!< Sleep B state Activity 1.1 5.13 */ + RFAL_LM_STATE_READY_Ax = 0x0E, /*!< Ready A* state Activity 1.1 5.3 5.4 & 5.5 */ + RFAL_LM_STATE_ACTIVE_Ax = 0x0F, /*!< Active A* state Activity 1.1 5.6 */ + RFAL_LM_STATE_SLEEP_AF = 0x10, /*!< Sleep AF state Activity 1.1 5.19 */ +} rfalLmState; + +/*! RFAL Listen Mode Passive A configs */ +typedef struct { + rfalLmNfcidLen nfcidLen; /*!< NFCID Len (4, 7 or 10 bytes) */ + uint8_t nfcid[RFAL_NFCID1_TRIPLE_LEN]; /*!< NFCID */ + uint8_t SENS_RES[RFAL_LM_SENS_RES_LEN]; /*!< NFC-106k; SENS_REQ Response */ + uint8_t SEL_RES; /*!< SEL_RES (SAK) with complete NFCID1 (UID) */ +} rfalLmConfPA; + +/*! RFAL Listen Mode Passive B configs */ +typedef struct { + uint8_t SENSB_RES[RFAL_LM_SENSB_RES_LEN]; /*!< SENSF_RES */ +} rfalLmConfPB; + +/*! RFAL Listen Mode Passive F configs */ +typedef struct { + uint8_t SC[RFAL_LM_SENSF_SC_LEN]; /*!< System Code to listen for */ + uint8_t SENSF_RES[RFAL_LM_SENSF_RES_LEN]; /*!< SENSF_RES */ +} rfalLmConfPF; + +/*******************************************************************************/ + +/*******************************************************************************/ +/* Wake-Up Mode */ +/*******************************************************************************/ + +#define RFAL_WUM_REFERENCE_AUTO 0xFFU /*!< Indicates new reference is set by the driver*/ + +/*! RFAL Wake-Up Mode States */ +typedef enum { + RFAL_WUM_STATE_NOT_INIT = 0x00, /*!< Not Initialized state */ + RFAL_WUM_STATE_ENABLED = 0x01, /*!< Wake-Up mode is enabled */ + RFAL_WUM_STATE_ENABLED_WOKE = 0x02, /*!< Wake-Up mode enabled and has received IRQ(s)*/ +} rfalWumState; + +/*! RFAL Wake-Up Period/Timer */ +typedef enum { + RFAL_WUM_PERIOD_10MS = 0x00, /*!< Wake-Up timer 10ms */ + RFAL_WUM_PERIOD_20MS = 0x01, /*!< Wake-Up timer 20ms */ + RFAL_WUM_PERIOD_30MS = 0x02, /*!< Wake-Up timer 30ms */ + RFAL_WUM_PERIOD_40MS = 0x03, /*!< Wake-Up timer 40ms */ + RFAL_WUM_PERIOD_50MS = 0x04, /*!< Wake-Up timer 50ms */ + RFAL_WUM_PERIOD_60MS = 0x05, /*!< Wake-Up timer 60ms */ + RFAL_WUM_PERIOD_70MS = 0x06, /*!< Wake-Up timer 70ms */ + RFAL_WUM_PERIOD_80MS = 0x07, /*!< Wake-Up timer 80ms */ + RFAL_WUM_PERIOD_100MS = 0x10, /*!< Wake-Up timer 100ms */ + RFAL_WUM_PERIOD_200MS = 0x11, /*!< Wake-Up timer 200ms */ + RFAL_WUM_PERIOD_300MS = 0x12, /*!< Wake-Up timer 300ms */ + RFAL_WUM_PERIOD_400MS = 0x13, /*!< Wake-Up timer 400ms */ + RFAL_WUM_PERIOD_500MS = 0x14, /*!< Wake-Up timer 500ms */ + RFAL_WUM_PERIOD_600MS = 0x15, /*!< Wake-Up timer 600ms */ + RFAL_WUM_PERIOD_700MS = 0x16, /*!< Wake-Up timer 700ms */ + RFAL_WUM_PERIOD_800MS = 0x17, /*!< Wake-Up timer 800ms */ +} rfalWumPeriod; + +/*! RFAL Wake-Up Period/Timer */ +typedef enum { + RFAL_WUM_AA_WEIGHT_4 = 0x00, /*!< Wake-Up Auto Average Weight 4 */ + RFAL_WUM_AA_WEIGHT_8 = 0x01, /*!< Wake-Up Auto Average Weight 8 */ + RFAL_WUM_AA_WEIGHT_16 = 0x02, /*!< Wake-Up Auto Average Weight 16 */ + RFAL_WUM_AA_WEIGHT_32 = 0x03, /*!< Wake-Up Auto Average Weight 32 */ +} rfalWumAAWeight; + +/*! RFAL Wake-Up Mode configuration */ +typedef struct { + rfalWumPeriod period; /*!< Wake-Up Timer period;how often measurement(s) is performed */ + bool irqTout; /*!< IRQ at every timeout will refresh the measurement(s) */ + bool swTagDetect; /*!< Use SW Tag Detection instead of HW Wake-Up mode */ + + struct { + bool enabled; /*!< Inductive Amplitude measurement enabled */ + uint8_t delta; /*!< Delta between the reference and measurement to wake-up */ + uint16_t reference; /*!< Reference to be used;RFAL_WUM_REFERENCE_AUTO sets it auto */ + bool autoAvg; /*!< Use the HW Auto Averaging feature */ + bool aaInclMeas; /*!< When AutoAvg is enabled, include IRQ measurement */ + rfalWumAAWeight aaWeight; /*!< When AutoAvg is enabled, last measure weight */ + } indAmp; /*!< Inductive Amplitude Configuration */ + struct { + bool enabled; /*!< Inductive Phase measurement enabled */ + uint8_t delta; /*!< Delta between the reference and measurement to wake-up */ + uint16_t reference; /*!< Reference to be used;RFAL_WUM_REFERENCE_AUTO sets it auto */ + bool autoAvg; /*!< Use the HW Auto Averaging feature */ + bool aaInclMeas; /*!< When AutoAvg is enabled, include IRQ measurement */ + rfalWumAAWeight aaWeight; /*!< When AutoAvg is enabled, last measure weight */ + } indPha; /*!< Inductive Phase Configuration */ + struct { + bool enabled; /*!< Capacitive measurement enabled */ + uint8_t delta; /*!< Delta between the reference and measurement to wake-up */ + uint16_t reference; /*!< Reference to be used;RFAL_WUM_REFERENCE_AUTO sets it auto */ + bool autoAvg; /*!< Use the HW Auto Averaging feature */ + bool aaInclMeas; /*!< When AutoAvg is enabled, include IRQ measurement */ + rfalWumAAWeight aaWeight; /*!< When AutoAvg is enabled, last measure weight */ + } cap; /*!< Capacitive Configuration */ +} rfalWakeUpConfig; + +/*******************************************************************************/ + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +/*! + ***************************************************************************** + * \brief RFAL Initialize + * + * Initializes RFAL layer and the ST25R391x + * Ensures that ST25R391x is properly connected and returns error if any problem + * is detected + * + * \warning rfalAnalogConfigInitialize() should be called before so that + * the Analog config table has been previously initialized. + * + * \return ERR_HW_MISMATCH : Expected HW do not match or communication error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalInitialize(void); + +/*! + ***************************************************************************** + * \brief RFAL Calibrate + * + * Performs necessary calibration of RF chip in case it is indicated by current + * register settings. E.g. antenna calibration and regulator calibration + * + * \return ERR_WRONG_STATE : RFAL not initialized + * \return ERR_NONE : No error + * + ***************************************************************************** + */ +ReturnCode rfalCalibrate(void); + +/*! + ***************************************************************************** + * \brief RFAL Adjust Regulators + * + * Adjusts ST25R391x regulators + * + * \param[out] result : the result of the calibrate antenna in mV + * NULL if result not requested + * + * \return ERR_WRONG_STATE : RFAL not initialized + * \return ERR_NONE : No error + * + ***************************************************************************** + */ +ReturnCode rfalAdjustRegulators(uint16_t* result); + +/*! + ***************************************************************************** + * \brief RFAL Set System Callback + * + * Sets a callback for the driver to call when an event has occurred that + * may require the system to be notified + * + * \param[in] pFunc : method pointer for the upper layer callback + * + ***************************************************************************** + */ +void rfalSetUpperLayerCallback(rfalUpperLayerCallback pFunc); + +/*! + ***************************************************************************** + * \brief RFAL Set Pre Tx Callback + * + * Sets a callback for the driver to call before a Transceive + * + * \param[in] pFunc : method pointer for the Pre Tx callback + * + ***************************************************************************** + */ +void rfalSetPreTxRxCallback(rfalPreTxRxCallback pFunc); + +/*! + ***************************************************************************** + * \brief RFAL Set Post Tx Callback + * + * Sets a callback for the driver to call after a Transceive + * + * \param[in] pFunc : method pointer for the Post Tx callback + * + ***************************************************************************** + */ +void rfalSetPostTxRxCallback(rfalPostTxRxCallback pFunc); + +/** Set RFAL state changed callback + * + * @param cb RfalStateChangedCallback instance + * @param ctx pointer to context + */ +void rfal_set_state_changed_callback(RfalStateChangedCallback callback); + +/** Set callback context + * + * @param ctx pointer to context + */ +void rfal_set_callback_context(void* context); + +/*! + ***************************************************************************** + * \brief RFAL Deinitialize + * + * Deinitializes RFAL layer and the ST25R391x + * + * \return ERR_NONE : No error + * + ***************************************************************************** + */ +ReturnCode rfalDeinitialize(void); + +/*! + ***************************************************************************** + * \brief RFAL Set Mode + * + * Sets the mode that RFAL will operate on the following communications. + * Proper initializations will be performed on the ST25R391x + * + * \warning bit rate value RFAL_BR_KEEP is not allowed, only in rfalSetBitRate() + * + * \warning the mode will be applied immediately on the RFchip regardless of + * any ongoing operations like Transceive, ListenMode + * + * \param[in] mode : mode for the RFAL/RFchip to perform + * \param[in] txBR : transmit bit rate + * \param[in] rxBR : receive bit rate + * + * \see rfalIsGTExpired + * \see rfalMode + * + * \return ERR_WRONG_STATE : RFAL not initialized + * \return ERR_PARAM : Invalid parameter + * \return ERR_NONE : No error + * + ***************************************************************************** + */ +ReturnCode rfalSetMode(rfalMode mode, rfalBitRate txBR, rfalBitRate rxBR); + +/*! + ***************************************************************************** + * \brief RFAL Get Mode + * + * Gets the mode that RFAL is set to operate + * + * \see rfalMode + * + * \return rfalMode : The current RFAL mode + ***************************************************************************** + */ +rfalMode rfalGetMode(void); + +/*! + ***************************************************************************** + * \brief RFAL Set Bit Rate + * + * Sets the Tx and Rx bit rates with the given values + * The bit rate change is applied on the RF chip remaining in the same + * mode previous defined with rfalSetMode() + * + * If no mode is defined bit rates will not be applied and an error + * is returned + * + * \param[in] txBR : transmit bit rate + * \param[in] rxBR : receive bit rate + * + * \see rfalSetMode + * \see rfalMode + * \see rfalBitRate + * + * \return ERR_WRONG_STATE : RFAL not initialized + * \return ERR_PARAM : Invalid parameter + * \return ERR_NOT_IMPLEMENTED : Mode not implemented + * \return ERR_NONE : No error + * + ***************************************************************************** + */ +ReturnCode rfalSetBitRate(rfalBitRate txBR, rfalBitRate rxBR); + +/*! + ***************************************************************************** + * \brief RFAL Get Bit Rate + * + * Gets the Tx and Rx current bit rates + * + * If RFAL is not initialized or mode not set the bit rates return will + * be invalid RFAL_BR_KEEP + * + * \param[out] txBR : RFAL's current Tx Bit Rate + * \param[out] rxBR : RFAL's current Rx Bit Rate + * + * \see rfalSetBitRate + * \see rfalBitRate + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalGetBitRate(rfalBitRate* txBR, rfalBitRate* rxBR); + +/*! + ***************************************************************************** + * \brief Set Error Handling Mode + * + * Sets the error handling mode to be used by the RFAL + * + * \param[in] eHandling : the error handling mode + * + ***************************************************************************** + */ +void rfalSetErrorHandling(rfalEHandling eHandling); + +/*! + ***************************************************************************** + * \brief Get Error Handling Mode + * + * Gets the error handling mode currently used by the RFAL + * + * \return rfalEHandling : Current error handling mode + ***************************************************************************** + */ +rfalEHandling rfalGetErrorHandling(void); + +/*! + ***************************************************************************** + * \brief Set Observation Mode + * + * Sets ST25R391x observation modes for RF debug purposes + * + * \param[in] txMode : the observation mode to be used during transmission + * \param[in] rxMode : the observation mode to be used during reception + * + * \warning The Observation Mode is an advanced feature and should be set + * according to the documentation of the part number in use. + * Please refer to the corresponding Datasheet or Application Note(s) + ***************************************************************************** + */ +void rfalSetObsvMode(uint8_t txMode, uint8_t rxMode); + +/*! + ***************************************************************************** + * \brief Get Observation Mode + * + * Gets ST25R391x the current configured observation modes + * + * \param[in] txMode : the current observation mode configured for transmission + * \param[in] rxMode : the current observation mode configured for reception + * + ***************************************************************************** + */ +void rfalGetObsvMode(uint8_t* txMode, uint8_t* rxMode); + +/*! + ***************************************************************************** + * \brief Disable Observation Mode + * + * Disables the ST25R391x observation mode + ***************************************************************************** + */ +void rfalDisableObsvMode(void); + +/*! + ***************************************************************************** + * \brief RFAL Set FDT Poll + * + * Sets the Frame Delay Time (FDT) to be used on the following + * communications. + * + * FDT Poll is the minimum time following a Poll Frame during + * which no subsequent Poll Frame can be sent (without a response from + * the Listener in between) + * FDTx,PP,MIN - Digital 1.1 6.10.2 & 7.9.2 & 8.7.2 + * + * \param[in] FDTPoll : Frame Delay Time in 1/fc cycles + * + ***************************************************************************** + */ +void rfalSetFDTPoll(uint32_t FDTPoll); + +/*! + ***************************************************************************** + * \brief RFAL Set FDT Poll + * + * Gets the current Frame Delay Time (FDT) + * + * FDT Poll is the minimum time following a Poll Frame during + * which no subsequent Poll Frame can be sent (without a response from + * the Listener in between) + * FDTx,PP,MIN - Digital 1.1 6.10.2 & 7.9.2 & 8.7.2 + * + * \return FDT : current FDT value in 1/fc cycles + * + ***************************************************************************** + */ +uint32_t rfalGetFDTPoll(void); + +/*! + ***************************************************************************** + * \brief RFAL Set FDT Listen + * + * Sets the Frame Delay Time (FDT) Listen minimum to be used on the + * following communications. + * + * FDT Listen is the minimum time between a Poll Frame and a Listen Frame + * FDTx,LISTEN,MIN - Digital 1.1 6.10.1 & 7.9.1 & 8.7.1 + * + * \param[in] FDTListen : Frame Delay Time in 1/fc cycles + * + ***************************************************************************** + */ +void rfalSetFDTListen(uint32_t FDTListen); + +/*! + ***************************************************************************** + * \brief RFAL Set FDT Listen + * + * Gets the Frame Delay Time (FDT) Listen minimum + * + * FDT Listen is the minimum time between a Poll Frame and a Listen Frame + * FDTx,LISTEN,MIN - Digital 1.1 6.10.1 & 7.9.1 & 8.7.1 + * + * \return FDT : current FDT value in 1/fc cycles + * + ***************************************************************************** + */ +uint32_t rfalGetFDTListen(void); + +/*! + ***************************************************************************** + * \brief RFAL Get GT + * + * Gets the current Guard Time (GT) + * + * GT is the minimum time when a device in Listen Mode is exposed to an + * unmodulated carrier + * + * \return GT : Guard Time in 1/fc cycles + * + ***************************************************************************** + */ +uint32_t rfalGetGT(void); + +/*! + ***************************************************************************** + * \brief RFAL Set GT + * + * Sets the Guard Time (GT) to be used on the following communications. + * + * GT is the minimum time when a device in Listen Mode is exposed to an + * unmodulated carrier + * + * \param[in] GT : Guard Time in 1/fc cycles + * RFAL_GT_NONE if no GT should be applied + * + ***************************************************************************** + */ +void rfalSetGT(uint32_t GT); + +/*! + ***************************************************************************** + * \brief RFAL Is GT expired + * + * Checks whether the GT timer has expired + * + * \return true : GT has expired or not running + * \return false : GT is still running + * + ***************************************************************************** + */ +bool rfalIsGTExpired(void); + +/*! + ***************************************************************************** + * \brief RFAL Turn Field On and Start GT + * + * Turns the Field On, performing Initial Collision Avoidance + * + * After Field On, if GT was set before, it starts the GT timer to be + * used on the following communications. + * + * \return ERR_RF_COLLISION : External field detected + * \return ERR_NONE : Field turned On + * + ***************************************************************************** + */ +ReturnCode rfalFieldOnAndStartGT(void); + +/*! + ***************************************************************************** + * \brief RFAL Turn Field Off + * + * Turns the Field Off + * + * \return ERR_NONE : Field turned Off + ***************************************************************************** + */ +ReturnCode rfalFieldOff(void); + +/***************************************************************************** + * Transceive * + *****************************************************************************/ + +/*! + ***************************************************************************** + * \brief RFAL Set transceive context + * + * Set the context that will be used for the following Transceive + * Output and input buffers have to be passed and all other details prior to + * the Transceive itself has been started + * + * This method only sets the context, once set rfalWorker has + * to be executed until is done + * + * \param[in] ctx : the context for the following Transceive + * + * \see rfalWorker + * \see rfalGetTransceiveStatus + * + * \return ERR_NONE : Done with no error + * \return ERR_WRONG_STATE : Not initialized properly + * \return ERR_PARAM : Invalid parameter or configuration + ***************************************************************************** + */ +ReturnCode rfalStartTransceive(const rfalTransceiveContext* ctx); + +/*! + ***************************************************************************** + * \brief Get Transceive State + * + * Gets current Transceive internal State + * + * \return rfalTransceiveState : the current Transceive internal State + ***************************************************************************** + */ +rfalTransceiveState rfalGetTransceiveState(void); + +/*! + ***************************************************************************** + * \brief Get Transceive Status + * + * Gets current Transceive status + * + * \return ERR_NONE : Transceive done with no error + * \return ERR_BUSY : Transceive ongoing + * \return ERR_XXXX : Error occurred + * \return ERR_TIMEOUT : No response + * \return ERR_FRAMING : Framing error detected + * \return ERR_PAR : Parity error detected + * \return ERR_CRC : CRC error detected + * \return ERR_LINK_LOSS : Link Loss - External Field is Off + * \return ERR_RF_COLLISION : Collision detected + * \return ERR_IO : Internal error + ***************************************************************************** + */ +ReturnCode rfalGetTransceiveStatus(void); + +/*! + ***************************************************************************** + * \brief Is Transceive in Tx + * + * Checks if Transceive is in Transmission state + * + * \return true Transmission ongoing + * \return false Not in transmission state + ***************************************************************************** + */ +bool rfalIsTransceiveInTx(void); + +/*! + ***************************************************************************** + * \brief Is Transceive in Rx + * + * Checks if Transceive is in Reception state + * + * \return true Transmission done/reception ongoing + * \return false Not in reception state + ***************************************************************************** + */ +bool rfalIsTransceiveInRx(void); + +/*! + ***************************************************************************** + * \brief Get Transceive RSSI + * + * Gets the RSSI value of the last executed Transceive in mV + * + * \param[out] rssi : RSSI value + * + * \return ERR_NOTSUPP : Feature not supported + * \return ERR_PARAM : Invalid parameter + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalGetTransceiveRSSI(uint16_t* rssi); + +/*! + ***************************************************************************** + * \brief RFAL Worker + * + * This runs RFAL layer, which drives the actual Transceive procedure + * It MUST be executed frequently in order to execute the RFAL internal + * states and perform the requested operations + * + ***************************************************************************** + */ +void rfalWorker(void); + +/***************************************************************************** + * ISO1443A * + *****************************************************************************/ + +/*! + ***************************************************************************** + * \brief Transceives an ISO14443A ShortFrame + * + * Sends REQA to detect if there is any PICC in the field + * + * \param[in] txCmd: Command to be sent: + * 0x52 WUPA / ALL_REQ + * 0x26 REQA / SENS_REQ + * + * \param[in] txCmd : type of short frame to be sent REQA or WUPA + * \param[out] rxBuf : buffer to place the response + * \param[in] rxBufLen : length of rxBuf + * \param[out] rxRcvdLen: received length + * \param[in] fwt : Frame Waiting Time in 1/fc + * + * \warning If fwt is set to RFAL_FWT_NONE it will make endlessly for + * a response, which on a blocking method may not be the + * desired usage + * + * \return ERR_NONE if there is response + * \return ERR_TIMEOUT if there is no response + * \return ERR_COLLISION collision has occurred + * + ***************************************************************************** + */ +ReturnCode rfalISO14443ATransceiveShortFrame( + rfal14443AShortFrameCmd txCmd, + uint8_t* rxBuf, + uint8_t rxBufLen, + uint16_t* rxRcvdLen, + uint32_t fwt); + +/*! + ***************************************************************************** + * \brief Sends an ISO14443A Anticollision Frame + * + * This is use to perform ISO14443A anti-collision. + * \note Anticollision is sent without CRC + * + * + * \param[in] buf : reference to ANTICOLLISION command (with known UID if any) to be sent (also out param) + * reception will be place on this buf after bytesToSend + * \param[in] bytesToSend: reference number of full bytes to be sent (including CMD byte and SEL_PAR) + * if a collision occurs will contain the number of clear bytes + * \param[in] bitsToSend : reference to number of bits (0-7) to be sent; and received (also out param) + * if a collision occurs will indicate the number of clear bits (also out param) + * \param[out] rxLength : reference to the return the received length + * \param[in] fwt : Frame Waiting Time in 1/fc + * + * \return ERR_NONE if there is no error + ***************************************************************************** + */ +ReturnCode rfalISO14443ATransceiveAnticollisionFrame( + uint8_t* buf, + uint8_t* bytesToSend, + uint8_t* bitsToSend, + uint16_t* rxLength, + uint32_t fwt); + +/***************************************************************************** + * FeliCa * + *****************************************************************************/ + +/*! + ***************************************************************************** + * \brief FeliCa Poll + * + * Sends a Poll Request and collects all Poll Responses according to the + * given slots + * + * + * \param[in] slots : number of slots for the Poll Request + * \param[in] sysCode : system code (SC) for the Poll Request + * \param[in] reqCode : request code (RC) for the Poll Request + * \param[out] pollResList : list of all responses + * \param[in] pollResListSize : number of responses that can be placed in pollResList + * \param[out] devicesDetected : number of cards found + * \param[out] collisionsDetected: number of collisions detected + * + * \return ERR_NONE if there is no error + * \return ERR_TIMEOUT if there is no response + ***************************************************************************** + */ +ReturnCode rfalFeliCaPoll( + rfalFeliCaPollSlots slots, + uint16_t sysCode, + uint8_t reqCode, + rfalFeliCaPollRes* pollResList, + uint8_t pollResListSize, + uint8_t* devicesDetected, + uint8_t* collisionsDetected); + +/***************************************************************************** + * ISO15693 * + *****************************************************************************/ + +/*! + ***************************************************************************** + * \brief Sends an ISO15693 Anticollision Frame + * + * This send the Anticollision|Inventory frame (INVENTORY_REQ) + * + * \warning rxBuf must be able to contain the payload and CRC + * + * \param[in] txBuf : Buffer where outgoing message is located + * \param[in] txBufLen : Length of the outgoing message in bytes + * \param[out] rxBuf : Buffer where incoming message will be placed + * \param[in] rxBufLen : Maximum length of the incoming message in bytes + * \param[out] actLen : Actual received length in bits + * + * \return ERR_NONE : Transceive done with no error + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_IO : Internal error + ***************************************************************************** + */ +ReturnCode rfalISO15693TransceiveAnticollisionFrame( + uint8_t* txBuf, + uint8_t txBufLen, + uint8_t* rxBuf, + uint8_t rxBufLen, + uint16_t* actLen); + +/*! + ***************************************************************************** + * \brief Sends an ISO15693 Anticollision EOF + * + * This sends the Anticollision|Inventory EOF used as a slot marker + * + * \warning rxBuf must be able to contain the payload and CRC + * + * \param[out] rxBuf : Buffer where incoming message will be placed + * \param[in] rxBufLen : Maximum length of the incoming message in bytes + * \param[out] actLen : Actual received length in bits + * + * \return ERR_NONE : Transceive done with no error + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_IO : Internal error + ***************************************************************************** + */ +ReturnCode + rfalISO15693TransceiveEOFAnticollision(uint8_t* rxBuf, uint8_t rxBufLen, uint16_t* actLen); + +/*! + ***************************************************************************** + * \brief Sends an ISO15693 EOF + * + * This is method sends an ISO15693 (EoF) used for a Write operation + * + * \warning rxBuf must be able to contain the payload and CRC + * + * \param[out] rxBuf : Buffer where incoming message will be placed + * \param[in] rxBufLen : Maximum length of the incoming message in bytes + * \param[out] actLen : Actual received length in bytes + * + * \return ERR_NONE : Transceive done with no error + * \return ERR_IO : Internal error + ***************************************************************************** + */ +ReturnCode rfalISO15693TransceiveEOF(uint8_t* rxBuf, uint8_t rxBufLen, uint16_t* actLen); + +/*! + ***************************************************************************** + * \brief Transceive Blocking Tx + * + * This is method triggers a Transceive and executes it blocking until the + * Tx has been completed + * + * \param[in] txBuf : Buffer where outgoing message is located + * \param[in] txBufLen : Length of the outgoing message in bytes + * \param[out] rxBuf : Buffer where incoming message will be placed + * \param[in] rxBufLen : Maximum length of the incoming message in bytes + * \param[out] actLen : Actual received length in bits + * \param[in] flags : TransceiveFlags indication special handling + * \param[in] fwt : Frame Waiting Time in 1/fc + * + * \return ERR_NONE : Transceive done with no error + * \return ERR_BUSY : Transceive ongoing + * \return ERR_XXXX : Error occurred + * \return ERR_LINK_LOSS : Link Loss - External Field is Off + * \return ERR_RF_COLLISION : Collision detected + * \return ERR_IO : Internal error + ***************************************************************************** + */ +ReturnCode rfalTransceiveBlockingTx( + uint8_t* txBuf, + uint16_t txBufLen, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* actLen, + uint32_t flags, + uint32_t fwt); + +/*! + ***************************************************************************** + * \brief Transceive Blocking Rx + * + * This is method executes the reception of an ongoing Transceive triggered + * before by rfalTransceiveBlockingTx() + * + * \return ERR_NONE : Transceive done with no error + * \return ERR_BUSY : Transceive ongoing + * \return ERR_XXXX : Error occurred + * \return ERR_TIMEOUT : No response + * \return ERR_FRAMING : Framing error detected + * \return ERR_PAR : Parity error detected + * \return ERR_CRC : CRC error detected + * \return ERR_LINK_LOSS : Link Loss - External Field is Off + * \return ERR_RF_COLLISION : Collision detected + * \return ERR_IO : Internal error + ***************************************************************************** + */ +ReturnCode rfalTransceiveBlockingRx(void); + +/*! + ***************************************************************************** + * \brief Transceive Blocking + * + * This is method triggers a Transceive and executes it blocking until it + * has been completed + * + * \param[in] txBuf : Buffer where outgoing message is located + * \param[in] txBufLen : Length of the outgoing message in bytes + * \param[out] rxBuf : Buffer where incoming message will be placed + * \param[in] rxBufLen : Maximum length of the incoming message in bytes + * \param[out] actLen : Actual received length in bytes + * \param[in] flags : TransceiveFlags indication special handling + * \param[in] fwt : Frame Waiting Time in 1/fc + * + * \return ERR_NONE : Transceive done with no error + * \return ERR_BUSY : Transceive ongoing + * \return ERR_XXXX : Error occurred + * \return ERR_TIMEOUT : No response + * \return ERR_FRAMING : Framing error detected + * \return ERR_PAR : Parity error detected + * \return ERR_CRC : CRC error detected + * \return ERR_LINK_LOSS : Link Loss - External Field is Off + * \return ERR_RF_COLLISION : Collision detected + * \return ERR_IO : Internal error + ***************************************************************************** + */ +ReturnCode rfalTransceiveBlockingTxRx( + uint8_t* txBuf, + uint16_t txBufLen, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* actLen, + uint32_t flags, + uint32_t fwt); + +ReturnCode rfalTransceiveBitsBlockingTxRx( + uint8_t* txBuf, + uint16_t txBufLen, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* actLen, + uint32_t flags, + uint32_t fwt); + +ReturnCode rfalTransceiveBitsBlockingTx( + uint8_t* txBuf, + uint16_t txBufLen, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* actLen, + uint32_t flags, + uint32_t fwt); + +/***************************************************************************** + * Listen Mode * + *****************************************************************************/ + +/*! + ***************************************************************************** + * \brief Is external Field On + * + * Checks if external field (other peer/device) is on/detected + * + * \return true External field is On + * \return false No external field is detected + * + ***************************************************************************** + */ +bool rfalIsExtFieldOn(void); + +/*! + ***************************************************************************** + * \brief Listen Mode start + * + * Configures RF Chip to go into listen mode enabling the given technologies + * + * + * \param[in] lmMask: mask with the enabled/disabled listen modes + * use: RFAL_LM_MASK_NFCA ; RFAL_LM_MASK_NFCB ; + * RFAL_LM_MASK_NFCF ; RFAL_LM_MASK_ACTIVE_P2P + * \param[in] confA: pointer to Passive A configurations (NULL if disabled) + * \param[in] confB: pointer to Passive B configurations (NULL if disabled) + * \param[in] confF: pointer to Passive F configurations (NULL if disabled) + * \param[in] rxBuf: buffer to place incoming data + * \param[in] rxBufLen: length in bits of rxBuf + * \param[in] rxLen: pointer to write the data length in bits placed into rxBuf + * + * + * \return ERR_PARAM Invalid parameter + * \return ERR_REQUEST Invalid listen mode mask + * \return ERR_NONE Done with no error + * + ***************************************************************************** + */ +ReturnCode rfalListenStart( + uint32_t lmMask, + const rfalLmConfPA* confA, + const rfalLmConfPB* confB, + const rfalLmConfPF* confF, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rxLen); + +/*! + ***************************************************************************** + * \brief Listen Mode start Sleeping + * + * + ***************************************************************************** + */ +ReturnCode + rfalListenSleepStart(rfalLmState sleepSt, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t* rxLen); + +/*! + ***************************************************************************** + * \brief Listen Mode Stop + * + * Disables the listen mode on the RF Chip + * + * \warning the listen mode will be disabled immediately on the RFchip regardless + * of any ongoing operations like Transceive + * + * \return ERR_NONE Done with no error + * + ***************************************************************************** + */ +ReturnCode rfalListenStop(void); + +/*! + ***************************************************************************** + * \brief Listen Mode get state + * + * Sets the new state of the Listen Mode and applies the necessary changes + * on the RF Chip + * + * \param[out] dataFlag: indicates that Listen Mode has rcvd data and caller + * must process it. The received message is located + * at the rxBuf passed on rfalListenStart(). + * rfalListenSetState() will clear this flag + * if NULL output parameter will no be written/returned + * \param[out] lastBR: bit rate detected of the last initiator request + * if NULL output parameter will no be written/returned + * + * \return rfalLmState RFAL_LM_STATE_NOT_INIT : LM not initialized properly + * Any Other : LM State + * + ***************************************************************************** + */ +rfalLmState rfalListenGetState(bool* dataFlag, rfalBitRate* lastBR); + +/*! + ***************************************************************************** + * \brief Listen Mode set state + * + * Sets the new state of the Listen Mode and applies the necessary changes + * on the RF Chip + * + * \param[in] newSt : New state to go to + * + * \return ERR_WRONG_STATE : Not initialized properly + * \return ERR_PARAM : Invalid parameter + * \return ERR_NONE : Done with no error + * + ***************************************************************************** + */ +ReturnCode rfalListenSetState(rfalLmState newSt); + +/***************************************************************************** + * Wake-Up Mode * + *****************************************************************************/ + +/*! + ***************************************************************************** + * \brief Wake-Up Mode Start + * + * Sets the RF Chip in Low Power Wake-Up Mode according to the given + * configuration. + * + * \param[in] config : Generic Wake-Up configuration provided by lower + * layers. If NULL will automatically configure the + * Wake-Up mode + * + * \return ERR_WRONG_STATE : Not initialized properly + * \return ERR_PARAM : Invalid parameter + * \return ERR_NONE : Done with no error + * + ***************************************************************************** + */ +ReturnCode rfalWakeUpModeStart(const rfalWakeUpConfig* config); + +/*! + ***************************************************************************** + * \brief Wake-Up Has Woke + * + * Returns true if the Wake-Up mode is enabled and it has already received + * the indication from the RF Chip that the surrounding environment has changed + * and flagged at least one wake-Up interrupt + * + * \return true : Wake-Up mode enabled and has received a wake-up IRQ + * \return false : no Wake-Up IRQ has been received + * + ***************************************************************************** + */ +bool rfalWakeUpModeHasWoke(void); + +/*! + ***************************************************************************** + * \brief Wake-Up Mode Stop + * + * Stops the Wake-Up Mode + * + * \return ERR_WRONG_STATE : Not initialized properly + * \return ERR_PARAM : Invalid parameter + * \return ERR_NONE : Done with no error + * + ***************************************************************************** + */ +ReturnCode rfalWakeUpModeStop(void); + +/*! + ***************************************************************************** + * \brief Low Power Mode Start + * + * Sets the RF Chip in Low Power Mode. + * In this mode the RF Chip is placed in Low Power Mode, similar to Wake-up + * mode but no operation nor period measurement is performed. + * Mode must be terminated by rfalLowPowerModeStop() + * + * \return ERR_WRONG_STATE : Not initialized properly + * \return ERR_PARAM : Invalid parameter + * \return ERR_NONE : Done with no error + * + ***************************************************************************** + */ +ReturnCode rfalLowPowerModeStart(void); + +/*! + ***************************************************************************** + * \brief Low Power Mode Stop + * + * Stops the Low Power Mode re-enabling the device + * + * \return ERR_WRONG_STATE : Not initialized properly + * \return ERR_PARAM : Invalid parameter + * \return ERR_NONE : Done with no error + * + ***************************************************************************** + */ +ReturnCode rfalLowPowerModeStop(void); + +#endif /* RFAL_RF_H */ + +/** + * @} + * + * @} + * + * @} + */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_st25tb.h b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_st25tb.h new file mode 100644 index 00000000000..80d1bc03951 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_st25tb.h @@ -0,0 +1,340 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_st25tb.h + * + * \author Gustavo Patricio + * + * \brief Implementation of ST25TB interface + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-AL + * \brief RFAL Abstraction Layer + * @{ + * + * \addtogroup ST25TB + * \brief RFAL ST25TB Module + * @{ + * + */ + +#ifndef RFAL_ST25TB_H +#define RFAL_ST25TB_H + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "../platform.h" +#include "../st_errno.h" +#include "rfal_rf.h" +#include "rfal_nfcb.h" + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ + +#define RFAL_ST25TB_CHIP_ID_LEN 1U /*!< ST25TB chip ID length */ +#define RFAL_ST25TB_CRC_LEN 2U /*!< ST25TB CRC length */ +#define RFAL_ST25TB_UID_LEN 8U /*!< ST25TB Unique ID length */ +#define RFAL_ST25TB_BLOCK_LEN 4U /*!< ST25TB Data Block length */ + +/* +****************************************************************************** +* GLOBAL MACROS +****************************************************************************** +*/ + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ +typedef uint8_t rfalSt25tbUID[RFAL_ST25TB_UID_LEN]; /*!< ST25TB UID type */ +typedef uint8_t rfalSt25tbBlock[RFAL_ST25TB_BLOCK_LEN]; /*!< ST25TB Block type */ + +/*! ST25TB listener device (PICC) struct */ +typedef struct { + uint8_t chipID; /*!< Device's session Chip ID */ + rfalSt25tbUID UID; /*!< Device's UID */ + bool isDeselected; /*!< Device deselect flag */ +} rfalSt25tbListenDevice; + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +/*! + ***************************************************************************** + * \brief Initialize ST25TB Poller mode + * + * This methods configures RFAL RF layer to perform as a + * ST25TB Poller/RW including all default timings + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalSt25tbPollerInitialize(void); + +/*! + ***************************************************************************** + * \brief ST25TB Poller Check Presence + * + * This method checks if a ST25TB Listen device (PICC) is present on the field + * by sending an Initiate command + * + * \param[out] chipId : if successfully retrieved, the device's chip ID + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error, no listener device detected + * \return ERR_RF_COLLISION : Collision detected one or more device in the field + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalSt25tbPollerCheckPresence(uint8_t* chipId); + +/*! + ***************************************************************************** + * \brief ST25TB Poller Collision Resolution + * + * This method performs ST25TB Collision resolution, selects the each device, + * retrieves its UID and then deselects. + * In case only one device is identified the ST25TB device is left in select + * state. + * + * \param[in] devLimit : device limit value, and size st25tbDevList + * \param[out] st25tbDevList : ST35TB listener device info + * \param[out] devCnt : Devices found counter + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error, no listener device detected + * \return ERR_RF_COLLISION : Collision detected one or more device in the field + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalSt25tbPollerCollisionResolution( + uint8_t devLimit, + rfalSt25tbListenDevice* st25tbDevList, + uint8_t* devCnt); + +/*! + ***************************************************************************** + * \brief ST25TB Poller Initiate + * + * This method sends an Initiate command + * + * If a single device responds the chip ID will be retrieved + * + * \param[out] chipId : chip ID of the device + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error, no listener device detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalSt25tbPollerInitiate(uint8_t* chipId); + +/*! + ***************************************************************************** + * \brief ST25TB Poller Pcall + * + * This method sends a Pcall command + * If successful the device's chip ID will be retrieved + * + * \param[out] chipId : Chip ID of the device + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error, no listener device detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalSt25tbPollerPcall(uint8_t* chipId); + +/*! + ***************************************************************************** + * \brief ST25TB Poller Slot Marker + * + * This method sends a Slot Marker + * + * If a single device responds the chip ID will be retrieved + * + * \param[in] slotNum : Slot Number + * \param[out] chipIdRes : Chip ID of the device + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error, no listener device detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalSt25tbPollerSlotMarker(uint8_t slotNum, uint8_t* chipIdRes); + +/*! + ***************************************************************************** + * \brief ST25TB Poller Select + * + * This method sends a ST25TB Select command with the given chip ID. + * + * If the device is already in Selected state and receives an incorrect chip + * ID, it goes into Deselected state + * + * \param[in] chipId : chip ID of the device to be selected + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error, no listener device detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalSt25tbPollerSelect(uint8_t chipId); + +/*! + ***************************************************************************** + * \brief ST25TB Get UID + * + * This method sends a Get_UID command + * + * If a single device responds the chip UID will be retrieved + * + * \param[out] UID : UID of the found device + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error, no listener device detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalSt25tbPollerGetUID(rfalSt25tbUID* UID); + +/*! + ***************************************************************************** + * \brief ST25TB Poller Read Block + * + * This method reads a block of the ST25TB + * + * \param[in] blockAddress : address of the block to be read + * \param[out] blockData : location to place the data read from block + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error, no listener device detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalSt25tbPollerReadBlock(uint8_t blockAddress, rfalSt25tbBlock* blockData); + +/*! + ***************************************************************************** + * \brief ST25TB Poller Write Block + * + * This method writes a block of the ST25TB + * + * \param[in] blockAddress : address of the block to be written + * \param[in] blockData : data to be written on the block + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error, no listener device detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalSt25tbPollerWriteBlock(uint8_t blockAddress, const rfalSt25tbBlock* blockData); + +/*! + ***************************************************************************** + * \brief ST25TB Poller Completion + * + * This method sends a completion command to the ST25TB. After the + * completion the card no longer will reply to any command. + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error, no listener device detected + * \return ERR_PROTO : Protocol error detected, invalid SENSB_RES received + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalSt25tbPollerCompletion(void); + +/*! + ***************************************************************************** + * \brief ST25TB Poller Reset to Inventory + * + * This method sends a Reset to Inventory command to the ST25TB. + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_TIMEOUT : Timeout error, no listener device detected + * \return ERR_PROTO : Protocol error detected, invalid SENSB_RES received + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalSt25tbPollerResetToInventory(void); + +#endif /* RFAL_ST25TB_H */ + +/** + * @} + * + * @} + * + * @} + */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_st25xv.h b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_st25xv.h new file mode 100644 index 00000000000..3eef8a40b1b --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_st25xv.h @@ -0,0 +1,844 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_st25xv.h + * + * \author Gustavo Patricio + * + * \brief NFC-V ST25 NFC-V Tag specific features + * + * This module provides support for ST's specific features available on + * NFC-V (ISO15693) tag families: ST25D, ST25TV, M24LR + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-AL + * \brief RFAL Abstraction Layer + * @{ + * + * \addtogroup ST25xV + * \brief RFAL ST25xV Module + * @{ + * + */ + +#ifndef RFAL_ST25xV_H +#define RFAL_ST25xV_H + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "../platform.h" +#include "../st_errno.h" +#include "rfal_nfc.h" +#include "rfal_rf.h" + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ + +#define RFAL_NFCV_BLOCKNUM_M24LR_LEN \ + 2U /*!< Block Number length of MR24LR tags: 16 bits */ +#define RFAL_NFCV_ST_IC_MFG_CODE \ + 0x02 /*!< ST IC Mfg code (used for custom commands) */ + +/*! + ***************************************************************************** + * \brief NFC-V Poller Read Single Block (M24LR) + * + * Reads a Single Block from a M24LR tag which has the number of blocks + * bigger than 256 (M24LR16 ; M24LR64) + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * default: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] blockNum : Number of the block to read (16 bits) + * \param[out] rxBuf : buffer to store response (also with RES_FLAGS) + * \param[in] rxBufLen : length of rxBuf + * \param[out] rcvLen : number of bytes received + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerM24LRReadSingleBlock( + uint8_t flags, + const uint8_t* uid, + uint16_t blockNum, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvLen); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Fast Read Single Block (M24LR) + * + * Reads a Single Block from a M24LR tag which has the number of blocks + * bigger than 256 (M24LR16 ; M24LR64) using ST Fast mode + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * default: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] blockNum : Number of the block to read (16 bits) + * \param[out] rxBuf : buffer to store response (also with RES_FLAGS) + * \param[in] rxBufLen : length of rxBuf + * \param[out] rcvLen : number of bytes received + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerM24LRFastReadSingleBlock( + uint8_t flags, + const uint8_t* uid, + uint16_t blockNum, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvLen); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Write Single Block (M24LR) + * + * Writes a Single Block from a M24LR tag which has the number of blocks + * bigger than 256 (M24LR16 ; M24LR64) + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be written + * if not provided Select mode will be used + * \param[in] blockNum : Number of the block to write (16 bits) + * \param[in] wrData : data to be written on the given block + * \param[in] blockLen : number of bytes of a block + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerM24LRWriteSingleBlock( + uint8_t flags, + const uint8_t* uid, + uint16_t blockNum, + const uint8_t* wrData, + uint8_t blockLen); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Read Multiple Blocks (M24LR) + * + * Reads Multiple Blocks from a device from a M24LR tag which has the number of blocks + * bigger than 256 (M24LR16 ; M24LR64) + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] firstBlockNum : first block to be read (16 bits) + * \param[in] numOfBlocks : number of block to read + * \param[out] rxBuf : buffer to store response (also with RES_FLAGS) + * \param[in] rxBufLen : length of rxBuf + * \param[out] rcvLen : number of bytes received + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerM24LRReadMultipleBlocks( + uint8_t flags, + const uint8_t* uid, + uint16_t firstBlockNum, + uint8_t numOfBlocks, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvLen); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Fast Read Multiple Blocks (M24LR) + * + * Reads Multiple Blocks from a device from a M24LR tag which has the number of blocks + * bigger than 256 (M24LR16 ; M24LR64) using ST Fast mode + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] firstBlockNum : first block to be read (16 bits) + * \param[in] numOfBlocks : number of block to read + * \param[out] rxBuf : buffer to store response (also with RES_FLAGS) + * \param[in] rxBufLen : length of rxBuf + * \param[out] rcvLen : number of bytes received + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerM24LRFastReadMultipleBlocks( + uint8_t flags, + const uint8_t* uid, + uint16_t firstBlockNum, + uint8_t numOfBlocks, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvLen); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Fast Read Single Block + * + * Reads a Single Block from a device (VICC) using ST Fast mode + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] blockNum : Number of the block to read + * \param[out] rxBuf : buffer to store response (also with RES_FLAGS) + * \param[in] rxBufLen : length of rxBuf + * \param[out] rcvLen : number of bytes received + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerFastReadSingleBlock( + uint8_t flags, + const uint8_t* uid, + uint8_t blockNum, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvLen); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Fast Read Multiple Blocks + * + * Reads Multiple Blocks from a device (VICC) using ST Fast mode + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] firstBlockNum : first block to be read + * \param[in] numOfBlocks : number of block to read + * \param[out] rxBuf : buffer to store response (also with RES_FLAGS) + * \param[in] rxBufLen : length of rxBuf + * \param[out] rcvLen : number of bytes received + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerFastReadMultipleBlocks( + uint8_t flags, + const uint8_t* uid, + uint8_t firstBlockNum, + uint8_t numOfBlocks, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvLen); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Fast Extended Read Single Block + * + * Reads a Single Block from a device (VICC) supporting extended commands using ST Fast mode + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] blockNum : Number of the block to read (16 bits) + * \param[out] rxBuf : buffer to store response (also with RES_FLAGS) + * \param[in] rxBufLen : length of rxBuf + * \param[out] rcvLen : number of bytes received + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerFastExtendedReadSingleBlock( + uint8_t flags, + const uint8_t* uid, + uint16_t blockNum, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvLen); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Fast Extended Read Multiple Blocks + * + * Reads Multiple Blocks from a device (VICC) supporting extended commands using ST Fast mode + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] firstBlockNum : first block to be read (16 bits) + * \param[in] numOfBlocks : number of consecutive blocks to read (16 bits) + * \param[out] rxBuf : buffer to store response (also with RES_FLAGS) + * \param[in] rxBufLen : length of rxBuf + * \param[out] rcvLen : number of bytes received + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerFastExtReadMultipleBlocks( + uint8_t flags, + const uint8_t* uid, + uint16_t firstBlockNum, + uint16_t numOfBlocks, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvLen); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Read Configuration + * + * Reads static configuration registers at the Pointer address + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] pointer : Pointer address + * \param[out] regValue : Register value + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerReadConfiguration( + uint8_t flags, + const uint8_t* uid, + uint8_t pointer, + uint8_t* regValue); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Write Configuration + * + * Writes static configuration registers at the Pointer address + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] pointer : Pointer address + * \param[in] regValue : Register value + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerWriteConfiguration( + uint8_t flags, + const uint8_t* uid, + uint8_t pointer, + uint8_t regValue); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Read Dynamic Configuration + * + * Reads dynamic registers at the Pointer address + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] pointer : Pointer address + * \param[out] regValue : Register value + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerReadDynamicConfiguration( + uint8_t flags, + const uint8_t* uid, + uint8_t pointer, + uint8_t* regValue); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Write Dynamic Configuration + * + * Writes dynamic registers at the Pointer address + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] pointer : Pointer address + * \param[in] regValue : Register value + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerWriteDynamicConfiguration( + uint8_t flags, + const uint8_t* uid, + uint8_t pointer, + uint8_t regValue); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Fast Read Dynamic Configuration + * + * Reads dynamic registers at the Pointer address using ST Fast mode + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] pointer : Pointer address + * \param[out] regValue : Register value + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerFastReadDynamicConfiguration( + uint8_t flags, + const uint8_t* uid, + uint8_t pointer, + uint8_t* regValue); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Fast Write Dynamic Configuration + * + * Writes dynamic registers at the Pointer address using ST Fast mode + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] pointer : Pointer address + * \param[in] regValue : Register value + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerFastWriteDynamicConfiguration( + uint8_t flags, + const uint8_t* uid, + uint8_t pointer, + uint8_t regValue); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Present Password + * + * Sends the Present Password command + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] pwdNum : Password number + * \param[in] pwd : Password + * \param[in] pwdLen : Password length + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerPresentPassword( + uint8_t flags, + const uint8_t* uid, + uint8_t pwdNum, + const uint8_t* pwd, + uint8_t pwdLen); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Get Random Number + * + * Returns a 16 bit random number + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[out] rxBuf : buffer to store response (also with RES_FLAGS) + * \param[in] rxBufLen : length of rxBuf + * \param[out] rcvLen : number of bytes received + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerGetRandomNumber( + uint8_t flags, + const uint8_t* uid, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvLen); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Read Message length + * + * Sends a Read Message Length message to retrieve the value of MB_LEN_Dyn + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[out] msgLen : Message Length + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerReadMessageLength(uint8_t flags, const uint8_t* uid, uint8_t* msgLen); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Fast Read Message length + * + * Sends a Fast Read Message Length message to retrieve the value of MB_LEN_Dyn using ST Fast mode. + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[out] msgLen : Message Length + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerFastReadMsgLength(uint8_t flags, const uint8_t* uid, uint8_t* msgLen); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Read Message + * + * Reads up to 256 bytes in the Mailbox from the location + * specified by MBpointer and sends back their value in the rxBuf response. + * First MailBox location is '00'. When Number of bytes is set to 00h + * and MBPointer is equals to 00h, the MB_LEN bytes of the full message + * are returned. Otherwise, Read Message command returns (Number of Bytes + 1) bytes + * (i.e. 01h returns 2 bytes, FFh returns 256 bytes). + * An error is reported if (Pointer + Nb of bytes + 1) is greater than the message length. + * RF Reading of the last byte of the mailbox message automatically clears b1 + * of MB_CTRL_Dyn HOST_PUT_MSG, and allows RF to put a new message. + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] mbPointer : MPpointer + * \param[in] numBytes : number of bytes + * \param[out] rxBuf : buffer to store response (also with RES_FLAGS) + * \param[in] rxBufLen : length of rxBuf + * \param[out] rcvLen : number of bytes received + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerReadMessage( + uint8_t flags, + const uint8_t* uid, + uint8_t mbPointer, + uint8_t numBytes, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvLen); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Fast Read Message + * + * Reads up to 256 bytes in the Mailbox from the location + * specified by MBpointer and sends back their value in the rxBuf response using ST Fast mode. + * First MailBox location is '00'. When Number of bytes is set to 00h + * and MBPointer is equals to 00h, the MB_LEN bytes of the full message + * are returned. Otherwise, Read Message command returns (Number of Bytes + 1) bytes + * (i.e. 01h returns 2 bytes, FFh returns 256 bytes). + * An error is reported if (Pointer + Nb of bytes + 1) is greater than the message length. + * RF Reading of the last byte of the mailbox message automatically clears b1 + * of MB_CTRL_Dyn HOST_PUT_MSG, and allows RF to put a new message. + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] mbPointer : MPpointer + * \param[in] numBytes : number of bytes + * \param[out] rxBuf : buffer to store response (also with RES_FLAGS) + * \param[in] rxBufLen : length of rxBuf + * \param[out] rcvLen : number of bytes received + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerFastReadMessage( + uint8_t flags, + const uint8_t* uid, + uint8_t mbPointer, + uint8_t numBytes, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvLen); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Write Message + * + * Sends Write message Command + * + * On receiving the Write Message command, the ST25DVxxx puts the data contained + * in the request into the Mailbox buffer, update the MB_LEN_Dyn register, and + * set bit RF_PUT_MSG in MB_CTRL_Dyn register. It then reports if the write operation was successful + * in the response. The ST25DVxxx Mailbox contains up to 256 data bytes which are filled from the + * first location '00'. MSGlength parameter of the command is the number of + * Data bytes minus 1 (00 for 1 byte of data, FFh for 256 bytes of data). + * Write Message could be executed only when Mailbox is accessible by RF. + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] msgLen : MSGLen number of Data bytes minus 1 + * \param[in] msgData : Message Data + * \param[out] txBuf : buffer to used to build the Write Message command + * \param[in] txBufLen : length of txBuf + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerWriteMessage( + uint8_t flags, + const uint8_t* uid, + uint8_t msgLen, + const uint8_t* msgData, + uint8_t* txBuf, + uint16_t txBufLen); + +/*! + ***************************************************************************** + * \brief NFC-V Poller Fast Write Message + * + * Sends Fast Write message Command using ST Fast mode + * + * On receiving the Write Message command, the ST25DVxxx puts the data contained + * in the request into the Mailbox buffer, update the MB_LEN_Dyn register, and + * set bit RF_PUT_MSG in MB_CTRL_Dyn register. It then reports if the write operation was successful + * in the response. The ST25DVxxx Mailbox contains up to 256 data bytes which are filled from the + * first location '00'. MSGlength parameter of the command is the number of + * Data bytes minus 1 (00 for 1 byte of data, FFh for 256 bytes of data). + * Write Message could be executed only when Mailbox is accessible by RF. + * + * \param[in] flags : Flags to be used: Sub-carrier; Data_rate; Option + * for NFC-Forum use: RFAL_NFCV_REQ_FLAG_DEFAULT + * \param[in] uid : UID of the device to be put to be read + * if not provided Select mode will be used + * \param[in] msgLen : MSGLen number of Data bytes minus 1 + * \param[in] msgData : Message Data + * \param[out] txBuf : buffer to used to build the Write Message command + * \param[in] txBufLen : length of txBuf + * + * \return ERR_WRONG_STATE : RFAL not initialized or incorrect mode + * \return ERR_PARAM : Invalid parameters + * \return ERR_IO : Generic internal error + * \return ERR_CRC : CRC error detected + * \return ERR_FRAMING : Framing error detected + * \return ERR_PROTO : Protocol error detected + * \return ERR_TIMEOUT : Timeout error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalST25xVPollerFastWriteMessage( + uint8_t flags, + const uint8_t* uid, + uint8_t msgLen, + const uint8_t* msgData, + uint8_t* txBuf, + uint16_t txBufLen); + +#endif /* RFAL_ST25xV_H */ + +/** + * @} + * + * @} + * + * @} + */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_t1t.h b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_t1t.h new file mode 100644 index 00000000000..924bb29e806 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_t1t.h @@ -0,0 +1,178 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_t1t.h + * + * \author Gustavo Patricio + * + * \brief Provides NFC-A T1T convenience methods and definitions + * + * This module provides an interface to perform as a NFC-A Reader/Writer + * to handle a Type 1 Tag T1T (Topaz) + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-AL + * \brief RFAL Abstraction Layer + * @{ + * + * \addtogroup T1T + * \brief RFAL T1T Module + * @{ + * + */ + +#ifndef RFAL_T1T_H +#define RFAL_T1T_H + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "../platform.h" +#include "../st_errno.h" +#include "rfal_rf.h" + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ +#define RFAL_T1T_UID_LEN 4 /*!< T1T UID length of cascade level 1 only tag */ +#define RFAL_T1T_HR_LENGTH 2 /*!< T1T HR(Header ROM) length */ + +#define RFAL_T1T_HR0_NDEF_MASK 0xF0 /*!< T1T HR0 NDEF capability mask T1T 1.2 2.2.2 */ +#define RFAL_T1T_HR0_NDEF_SUPPORT 0x10 /*!< T1T HR0 NDEF capable value T1T 1.2 2.2.2 */ + +/*! NFC-A T1T (Topaz) command set */ +typedef enum { + RFAL_T1T_CMD_RID = 0x78, /*!< T1T Read UID */ + RFAL_T1T_CMD_RALL = 0x00, /*!< T1T Read All */ + RFAL_T1T_CMD_READ = 0x01, /*!< T1T Read */ + RFAL_T1T_CMD_WRITE_E = 0x53, /*!< T1T Write with erase (single byte) */ + RFAL_T1T_CMD_WRITE_NE = 0x1A /*!< T1T Write with no erase (single byte) */ +} rfalT1Tcmds; + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + +/*! NFC-A T1T (Topaz) RID_RES Digital 1.1 10.6.2 & Table 50 */ +typedef struct { + uint8_t hr0; /*!< T1T Header ROM: HR0 */ + uint8_t hr1; /*!< T1T Header ROM: HR1 */ + uint8_t uid[RFAL_T1T_UID_LEN]; /*!< T1T UID */ +} rfalT1TRidRes; + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +/*! + ***************************************************************************** + * \brief Initialize NFC-A T1T Poller mode + * + * This methods configures RFAL RF layer to perform as a + * NFC-A T1T Poller/RW (Topaz) including all default timings + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalT1TPollerInitialize(void); + +/*! + ***************************************************************************** + * \brief NFC-A T1T Poller RID + * + * This method reads the UID of a NFC-A T1T Listener device + * + * + * \param[out] ridRes : pointer to place the RID_RES + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_PARAM : Invalid parameter + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalT1TPollerRid(rfalT1TRidRes* ridRes); + +/*! + ***************************************************************************** + * \brief NFC-A T1T Poller RALL + * + * This method send a Read All command to a NFC-A T1T Listener device + * + * + * \param[in] uid : the UID of the device to read data + * \param[out] rxBuf : pointer to place the read data + * \param[in] rxBufLen : size of rxBuf + * \param[out] rxRcvdLen : actual received data + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_PARAM : Invalid parameter + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode + rfalT1TPollerRall(const uint8_t* uid, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t* rxRcvdLen); + +/*! + ***************************************************************************** + * \brief NFC-A T1T Poller Write + * + * This method writes the given data on the address of a NFC-A T1T Listener device + * + * + * \param[in] uid : the UID of the device to read data + * \param[in] address : address to write the data + * \param[in] data : the data to be written + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_PARAM : Invalid parameter + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalT1TPollerWrite(const uint8_t* uid, uint8_t address, uint8_t data); + +#endif /* RFAL_T1T_H */ + +/** + * @} + * + * @} + * + * @} + */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_t2t.h b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_t2t.h new file mode 100644 index 00000000000..f7f64f36345 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_t2t.h @@ -0,0 +1,150 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_t2t.h + * + * \author Gustavo Patricio + * + * \brief Provides NFC-A T2T convenience methods and definitions + * + * This module provides an interface to perform as a NFC-A Reader/Writer + * to handle a Type 2 Tag T2T + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-AL + * \brief RFAL Abstraction Layer + * @{ + * + * \addtogroup T2T + * \brief RFAL T2T Module + * @{ + * + */ + +#ifndef RFAL_T2T_H +#define RFAL_T2T_H + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "../platform.h" +#include "../st_errno.h" +#include "rfal_rf.h" + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ + +#define RFAL_T2T_BLOCK_LEN 4U /*!< T2T block length */ +#define RFAL_T2T_READ_DATA_LEN (4U * RFAL_T2T_BLOCK_LEN) /*!< T2T READ data length */ +#define RFAL_T2T_WRITE_DATA_LEN RFAL_T2T_BLOCK_LEN /*!< T2T WRITE data length */ + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +/*! + ***************************************************************************** + * \brief NFC-A T2T Poller Read + * + * This method sends a Read command to a NFC-A T2T Listener device + * + * + * \param[in] blockNum : Number of the block to read + * \param[out] rxBuf : pointer to place the read data + * \param[in] rxBufLen : size of rxBuf (RFAL_T2T_READ_DATA_LEN) + * \param[out] rcvLen : actual received data + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_PARAM : Invalid parameter + * \return ERR_PROTO : Protocol error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode + rfalT2TPollerRead(uint8_t blockNum, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t* rcvLen); + +/*! + ***************************************************************************** + * \brief NFC-A T2T Poller Write + * + * This method sends a Write command to a NFC-A T2T Listener device + * + * + * \param[in] blockNum : Number of the block to write + * \param[in] wrData : data to be written on the given block + * size must be of RFAL_T2T_WRITE_DATA_LEN + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_PARAM : Invalid parameter + * \return ERR_PROTO : Protocol error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalT2TPollerWrite(uint8_t blockNum, const uint8_t* wrData); + +/*! + ***************************************************************************** + * \brief NFC-A T2T Poller Sector Select + * + * This method sends a Sector Select commands to a NFC-A T2T Listener device + * + * \param[in] sectorNum : Sector Number + * + * \return ERR_WRONG_STATE : RFAL not initialized or mode not set + * \return ERR_PARAM : Invalid parameter + * \return ERR_PROTO : Protocol error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalT2TPollerSectorSelect(uint8_t sectorNum); + +#endif /* RFAL_T2T_H */ + +/** + * @} + * + * @} + * + * @} + */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_t4t.h b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_t4t.h new file mode 100644 index 00000000000..c0c20310fef --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/include/rfal_t4t.h @@ -0,0 +1,395 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_t4t.h + * + * \author Gustavo Patricio + * + * \brief Provides convenience methods and definitions for T4T (ISO7816-4) + * + * This module provides an interface to exchange T4T APDUs according to + * NFC Forum T4T and ISO7816-4 + * + * This implementation was based on the following specs: + * - ISO/IEC 7816-4 3rd Edition 2013-04-15 + * - NFC Forum T4T Technical Specification 1.0 2017-08-28 + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-AL + * \brief RFAL Abstraction Layer + * @{ + * + * \addtogroup T4T + * \brief RFAL T4T Module + * @{ + * + */ + +#ifndef RFAL_T4T_H +#define RFAL_T4T_H + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "../platform.h" +#include "../st_errno.h" +#include "rfal_rf.h" +#include "rfal_isoDep.h" + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ + +#define RFAL_T4T_MAX_CAPDU_PROLOGUE_LEN \ + 4U /*!< Command-APDU prologue length (CLA INS P1 P2) */ +#define RFAL_T4T_LE_LEN 1U /*!< Le Expected Response Length (short field coding) */ +#define RFAL_T4T_LC_LEN 1U /*!< Lc Data field length (short field coding) */ +#define RFAL_T4T_MAX_RAPDU_SW1SW2_LEN \ + 2U /*!< SW1 SW2 length */ +#define RFAL_T4T_CLA 0x00U /*!< Class byte (contains 00h because secure message are not used) */ + +#define RFAL_T4T_ISO7816_P1_SELECT_BY_DF_NAME \ + 0x04U /*!< P1 value for Select by name */ +#define RFAL_T4T_ISO7816_P1_SELECT_BY_FILEID \ + 0x00U /*!< P1 value for Select by file identifier */ +#define RFAL_T4T_ISO7816_P2_SELECT_FIRST_OR_ONLY_OCCURENCE \ + 0x00U /*!< b2b1 P2 value for First or only occurrence */ +#define RFAL_T4T_ISO7816_P2_SELECT_RETURN_FCI_TEMPLATE \ + 0x00U /*!< b4b3 P2 value for Return FCI template */ +#define RFAL_T4T_ISO7816_P2_SELECT_NO_RESPONSE_DATA \ + 0x0CU /*!< b4b3 P2 value for No response data */ + +#define RFAL_T4T_ISO7816_STATUS_COMPLETE \ + 0x9000U /*!< Command completed \ Normal processing - No further qualification*/ + +/* +****************************************************************************** +* GLOBAL VARIABLES +****************************************************************************** +*/ + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ +/*! NFC-A T4T Command-APDU structure */ +typedef struct { + uint8_t CLA; /*!< Class byte */ + uint8_t INS; /*!< Instruction byte */ + uint8_t P1; /*!< Parameter byte 1 */ + uint8_t P2; /*!< Parameter byte 2 */ + uint8_t Lc; /*!< Data field length */ + bool LcFlag; /*!< Lc flag (append Lc when true) */ + uint8_t Le; /*!< Expected Response Length */ + bool LeFlag; /*!< Le flag (append Le when true) */ + + rfalIsoDepApduBufFormat* cApduBuf; /*!< Command-APDU buffer (Tx) */ + uint16_t* cApduLen; /*!< Command-APDU Length */ +} rfalT4tCApduParam; + +/*! NFC-A T4T Response-APDU structure */ +typedef struct { + rfalIsoDepApduBufFormat* rApduBuf; /*!< Response-APDU buffer (Rx) */ + uint16_t rcvdLen; /*!< Full response length */ + uint16_t rApduBodyLen; /*!< Response body length */ + uint16_t statusWord; /*!< R-APDU Status Word SW1|SW2 */ +} rfalT4tRApduParam; + +/*! NFC-A T4T command set T4T 1.0 & ISO7816-4 2013 Table 4 */ +typedef enum { + RFAL_T4T_INS_SELECT = 0xA4U, /*!< T4T Select */ + RFAL_T4T_INS_READBINARY = 0xB0U, /*!< T4T ReadBinary */ + RFAL_T4T_INS_UPDATEBINARY = 0xD6U, /*!< T4T UpdateBinay */ + RFAL_T4T_INS_READBINARY_ODO = 0xB1U, /*!< T4T ReadBinary using ODO */ + RFAL_T4T_INS_UPDATEBINARY_ODO = + 0xD7U /*!< T4T UpdateBinay using ODO */ +} rfalT4tCmds; + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +/*! + ***************************************************************************** + * \brief T4T Compose APDU + * + * This method computes a C-APDU according to NFC Forum T4T and ISO7816-4. + * + * If C-APDU contains data to be sent, it must be placed inside the buffer + * rfalT4tTxRxApduParam.txRx.cApduBuf.apdu and signaled by Lc + * + * To transceive the formed APDU the ISO-DEP layer shall be used + * + * \see rfalIsoDepStartApduTransceive() + * \see rfalIsoDepGetApduTransceiveStatus() + * \see rfalT4TPollerParseRAPDU() + * + * \warning The ISO-DEP module is used to perform the tranceive. Usually + * activation has been done via ISO-DEP activatiavtion. If not + * please call rfalIsoDepInitialize() before. + * + * \param[in,out] apduParam : APDU parameters + * apduParam.cApduLen will contain the APDU length + * + * \return ERR_PARAM : Invalid parameter + * \return ERR_PROTO : Protocol error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalT4TPollerComposeCAPDU(const rfalT4tCApduParam* apduParam); + +/*! + ***************************************************************************** + * \brief T4T Parse R-APDU + * + * This method parses a R-APDU according to NFC Forum T4T and ISO7816-4. + * It will extract the data length and check if the Status word is expected. + * + * \param[in,out] apduParam : APDU parameters + * apduParam.rApduBodyLen will contain the data length + * apduParam.statusWord will contain the SW1 and SW2 + * + * \return ERR_REQUEST : Status word (SW1 SW2) different from 9000 + * \return ERR_PARAM : Invalid parameter + * \return ERR_PROTO : Protocol error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalT4TPollerParseRAPDU(rfalT4tRApduParam* apduParam); + +/*! + ***************************************************************************** + * \brief T4T Compose Select Application APDU + * + * This method computes a Select Application APDU according to NFC Forum T4T + * + * To transceive the formed APDU the ISO-DEP layer shall be used + * + * \see rfalIsoDepStartApduTransceive() + * \see rfalIsoDepGetApduTransceiveStatus() + * + * \param[out] cApduBuf : buffer where the C-APDU will be placed + * \param[in] aid : Application ID to be used + * \param[in] aidLen : Application ID length + * \param[out] cApduLen : Composed C-APDU length + * + * \return ERR_PARAM : Invalid parameter + * \return ERR_PROTO : Protocol error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalT4TPollerComposeSelectAppl( + rfalIsoDepApduBufFormat* cApduBuf, + const uint8_t* aid, + uint8_t aidLen, + uint16_t* cApduLen); + +/*! + ***************************************************************************** + * \brief T4T Compose Select File APDU + * + * This method computes a Select File APDU according to NFC Forum T4T + * + * To transceive the formed APDU the ISO-DEP layer shall be used + * + * \see rfalIsoDepStartApduTransceive() + * \see rfalIsoDepGetApduTransceiveStatus() + * + * \param[out] cApduBuf : buffer where the C-APDU will be placed + * \param[in] fid : File ID to be used + * \param[in] fidLen : File ID length + * \param[out] cApduLen : Composed C-APDU length + * + * \return ERR_PARAM : Invalid parameter + * \return ERR_PROTO : Protocol error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalT4TPollerComposeSelectFile( + rfalIsoDepApduBufFormat* cApduBuf, + const uint8_t* fid, + uint8_t fidLen, + uint16_t* cApduLen); + +/*! + ***************************************************************************** + * \brief T4T Compose Select File APDU for Mapping Version 1 + * + * This method computes a Select File APDU according to NFC Forum T4TOP_v1.0 + * + * To transceive the formed APDU the ISO-DEP layer shall be used + * + * \see rfalIsoDepStartApduTransceive() + * \see rfalIsoDepGetApduTransceiveStatus() + * + * \param[out] cApduBuf : buffer where the C-APDU will be placed + * \param[in] fid : File ID to be used + * \param[in] fidLen : File ID length + * \param[out] cApduLen : Composed C-APDU length + * + * \return ERR_PARAM : Invalid parameter + * \return ERR_PROTO : Protocol error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalT4TPollerComposeSelectFileV1Mapping( + rfalIsoDepApduBufFormat* cApduBuf, + const uint8_t* fid, + uint8_t fidLen, + uint16_t* cApduLen); + +/*! + ***************************************************************************** + * \brief T4T Compose Read Data APDU + * + * This method computes a Read Data APDU according to NFC Forum T4T + * + * To transceive the formed APDU the ISO-DEP layer shall be used + * + * \see rfalIsoDepStartApduTransceive() + * \see rfalIsoDepGetApduTransceiveStatus() + * + * \param[out] cApduBuf : buffer where the C-APDU will be placed + * \param[in] offset : File offset + * \param[in] expLen : Expected length (Le) + * \param[out] cApduLen : Composed C-APDU length + * + * \return ERR_PARAM : Invalid parameter + * \return ERR_PROTO : Protocol error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalT4TPollerComposeReadData( + rfalIsoDepApduBufFormat* cApduBuf, + uint16_t offset, + uint8_t expLen, + uint16_t* cApduLen); + +/*! + ***************************************************************************** + * \brief T4T Compose Read Data ODO APDU + * + * This method computes a Read Data ODO APDU according to NFC Forum T4T + * + * To transceive the formed APDU the ISO-DEP layer shall be used + * + * \see rfalIsoDepStartApduTransceive() + * \see rfalIsoDepGetApduTransceiveStatus() + * + * \param[out] cApduBuf : buffer where the C-APDU will be placed + * \param[in] offset : File offset + * \param[in] expLen : Expected length (Le) + * \param[out] cApduLen : Composed C-APDU length + * + * \return ERR_PARAM : Invalid parameter + * \return ERR_PROTO : Protocol error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalT4TPollerComposeReadDataODO( + rfalIsoDepApduBufFormat* cApduBuf, + uint32_t offset, + uint8_t expLen, + uint16_t* cApduLen); + +/*! + ***************************************************************************** + * \brief T4T Compose Write Data APDU + * + * This method computes a Write Data APDU according to NFC Forum T4T + * + * To transceive the formed APDU the ISO-DEP layer shall be used + * + * \see rfalIsoDepStartApduTransceive() + * \see rfalIsoDepGetApduTransceiveStatus() + * + * \param[out] cApduBuf : buffer where the C-APDU will be placed + * \param[in] offset : File offset + * \param[in] data : Data to be written + * \param[in] dataLen : Data length to be written (Lc) + * \param[out] cApduLen : Composed C-APDU length + * + * \return ERR_PARAM : Invalid parameter + * \return ERR_PROTO : Protocol error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalT4TPollerComposeWriteData( + rfalIsoDepApduBufFormat* cApduBuf, + uint16_t offset, + const uint8_t* data, + uint8_t dataLen, + uint16_t* cApduLen); + +/*! + ***************************************************************************** + * \brief T4T Compose Write Data ODO APDU + * + * This method computes a Write Data ODO sAPDU according to NFC Forum T4T + * + * To transceive the formed APDU the ISO-DEP layer shall be used + * + * \see rfalIsoDepStartApduTransceive() + * \see rfalIsoDepGetApduTransceiveStatus() + * + * \param[out] cApduBuf : buffer where the C-APDU will be placed + * \param[in] offset : File offset + * \param[in] data : Data to be written + * \param[in] dataLen : Data length to be written (Lc) + * \param[out] cApduLen : Composed C-APDU length + * + * \return ERR_PARAM : Invalid parameter + * \return ERR_PROTO : Protocol error + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode rfalT4TPollerComposeWriteDataODO( + rfalIsoDepApduBufFormat* cApduBuf, + uint32_t offset, + const uint8_t* data, + uint8_t dataLen, + uint16_t* cApduLen); + +#endif /* RFAL_T4T_H */ + +/** + * @} + * + * @} + * + * @} + */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/platform.c b/esubghz_chat/lib/nfclegacy/ST25RFAL002/platform.c new file mode 100644 index 00000000000..cc1a1f19366 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/platform.c @@ -0,0 +1,104 @@ +#include "platform.h" +#include +#include +#include + +typedef struct { + FuriThread* thread; + volatile PlatformIrqCallback callback; + bool need_spi_lock; +} RfalPlatform; + +static volatile RfalPlatform rfal_platform = { + .thread = NULL, + .callback = NULL, + .need_spi_lock = true, +}; + +void nfc_isr(void* _ctx) { + UNUSED(_ctx); + if(rfal_platform.callback && platformGpioIsHigh(ST25R_INT_PORT, ST25R_INT_PIN)) { + furi_thread_flags_set(furi_thread_get_id(rfal_platform.thread), 0x1); + } +} + +int32_t rfal_platform_irq_thread(void* context) { + UNUSED(context); + + while(1) { + uint32_t flags = furi_thread_flags_wait(0x1, FuriFlagWaitAny, FuriWaitForever); + if(flags & 0x1) { + rfal_platform.callback(); + } + } +} + +void platformEnableIrqCallback() { + furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeInterruptRise, GpioPullDown, GpioSpeedLow); + furi_hal_gpio_enable_int_callback(&gpio_nfc_irq_rfid_pull); +} + +void platformDisableIrqCallback() { + furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_disable_int_callback(&gpio_nfc_irq_rfid_pull); +} + +void platformSetIrqCallback(PlatformIrqCallback callback) { + rfal_platform.callback = callback; + + if(!rfal_platform.thread) { + rfal_platform.thread = + furi_thread_alloc_ex("RfalIrqDriver", 1024, rfal_platform_irq_thread, NULL); + furi_thread_set_priority(rfal_platform.thread, FuriThreadPriorityIsr); + furi_thread_start(rfal_platform.thread); + } + + furi_hal_gpio_remove_int_callback(&gpio_nfc_irq_rfid_pull); + + furi_hal_gpio_add_int_callback(&gpio_nfc_irq_rfid_pull, nfc_isr, NULL); + // Disable interrupt callback as the pin is shared between 2 apps + // It is enabled in rfalLowPowerModeStop() + furi_hal_gpio_disable_int_callback(&gpio_nfc_irq_rfid_pull); +} + +bool platformSpiTxRx(const uint8_t* txBuf, uint8_t* rxBuf, uint16_t len) { + bool ret = false; + if(txBuf && rxBuf) { + ret = + furi_hal_spi_bus_trx(&furi_hal_spi_bus_handle_nfc, (uint8_t*)txBuf, rxBuf, len, 1000); + } else if(txBuf) { + ret = furi_hal_spi_bus_tx(&furi_hal_spi_bus_handle_nfc, (uint8_t*)txBuf, len, 1000); + } else if(rxBuf) { + ret = furi_hal_spi_bus_rx(&furi_hal_spi_bus_handle_nfc, (uint8_t*)rxBuf, len, 1000); + } + + return ret; +} + +// Until we completely remove RFAL, NFC works with SPI from rfal_platform_irq_thread and nfc_worker +// threads. Some nfc features already stop using RFAL and work with SPI from nfc_worker only. +// rfal_platform_spi_acquire() and rfal_platform_spi_release() functions are used to lock SPI for a +// long term without locking it for each SPI transaction. This is needed for time critical communications. +void rfal_platform_spi_acquire() { + platformDisableIrqCallback(); + rfal_platform.need_spi_lock = false; + furi_hal_spi_acquire(&furi_hal_spi_bus_handle_nfc); +} + +void rfal_platform_spi_release() { + furi_hal_spi_release(&furi_hal_spi_bus_handle_nfc); + rfal_platform.need_spi_lock = true; + platformEnableIrqCallback(); +} + +void platformProtectST25RComm() { + if(rfal_platform.need_spi_lock) { + furi_hal_spi_acquire(&furi_hal_spi_bus_handle_nfc); + } +} + +void platformUnprotectST25RComm() { + if(rfal_platform.need_spi_lock) { + furi_hal_spi_release(&furi_hal_spi_bus_handle_nfc); + } +} diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/platform.h b/esubghz_chat/lib/nfclegacy/ST25RFAL002/platform.h new file mode 100644 index 00000000000..d86bba73e36 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/platform.h @@ -0,0 +1,188 @@ +#pragma once + +#include +#include +#include +#include +#include "timer.h" +#include "math.h" +#include +#include +#include + +typedef void (*PlatformIrqCallback)(); +void platformSetIrqCallback(PlatformIrqCallback cb); +void platformEnableIrqCallback(); +void platformDisableIrqCallback(); + +bool platformSpiTxRx(const uint8_t* txBuf, uint8_t* rxBuf, uint16_t len); +void platformProtectST25RComm(); +void platformUnprotectST25RComm(); +void rfal_platform_spi_acquire(); +void rfal_platform_spi_release(); + +#define ST25R_SS_PIN NFC_CS_Pin +#define ST25R_SS_PORT NFC_CS_GPIO_Port + +#define ST25R_INT_PIN NFC_IRQ_Pin +#define ST25R_INT_PORT NFC_IRQ_GPIO_Port + +#define RFAL_ANALOG_CONFIG_CUSTOM \ + true /*!< Enable/Disable RFAL custom analog configuration */ + +#define RFAL_FEATURE_LISTEN_MODE \ + true /*!< Enable/Disable RFAL support for Listen Mode */ +#define RFAL_FEATURE_WAKEUP_MODE \ + true /*!< Enable/Disable RFAL support for the Wake-Up mode */ +#define RFAL_FEATURE_LOWPOWER_MODE \ + true /*!< Enable/Disable RFAL support for the Low Power mode */ +#define RFAL_FEATURE_NFCA \ + true /*!< Enable/Disable RFAL support for NFC-A (ISO14443A) */ +#define RFAL_FEATURE_NFCB \ + true /*!< Enable/Disable RFAL support for NFC-B (ISO14443B) */ +#define RFAL_FEATURE_NFCF \ + true /*!< Enable/Disable RFAL support for NFC-F (FeliCa) */ +#define RFAL_FEATURE_NFCV \ + true /*!< Enable/Disable RFAL support for NFC-V (ISO15693) */ +#define RFAL_FEATURE_T1T \ + true /*!< Enable/Disable RFAL support for T1T (Topaz) */ +#define RFAL_FEATURE_T2T \ + true /*!< Enable/Disable RFAL support for T2T (MIFARE Ultralight) */ +#define RFAL_FEATURE_T4T \ + true /*!< Enable/Disable RFAL support for T4T */ +#define RFAL_FEATURE_ST25TB \ + true /*!< Enable/Disable RFAL support for ST25TB */ +#define RFAL_FEATURE_ST25xV \ + true /*!< Enable/Disable RFAL support for ST25TV/ST25DV */ +#define RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG \ + false /*!< Enable/Disable Analog Configs to be dynamically updated (RAM) */ +#define RFAL_FEATURE_DPO \ + false /*!< Enable/Disable RFAL Dynamic Power Output upport */ +#define RFAL_FEATURE_ISO_DEP \ + true /*!< Enable/Disable RFAL support for ISO-DEP (ISO14443-4) */ +#define RFAL_FEATURE_ISO_DEP_POLL \ + true /*!< Enable/Disable RFAL support for Poller mode (PCD) ISO-DEP (ISO14443-4) */ +#define RFAL_FEATURE_ISO_DEP_LISTEN \ + true /*!< Enable/Disable RFAL support for Listen mode (PICC) ISO-DEP (ISO14443-4) */ +#define RFAL_FEATURE_NFC_DEP \ + true /*!< Enable/Disable RFAL support for NFC-DEP (NFCIP1/P2P) */ + +#define RFAL_FEATURE_ISO_DEP_IBLOCK_MAX_LEN \ + 256U /*!< ISO-DEP I-Block max length. Please use values as defined by rfalIsoDepFSx */ +#define RFAL_FEATURE_NFC_DEP_BLOCK_MAX_LEN \ + 254U /*!< NFC-DEP Block/Payload length. Allowed values: 64, 128, 192, 254 */ +#define RFAL_FEATURE_NFC_RF_BUF_LEN \ + 256U /*!< RF buffer length used by RFAL NFC layer */ + +#define RFAL_FEATURE_ISO_DEP_APDU_MAX_LEN \ + 512U /*!< ISO-DEP APDU max length. */ +#define RFAL_FEATURE_NFC_DEP_PDU_MAX_LEN \ + 512U /*!< NFC-DEP PDU max length. */ + +#define platformIrqST25RSetCallback(cb) platformSetIrqCallback(cb) + +#define platformProtectST25RIrqStatus() \ + platformProtectST25RComm() /*!< Protect unique access to IRQ status var - IRQ disable on single thread environment (MCU) ; Mutex lock on a multi thread environment */ +#define platformUnprotectST25RIrqStatus() \ + platformUnprotectST25RComm() /*!< Unprotect the IRQ status var - IRQ enable on a single thread environment (MCU) ; Mutex unlock on a multi thread environment */ + +#define platformGpioSet(port, pin) \ + furi_hal_gpio_write_port_pin( \ + port, pin, true) /*!< Turns the given GPIO High */ +#define platformGpioClear(port, pin) \ + furi_hal_gpio_write_port_pin( \ + port, pin, false) /*!< Turns the given GPIO Low */ + +#define platformGpioIsHigh(port, pin) \ + (furi_hal_gpio_read_port_pin(port, pin) == \ + true) /*!< Checks if the given LED is High */ +#define platformGpioIsLow(port, pin) \ + (!platformGpioIsHigh(port, pin)) /*!< Checks if the given LED is Low */ + +#define platformTimerCreate(t) \ + timerCalculateTimer(t) /*!< Create a timer with the given time (ms) */ +#define platformTimerIsExpired(timer) \ + timerIsExpired(timer) /*!< Checks if the given timer is expired */ +#define platformDelay(t) furi_delay_ms(t) /*!< Performs a delay for the given time (ms) */ + +#define platformGetSysTick() furi_get_tick() /*!< Get System Tick (1 tick = 1 ms) */ + +#define platformAssert(exp) assert_param(exp) /*!< Asserts whether the given expression is true*/ + +#define platformSpiSelect() \ + platformGpioClear( \ + ST25R_SS_PORT, ST25R_SS_PIN) /*!< SPI SS\CS: Chip|Slave Select */ +#define platformSpiDeselect() \ + platformGpioSet( \ + ST25R_SS_PORT, ST25R_SS_PIN) /*!< SPI SS\CS: Chip|Slave Deselect */ + +#define platformI2CTx(txBuf, len, last, txOnly) /*!< I2C Transmit */ +#define platformI2CRx(txBuf, len) /*!< I2C Receive */ +#define platformI2CStart() /*!< I2C Start condition */ +#define platformI2CStop() /*!< I2C Stop condition */ +#define platformI2CRepeatStart() /*!< I2C Repeat Start */ +#define platformI2CSlaveAddrWR(add) /*!< I2C Slave address for Write operation */ +#define platformI2CSlaveAddrRD(add) /*!< I2C Slave address for Read operation */ + +#define platformLog(...) /*!< Log method */ + +/* + ****************************************************************************** + * RFAL OPTIONAL MACROS (Do not change) + ****************************************************************************** + */ +#ifndef platformProtectST25RIrqStatus +#define platformProtectST25RIrqStatus() /*!< Protect unique access to IRQ status var - IRQ disable on single thread environment (MCU) ; Mutex lock on a multi thread environment */ +#endif /* platformProtectST25RIrqStatus */ + +#ifndef platformUnprotectST25RIrqStatus +#define platformUnprotectST25RIrqStatus() /*!< Unprotect the IRQ status var - IRQ enable on a single thread environment (MCU) ; Mutex unlock on a multi thread environment */ +#endif /* platformUnprotectST25RIrqStatus */ + +#ifndef platformProtectWorker +#define platformProtectWorker() /* Protect RFAL Worker/Task/Process from concurrent execution on multi thread platforms */ +#endif /* platformProtectWorker */ + +#ifndef platformUnprotectWorker +#define platformUnprotectWorker() /* Unprotect RFAL Worker/Task/Process from concurrent execution on multi thread platforms */ +#endif /* platformUnprotectWorker */ + +#ifndef platformIrqST25RPinInitialize +#define platformIrqST25RPinInitialize() /*!< Initializes ST25R IRQ pin */ +#endif /* platformIrqST25RPinInitialize */ + +#ifndef platformIrqST25RSetCallback +#define platformIrqST25RSetCallback(cb) /*!< Sets ST25R ISR callback */ +#endif /* platformIrqST25RSetCallback */ + +#ifndef platformLedsInitialize +#define platformLedsInitialize() /*!< Initializes the pins used as LEDs to outputs */ +#endif /* platformLedsInitialize */ + +#ifndef platformLedOff +#define platformLedOff(port, pin) /*!< Turns the given LED Off */ +#endif /* platformLedOff */ + +#ifndef platformLedOn +#define platformLedOn(port, pin) /*!< Turns the given LED On */ +#endif /* platformLedOn */ + +#ifndef platformLedToogle +#define platformLedToogle(port, pin) /*!< Toggles the given LED */ +#endif /* platformLedToogle */ + +#ifndef platformGetSysTick +#define platformGetSysTick() /*!< Get System Tick (1 tick = 1 ms) */ +#endif /* platformGetSysTick */ + +#ifndef platformTimerDestroy +#define platformTimerDestroy(timer) /*!< Stops and released the given timer */ +#endif /* platformTimerDestroy */ + +#ifndef platformAssert +#define platformAssert(exp) /*!< Asserts whether the given expression is true */ +#endif /* platformAssert */ + +#ifndef platformErrorHandle +#define platformErrorHandle() /*!< Global error handler or trap */ +#endif /* platformErrorHandle */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/custom_analog_config.c b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/custom_analog_config.c new file mode 100644 index 00000000000..713b5988153 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/custom_analog_config.c @@ -0,0 +1,777 @@ +#include "st25r3916/rfal_analogConfigTbl.h" + +const uint8_t rfalAnalogConfigCustomSettings[] = { + /****** Default Analog Configuration for Chip-Specific Reset ******/ + MODE_ENTRY_16_REG( + (RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_INIT), + ST25R3916_REG_IO_CONF1, + (ST25R3916_REG_IO_CONF1_out_cl_mask | ST25R3916_REG_IO_CONF1_lf_clk_off), + 0x07 /* Disable MCU_CLK */ + , + ST25R3916_REG_IO_CONF2, + (ST25R3916_REG_IO_CONF2_miso_pd1 | ST25R3916_REG_IO_CONF2_miso_pd2), + 0x18 /* SPI Pull downs */ + // , ST25R3916_REG_IO_CONF2, ST25R3916_REG_IO_CONF2_aat_en, ST25R3916_REG_IO_CONF2_aat_en /* Enable AAT */ + , + ST25R3916_REG_TX_DRIVER, + ST25R3916_REG_TX_DRIVER_d_res_mask, + 0x00 /* Set RFO resistance Active Tx */ + , + ST25R3916_REG_RES_AM_MOD, + 0xFF, + 0x80 /* Use minimum non-overlap */ + , + ST25R3916_REG_FIELD_THRESHOLD_ACTV, + ST25R3916_REG_FIELD_THRESHOLD_ACTV_trg_mask, + ST25R3916_REG_FIELD_THRESHOLD_ACTV_trg_105mV /* Lower activation threshold (higher than deactivation)*/ + , + ST25R3916_REG_FIELD_THRESHOLD_ACTV, + ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_mask, + ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_105mV /* Lower activation threshold (higher than deactivation)*/ + , + ST25R3916_REG_FIELD_THRESHOLD_DEACTV, + ST25R3916_REG_FIELD_THRESHOLD_DEACTV_trg_mask, + ST25R3916_REG_FIELD_THRESHOLD_DEACTV_trg_75mV /* Lower deactivation threshold */ + , + ST25R3916_REG_FIELD_THRESHOLD_DEACTV, + ST25R3916_REG_FIELD_THRESHOLD_DEACTV_rfe_mask, + ST25R3916_REG_FIELD_THRESHOLD_DEACTV_rfe_75mV /* Lower deactivation threshold */ + , + ST25R3916_REG_AUX_MOD, + ST25R3916_REG_AUX_MOD_lm_ext, + ST25R3916_REG_AUX_MOD_lm_ext /* Disable External Load Modulation */ + , + ST25R3916_REG_AUX_MOD, + ST25R3916_REG_AUX_MOD_lm_dri, + ST25R3916_REG_AUX_MOD_lm_dri /* Use internal Load Modulation */ + , + ST25R3916_REG_PASSIVE_TARGET, + ST25R3916_REG_PASSIVE_TARGET_fdel_mask, + (5U + << ST25R3916_REG_PASSIVE_TARGET_fdel_shift) /* Adjust the FDT to be aligned with the bitgrid */ + , + ST25R3916_REG_PT_MOD, + (ST25R3916_REG_PT_MOD_ptm_res_mask | ST25R3916_REG_PT_MOD_pt_res_mask), + 0x0f /* Reduce RFO resistance in Modulated state */ + , + ST25R3916_REG_EMD_SUP_CONF, + ST25R3916_REG_EMD_SUP_CONF_rx_start_emv, + ST25R3916_REG_EMD_SUP_CONF_rx_start_emv_on /* Enable start on first 4 bits */ + , + ST25R3916_REG_ANT_TUNE_A, + 0xFF, + 0x82 /* Set Antenna Tuning (Poller): ANTL */ + , + ST25R3916_REG_ANT_TUNE_B, + 0xFF, + 0x82 /* Set Antenna Tuning (Poller): ANTL */ + , + 0x84U, + 0x10, + 0x10 /* Avoid chip internal overheat protection */ + ) + + /****** Default Analog Configuration for Chip-Specific Poll Common ******/ + , + MODE_ENTRY_9_REG( + (RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_POLL_COMMON), + ST25R3916_REG_MODE, + ST25R3916_REG_MODE_tr_am, + ST25R3916_REG_MODE_tr_am_am /* Use AM modulation */ + , + ST25R3916_REG_TX_DRIVER, + ST25R3916_REG_TX_DRIVER_am_mod_mask, + ST25R3916_REG_TX_DRIVER_am_mod_12percent /* Set Modulation index */ + , + ST25R3916_REG_AUX_MOD, + (ST25R3916_REG_AUX_MOD_dis_reg_am | ST25R3916_REG_AUX_MOD_res_am), + 0x00 /* Use AM via regulator */ + , + ST25R3916_REG_ANT_TUNE_A, + 0xFF, + 0x82 /* Set Antenna Tuning (Poller): ANTL */ + , + ST25R3916_REG_ANT_TUNE_B, + 0xFF, + 0x82 /* Set Antenna Tuning (Poller): ANTL */ + , + ST25R3916_REG_OVERSHOOT_CONF1, + 0xFF, + 0x00 /* Disable Overshoot Protection */ + , + ST25R3916_REG_OVERSHOOT_CONF2, + 0xFF, + 0x00 /* Disable Overshoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF1, + 0xFF, + 0x00 /* Disable Undershoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF2, + 0xFF, + 0x00 /* Disable Undershoot Protection */ + ) + + /****** Default Analog Configuration for Poll NFC-A Rx Common ******/ + , + MODE_ENTRY_1_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_AUX, + ST25R3916_REG_AUX_dis_corr, + ST25R3916_REG_AUX_dis_corr_correlator /* Use Correlator Receiver */ + ) + + /****** Default Analog Configuration for Poll NFC-A Tx 106 ******/ + , + MODE_ENTRY_5_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | RFAL_ANALOG_CONFIG_BITRATE_106 | + RFAL_ANALOG_CONFIG_TX), + ST25R3916_REG_MODE, + ST25R3916_REG_MODE_tr_am, + ST25R3916_REG_MODE_tr_am_ook /* Use OOK */ + , + ST25R3916_REG_OVERSHOOT_CONF1, + 0xFF, + 0x40 /* Set default Overshoot Protection */ + , + ST25R3916_REG_OVERSHOOT_CONF2, + 0xFF, + 0x03 /* Set default Overshoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF1, + 0xFF, + 0x40 /* Set default Undershoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF2, + 0xFF, + 0x03 /* Set default Undershoot Protection */ + ) + + /****** Default Analog Configuration for Poll NFC-A Rx 106 ******/ + , + MODE_ENTRY_6_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | RFAL_ANALOG_CONFIG_BITRATE_106 | + RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_RX_CONF1, + 0xFF, + 0x08, + ST25R3916_REG_RX_CONF2, + 0xFF, + 0x2D, + ST25R3916_REG_RX_CONF3, + 0xFF, + 0x00, + ST25R3916_REG_RX_CONF4, + 0xFF, + 0x00, + ST25R3916_REG_CORR_CONF1, + 0xFF, + 0x51, + ST25R3916_REG_CORR_CONF2, + 0xFF, + 0x00) + + /****** Default Analog Configuration for Poll NFC-A Tx 212 ******/ + , + MODE_ENTRY_7_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | RFAL_ANALOG_CONFIG_BITRATE_212 | + RFAL_ANALOG_CONFIG_TX), + ST25R3916_REG_MODE, + ST25R3916_REG_MODE_tr_am, + ST25R3916_REG_MODE_tr_am_am /* Use AM modulation */ + , + ST25R3916_REG_AUX_MOD, + (ST25R3916_REG_AUX_MOD_dis_reg_am | ST25R3916_REG_AUX_MOD_res_am), + 0x88 /* Use Resistive AM */ + , + ST25R3916_REG_RES_AM_MOD, + ST25R3916_REG_RES_AM_MOD_md_res_mask, + 0x7F /* Set Resistive modulation */ + , + ST25R3916_REG_OVERSHOOT_CONF1, + 0xFF, + 0x40 /* Set default Overshoot Protection */ + , + ST25R3916_REG_OVERSHOOT_CONF2, + 0xFF, + 0x03 /* Set default Overshoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF1, + 0xFF, + 0x40 /* Set default Undershoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF2, + 0xFF, + 0x03 /* Set default Undershoot Protection */ + ) + + /****** Default Analog Configuration for Poll NFC-A Rx 212 ******/ + , + MODE_ENTRY_6_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | RFAL_ANALOG_CONFIG_BITRATE_212 | + RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_RX_CONF1, + 0xFF, + 0x02, + ST25R3916_REG_RX_CONF2, + 0xFF, + 0x3D, + ST25R3916_REG_RX_CONF3, + 0xFF, + 0x00, + ST25R3916_REG_RX_CONF4, + 0xFF, + 0x00, + ST25R3916_REG_CORR_CONF1, + 0xFF, + 0x14, + ST25R3916_REG_CORR_CONF2, + 0xFF, + 0x00) + + /****** Default Analog Configuration for Poll NFC-A Tx 424 ******/ + , + MODE_ENTRY_7_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | RFAL_ANALOG_CONFIG_BITRATE_424 | + RFAL_ANALOG_CONFIG_TX), + ST25R3916_REG_MODE, + ST25R3916_REG_MODE_tr_am, + ST25R3916_REG_MODE_tr_am_am /* Use AM modulation */ + , + ST25R3916_REG_AUX_MOD, + (ST25R3916_REG_AUX_MOD_dis_reg_am | ST25R3916_REG_AUX_MOD_res_am), + 0x88 /* Use Resistive AM */ + , + ST25R3916_REG_RES_AM_MOD, + ST25R3916_REG_RES_AM_MOD_md_res_mask, + 0x7F /* Set Resistive modulation */ + , + ST25R3916_REG_OVERSHOOT_CONF1, + 0xFF, + 0x40 /* Set default Overshoot Protection */ + , + ST25R3916_REG_OVERSHOOT_CONF2, + 0xFF, + 0x03 /* Set default Overshoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF1, + 0xFF, + 0x40 /* Set default Undershoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF2, + 0xFF, + 0x03 /* Set default Undershoot Protection */ + ) + + /****** Default Analog Configuration for Poll NFC-A Rx 424 ******/ + , + MODE_ENTRY_6_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | RFAL_ANALOG_CONFIG_BITRATE_424 | + RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_RX_CONF1, + 0xFF, + 0x42, + ST25R3916_REG_RX_CONF2, + 0xFF, + 0x3D, + ST25R3916_REG_RX_CONF3, + 0xFF, + 0x00, + ST25R3916_REG_RX_CONF4, + 0xFF, + 0x00, + ST25R3916_REG_CORR_CONF1, + 0xFF, + 0x54, + ST25R3916_REG_CORR_CONF2, + 0xFF, + 0x00) + + /****** Default Analog Configuration for Poll NFC-A Tx 848 ******/ + , + MODE_ENTRY_7_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | RFAL_ANALOG_CONFIG_BITRATE_848 | + RFAL_ANALOG_CONFIG_TX), + ST25R3916_REG_MODE, + ST25R3916_REG_MODE_tr_am, + ST25R3916_REG_MODE_tr_am_am /* Use AM modulation */ + , + ST25R3916_REG_TX_DRIVER, + ST25R3916_REG_TX_DRIVER_am_mod_mask, + ST25R3916_REG_TX_DRIVER_am_mod_40percent /* Set Modulation index */ + , + ST25R3916_REG_AUX_MOD, + (ST25R3916_REG_AUX_MOD_dis_reg_am | ST25R3916_REG_AUX_MOD_res_am), + 0x00 /* Use AM via regulator */ + , + ST25R3916_REG_OVERSHOOT_CONF1, + 0xFF, + 0x00 /* Disable Overshoot Protection */ + , + ST25R3916_REG_OVERSHOOT_CONF2, + 0xFF, + 0x00 /* Disable Overshoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF1, + 0xFF, + 0x00 /* Disable Undershoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF2, + 0xFF, + 0x00 /* Disable Undershoot Protection */ + ) + + /****** Default Analog Configuration for Poll NFC-A Rx 848 ******/ + , + MODE_ENTRY_6_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | RFAL_ANALOG_CONFIG_BITRATE_848 | + RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_RX_CONF1, + 0xFF, + 0x42, + ST25R3916_REG_RX_CONF2, + 0xFF, + 0x3D, + ST25R3916_REG_RX_CONF3, + 0xFF, + 0x00, + ST25R3916_REG_RX_CONF4, + 0xFF, + 0x00, + ST25R3916_REG_CORR_CONF1, + 0xFF, + 0x44, + ST25R3916_REG_CORR_CONF2, + 0xFF, + 0x00) + + /****** Default Analog Configuration for Poll NFC-A Anticolision setting ******/ + , + MODE_ENTRY_1_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_ANTICOL), + ST25R3916_REG_CORR_CONF1, + ST25R3916_REG_CORR_CONF1_corr_s6, + 0x00 /* Set collision detection level different from data */ + ) + +#ifdef RFAL_USE_COHE + /****** Default Analog Configuration for Poll NFC-B Rx Common ******/ + , + MODE_ENTRY_1_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCB | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_AUX, + ST25R3916_REG_AUX_dis_corr, + ST25R3916_REG_AUX_dis_corr_coherent /* Use Coherent Receiver */ + ) +#else + /****** Default Analog Configuration for Poll NFC-B Rx Common ******/ + , + MODE_ENTRY_1_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCB | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_AUX, + ST25R3916_REG_AUX_dis_corr, + ST25R3916_REG_AUX_dis_corr_correlator /* Use Correlator Receiver */ + ) +#endif /*RFAL_USE_COHE*/ + + /****** Default Analog Configuration for Poll NFC-B Rx 106 ******/ + , + MODE_ENTRY_6_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCB | RFAL_ANALOG_CONFIG_BITRATE_106 | + RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_RX_CONF1, + 0xFF, + 0x04, + ST25R3916_REG_RX_CONF2, + 0xFF, + 0x3D, + ST25R3916_REG_RX_CONF3, + 0xFF, + 0x00, + ST25R3916_REG_RX_CONF4, + 0xFF, + 0x00, + ST25R3916_REG_CORR_CONF1, + 0xFF, + 0x1B, + ST25R3916_REG_CORR_CONF2, + 0xFF, + 0x00) + + /****** Default Analog Configuration for Poll NFC-B Rx 212 ******/ + , + MODE_ENTRY_6_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCB | RFAL_ANALOG_CONFIG_BITRATE_212 | + RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_RX_CONF1, + 0xFF, + 0x02, + ST25R3916_REG_RX_CONF2, + 0xFF, + 0x3D, + ST25R3916_REG_RX_CONF3, + 0xFF, + 0x00, + ST25R3916_REG_RX_CONF4, + 0xFF, + 0x00, + ST25R3916_REG_CORR_CONF1, + 0xFF, + 0x14, + ST25R3916_REG_CORR_CONF2, + 0xFF, + 0x00) + + /****** Default Analog Configuration for Poll NFC-B Rx 424 ******/ + , + MODE_ENTRY_6_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCB | RFAL_ANALOG_CONFIG_BITRATE_424 | + RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_RX_CONF1, + 0xFF, + 0x42, + ST25R3916_REG_RX_CONF2, + 0xFF, + 0x3D, + ST25R3916_REG_RX_CONF3, + 0xFF, + 0x00, + ST25R3916_REG_RX_CONF4, + 0xFF, + 0x00, + ST25R3916_REG_CORR_CONF1, + 0xFF, + 0x54, + ST25R3916_REG_CORR_CONF2, + 0xFF, + 0x00) + + /****** Default Analog Configuration for Poll NFC-B Rx 848 ******/ + , + MODE_ENTRY_6_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCB | RFAL_ANALOG_CONFIG_BITRATE_848 | + RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_RX_CONF1, + 0xFF, + 0x42, + ST25R3916_REG_RX_CONF2, + 0xFF, + 0x3D, + ST25R3916_REG_RX_CONF3, + 0xFF, + 0x00, + ST25R3916_REG_RX_CONF4, + 0xFF, + 0x00, + ST25R3916_REG_CORR_CONF1, + 0xFF, + 0x44, + ST25R3916_REG_CORR_CONF2, + 0xFF, + 0x00) +#ifdef RFAL_USE_COHE + + /****** Default Analog Configuration for Poll NFC-F Rx Common ******/ + , + MODE_ENTRY_7_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCF | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_AUX, + ST25R3916_REG_AUX_dis_corr, + ST25R3916_REG_AUX_dis_corr_coherent /* Use Pulse Receiver */ + , + ST25R3916_REG_RX_CONF1, + 0xFF, + 0x13, + ST25R3916_REG_RX_CONF2, + 0xFF, + 0x3D, + ST25R3916_REG_RX_CONF3, + 0xFF, + 0x00, + ST25R3916_REG_RX_CONF4, + 0xFF, + 0x00, + ST25R3916_REG_CORR_CONF1, + 0xFF, + 0x54, + ST25R3916_REG_CORR_CONF2, + 0xFF, + 0x00) +#else + /****** Default Analog Configuration for Poll NFC-F Rx Common ******/ + , + MODE_ENTRY_7_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCF | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_AUX, + ST25R3916_REG_AUX_dis_corr, + ST25R3916_REG_AUX_dis_corr_correlator /* Use Correlator Receiver */ + , + ST25R3916_REG_RX_CONF1, + 0xFF, + 0x13, + ST25R3916_REG_RX_CONF2, + 0xFF, + 0x3D, + ST25R3916_REG_RX_CONF3, + 0xFF, + 0x00, + ST25R3916_REG_RX_CONF4, + 0xFF, + 0x00, + ST25R3916_REG_CORR_CONF1, + 0xFF, + 0x54, + ST25R3916_REG_CORR_CONF2, + 0xFF, + 0x00) +#endif /*RFAL_USE_COHE*/ + + , + MODE_ENTRY_1_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCV | RFAL_ANALOG_CONFIG_BITRATE_1OF4 | + RFAL_ANALOG_CONFIG_TX), + ST25R3916_REG_MODE, + ST25R3916_REG_MODE_tr_am, + ST25R3916_REG_MODE_tr_am_ook /* Use OOK */ + ) + +#ifdef RFAL_USE_COHE + /****** Default Analog Configuration for Poll NFC-V Rx Common ******/ + , + MODE_ENTRY_7_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCV | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_AUX, + ST25R3916_REG_AUX_dis_corr, + ST25R3916_REG_AUX_dis_corr_coherent /* Use Pulse Receiver */ + , + ST25R3916_REG_RX_CONF1, + 0xFF, + 0x13, + ST25R3916_REG_RX_CONF2, + 0xFF, + 0x2D, + ST25R3916_REG_RX_CONF3, + 0xFF, + 0x00, + ST25R3916_REG_RX_CONF4, + 0xFF, + 0x00, + ST25R3916_REG_CORR_CONF1, + 0xFF, + 0x13, + ST25R3916_REG_CORR_CONF2, + 0xFF, + 0x01) +#else + /****** Default Analog Configuration for Poll NFC-V Rx Common ******/ + , + MODE_ENTRY_7_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCV | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_AUX, + ST25R3916_REG_AUX_dis_corr, + ST25R3916_REG_AUX_dis_corr_correlator /* Use Correlator Receiver */ + , + ST25R3916_REG_RX_CONF1, + 0xFF, + 0x13, + ST25R3916_REG_RX_CONF2, + 0xFF, + 0x2D, + ST25R3916_REG_RX_CONF3, + 0xFF, + 0x00, + ST25R3916_REG_RX_CONF4, + 0xFF, + 0x00, + ST25R3916_REG_CORR_CONF1, + 0xFF, + 0x13, + ST25R3916_REG_CORR_CONF2, + 0xFF, + 0x01) +#endif /*RFAL_USE_COHE*/ + + /****** Default Analog Configuration for Poll AP2P Tx 106 ******/ + , + MODE_ENTRY_5_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_AP2P | RFAL_ANALOG_CONFIG_BITRATE_106 | + RFAL_ANALOG_CONFIG_TX), + ST25R3916_REG_MODE, + ST25R3916_REG_MODE_tr_am, + ST25R3916_REG_MODE_tr_am_ook /* Use OOK modulation */ + , + ST25R3916_REG_OVERSHOOT_CONF1, + 0xFF, + 0x40 /* Set default Overshoot Protection */ + , + ST25R3916_REG_OVERSHOOT_CONF2, + 0xFF, + 0x03 /* Set default Overshoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF1, + 0xFF, + 0x40 /* Set default Undershoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF2, + 0xFF, + 0x03 /* Set default Undershoot Protection */ + ) + + /****** Default Analog Configuration for Poll AP2P Tx 212 ******/ + , + MODE_ENTRY_1_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_AP2P | RFAL_ANALOG_CONFIG_BITRATE_212 | + RFAL_ANALOG_CONFIG_TX), + ST25R3916_REG_MODE, + ST25R3916_REG_MODE_tr_am, + ST25R3916_REG_MODE_tr_am_am /* Use AM modulation */ + ) + + /****** Default Analog Configuration for Poll AP2P Tx 424 ******/ + , + MODE_ENTRY_1_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_AP2P | RFAL_ANALOG_CONFIG_BITRATE_424 | + RFAL_ANALOG_CONFIG_TX), + ST25R3916_REG_MODE, + ST25R3916_REG_MODE_tr_am, + ST25R3916_REG_MODE_tr_am_am /* Use AM modulation */ + ) + + /****** Default Analog Configuration for Chip-Specific Listen On ******/ + , + MODE_ENTRY_6_REG( + (RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_LISTEN_ON), + ST25R3916_REG_ANT_TUNE_A, + 0xFF, + 0x00 /* Set Antenna Tuning (Listener): ANTL */ + , + ST25R3916_REG_ANT_TUNE_B, + 0xFF, + 0xff /* Set Antenna Tuning (Listener): ANTL */ + , + ST25R3916_REG_OVERSHOOT_CONF1, + 0xFF, + 0x00 /* Disable Overshoot Protection */ + , + ST25R3916_REG_OVERSHOOT_CONF2, + 0xFF, + 0x00 /* Disable Overshoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF1, + 0xFF, + 0x00 /* Disable Undershoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF2, + 0xFF, + 0x00 /* Disable Undershoot Protection */ + ) + + /****** Default Analog Configuration for Listen AP2P Tx Common ******/ + , + MODE_ENTRY_7_REG( + (RFAL_ANALOG_CONFIG_LISTEN | RFAL_ANALOG_CONFIG_TECH_AP2P | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_TX), + ST25R3916_REG_ANT_TUNE_A, + 0xFF, + 0x82 /* Set Antenna Tuning (Poller): ANTL */ + , + ST25R3916_REG_ANT_TUNE_B, + 0xFF, + 0x82 /* Set Antenna Tuning (Poller): ANTL */ + , + ST25R3916_REG_TX_DRIVER, + ST25R3916_REG_TX_DRIVER_am_mod_mask, + ST25R3916_REG_TX_DRIVER_am_mod_12percent /* Set Modulation index */ + , + ST25R3916_REG_OVERSHOOT_CONF1, + 0xFF, + 0x00 /* Disable Overshoot Protection */ + , + ST25R3916_REG_OVERSHOOT_CONF2, + 0xFF, + 0x00 /* Disable Overshoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF1, + 0xFF, + 0x00 /* Disable Undershoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF2, + 0xFF, + 0x00 /* Disable Undershoot Protection */ + ) + + /****** Default Analog Configuration for Listen AP2P Rx Common ******/ + , + MODE_ENTRY_3_REG( + (RFAL_ANALOG_CONFIG_LISTEN | RFAL_ANALOG_CONFIG_TECH_AP2P | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_RX_CONF1, + ST25R3916_REG_RX_CONF1_lp_mask, + ST25R3916_REG_RX_CONF1_lp_1200khz /* Set Rx filter configuration */ + , + ST25R3916_REG_RX_CONF1, + ST25R3916_REG_RX_CONF1_hz_mask, + ST25R3916_REG_RX_CONF1_hz_12_200khz /* Set Rx filter configuration */ + , + ST25R3916_REG_RX_CONF2, + ST25R3916_REG_RX_CONF2_amd_sel, + ST25R3916_REG_RX_CONF2_amd_sel_mixer /* AM demodulator: mixer */ + ) + + /****** Default Analog Configuration for Listen AP2P Tx 106 ******/ + , + MODE_ENTRY_5_REG( + (RFAL_ANALOG_CONFIG_LISTEN | RFAL_ANALOG_CONFIG_TECH_AP2P | + RFAL_ANALOG_CONFIG_BITRATE_106 | RFAL_ANALOG_CONFIG_TX), + ST25R3916_REG_MODE, + ST25R3916_REG_MODE_tr_am, + ST25R3916_REG_MODE_tr_am_ook /* Use OOK modulation */ + , + ST25R3916_REG_OVERSHOOT_CONF1, + 0xFF, + 0x40 /* Set default Overshoot Protection */ + , + ST25R3916_REG_OVERSHOOT_CONF2, + 0xFF, + 0x03 /* Set default Overshoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF1, + 0xFF, + 0x40 /* Set default Undershoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF2, + 0xFF, + 0x03 /* Set default Undershoot Protection */ + ) + + /****** Default Analog Configuration for Listen AP2P Tx 212 ******/ + , + MODE_ENTRY_1_REG( + (RFAL_ANALOG_CONFIG_LISTEN | RFAL_ANALOG_CONFIG_TECH_AP2P | + RFAL_ANALOG_CONFIG_BITRATE_212 | RFAL_ANALOG_CONFIG_TX), + ST25R3916_REG_MODE, + ST25R3916_REG_MODE_tr_am, + ST25R3916_REG_MODE_tr_am_am /* Use AM modulation */ + ) + + /****** Default Analog Configuration for Listen AP2P Tx 424 ******/ + , + MODE_ENTRY_1_REG( + (RFAL_ANALOG_CONFIG_LISTEN | RFAL_ANALOG_CONFIG_TECH_AP2P | + RFAL_ANALOG_CONFIG_BITRATE_424 | RFAL_ANALOG_CONFIG_TX), + ST25R3916_REG_MODE, + ST25R3916_REG_MODE_tr_am, + ST25R3916_REG_MODE_tr_am_am /* Use AM modulation */ + ) + +}; + +const uint16_t rfalAnalogConfigCustomSettingsLength = sizeof(rfalAnalogConfigCustomSettings); diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_analogConfig.c b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_analogConfig.c new file mode 100644 index 00000000000..b3dfbfe45ef --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_analogConfig.c @@ -0,0 +1,480 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_analogConfig.c + * + * \author bkam + * + * \brief Functions to manage and set analog settings. + * + */ + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "../include/rfal_analogConfig.h" +#include "../include/rfal_chip.h" +#include "../st_errno.h" +#include "../platform.h" +#include "../utils.h" + +/* Check whether the Default Analog settings are to be used or custom ones */ +#ifdef RFAL_ANALOG_CONFIG_CUSTOM +extern const uint8_t* rfalAnalogConfigCustomSettings; +extern const uint16_t rfalAnalogConfigCustomSettingsLength; +#else +#include "st25r3916/rfal_analogConfigTbl.h" +#endif + +/* + ****************************************************************************** + * DEFINES + ****************************************************************************** + */ + +#define RFAL_TEST_REG 0x0080U /*!< Test Register indicator */ + +/* + ****************************************************************************** + * MACROS + ****************************************************************************** + */ + +/* + ****************************************************************************** + * LOCAL DATA TYPES + ****************************************************************************** + */ + +#if RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG +static uint8_t + gRfalAnalogConfig[RFAL_ANALOG_CONFIG_TBL_SIZE]; /*!< Analog Configuration Settings List */ +#endif /* RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG */ + +/*! Struct for Analog Config Look Up Table Update */ +typedef struct { + const uint8_t* + currentAnalogConfigTbl; /*!< Reference to start of current Analog Configuration */ + uint16_t configTblSize; /*!< Total size of Analog Configuration */ + bool ready; /*!< Indicate if Look Up Table is complete and ready for use */ +} rfalAnalogConfigMgmt; + +static rfalAnalogConfigMgmt gRfalAnalogConfigMgmt; /*!< Analog Configuration LUT management */ + +/* + ****************************************************************************** + * LOCAL TABLES + ****************************************************************************** + */ + +/* + ****************************************************************************** + * LOCAL FUNCTION PROTOTYPES + ****************************************************************************** + */ +static rfalAnalogConfigNum + rfalAnalogConfigSearch(rfalAnalogConfigId configId, uint16_t* configOffset); + +#if RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG +static void rfalAnalogConfigPtrUpdate(const uint8_t* analogConfigTbl); +#endif /* RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG */ + +/* + ****************************************************************************** + * GLOBAL VARIABLE DEFINITIONS + ****************************************************************************** + */ + +/* + ****************************************************************************** + * GLOBAL FUNCTIONS + ****************************************************************************** + */ + +void rfalAnalogConfigInitialize(void) { + /* Use default Analog configuration settings in Flash by default. */ + +/* Check whether the Default Analog settings are to be used or custom ones */ +#ifdef RFAL_ANALOG_CONFIG_CUSTOM + gRfalAnalogConfigMgmt.currentAnalogConfigTbl = (const uint8_t*)&rfalAnalogConfigCustomSettings; + gRfalAnalogConfigMgmt.configTblSize = rfalAnalogConfigCustomSettingsLength; +#else + gRfalAnalogConfigMgmt.currentAnalogConfigTbl = + (const uint8_t*)&rfalAnalogConfigDefaultSettings; + gRfalAnalogConfigMgmt.configTblSize = sizeof(rfalAnalogConfigDefaultSettings); +#endif + + gRfalAnalogConfigMgmt.ready = true; +} /* rfalAnalogConfigInitialize() */ + +bool rfalAnalogConfigIsReady(void) { + return gRfalAnalogConfigMgmt.ready; +} + +ReturnCode rfalAnalogConfigListWriteRaw(const uint8_t* configTbl, uint16_t configTblSize) { +#if RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG + + /* Check if the Configuration Table exceed the Table size */ + if(configTblSize >= RFAL_ANALOG_CONFIG_TBL_SIZE) { + rfalAnalogConfigInitialize(); /* Revert to default Analog Configuration */ + return ERR_NOMEM; + } + + /* Check for invalid parameters */ + if((configTbl == NULL) || (configTblSize == 0U)) { + return ERR_PARAM; + } + + /* NOTE: Function does not check for the validity of the Table contents (conf IDs, conf sets, register address) */ + ST_MEMCPY(gRfalAnalogConfig, configTbl, configTblSize); + + /* Update the total size of configuration settings */ + gRfalAnalogConfigMgmt.configTblSize = configTblSize; + + rfalAnalogConfigPtrUpdate(gRfalAnalogConfig); + return ERR_NONE; + +#else + + // If Analog Configuration Update is to be disabled + NO_WARNING(configTbl); + NO_WARNING(configTblSize); + return ERR_REQUEST; + +#endif /* RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG */ +} + +ReturnCode rfalAnalogConfigListWrite(uint8_t more, const rfalAnalogConfig* config) { +#if RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG + + rfalAnalogConfigId configId; + rfalAnalogConfigNum numConfig; + uint8_t configSize; + + if(true == gRfalAnalogConfigMgmt.ready) { /* First Update to the Configuration list. */ + gRfalAnalogConfigMgmt.ready = false; // invalidate the config List + gRfalAnalogConfigMgmt.configTblSize = 0; // Clear the config List + } + + configId = GETU16(config->id); + + /* Check validity of the Configuration ID. */ + if((RFAL_ANALOG_CONFIG_TECH_RFU <= RFAL_ANALOG_CONFIG_ID_GET_TECH(configId)) || + ((RFAL_ANALOG_CONFIG_BITRATE_6780 < RFAL_ANALOG_CONFIG_ID_GET_BITRATE(configId)) && + (RFAL_ANALOG_CONFIG_BITRATE_1OF4 > RFAL_ANALOG_CONFIG_ID_GET_BITRATE(configId))) || + (RFAL_ANALOG_CONFIG_BITRATE_1OF256 < RFAL_ANALOG_CONFIG_ID_GET_BITRATE(configId))) { + rfalAnalogConfigInitialize(); /* Revert to default Analog Configuration */ + return ERR_PARAM; + } + + numConfig = config->num; + configSize = (uint8_t)(sizeof(rfalAnalogConfigId) + sizeof(rfalAnalogConfigNum) + + (numConfig * sizeof(rfalAnalogConfigRegAddrMaskVal))); + + /* Check if the Configuration Set exceed the Table size. */ + if(RFAL_ANALOG_CONFIG_TBL_SIZE <= (gRfalAnalogConfigMgmt.configTblSize + configSize)) { + rfalAnalogConfigInitialize(); /* Revert to default Analog Configuration */ + return ERR_NOMEM; + } + + /* NOTE: Function does not check for the validity of the Register Address. */ + ST_MEMCPY( + &gRfalAnalogConfig[gRfalAnalogConfigMgmt.configTblSize], + (const uint8_t*)config, + configSize); + + /* Increment the total size of configuration settings. */ + gRfalAnalogConfigMgmt.configTblSize += configSize; + + /* Check if it is the last Analog Configuration to load. */ + if(RFAL_ANALOG_CONFIG_UPDATE_LAST == + more) { /* Update the Analog Configuration to the new settings. */ + rfalAnalogConfigPtrUpdate(gRfalAnalogConfig); + } + + return ERR_NONE; + +#else + + // If Analog Configuration Update is to be disabled + NO_WARNING(config); + NO_WARNING(more); + return ERR_DISABLED; + +#endif /* RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG */ + +} /* rfalAnalogConfigListUpdate() */ + +ReturnCode + rfalAnalogConfigListReadRaw(uint8_t* tblBuf, uint16_t tblBufLen, uint16_t* configTblSize) { + /* Check if the the current table will fit into the given buffer */ + if(tblBufLen < gRfalAnalogConfigMgmt.configTblSize) { + return ERR_NOMEM; + } + + /* Check for invalid parameters */ + if(configTblSize == NULL) { + return ERR_PARAM; + } + + /* Copy the whole Table to the given buffer */ + if(gRfalAnalogConfigMgmt.configTblSize > 0U) /* MISRA 21.18 */ + { + ST_MEMCPY( + tblBuf, + gRfalAnalogConfigMgmt.currentAnalogConfigTbl, + gRfalAnalogConfigMgmt.configTblSize); + } + *configTblSize = gRfalAnalogConfigMgmt.configTblSize; + + return ERR_NONE; +} + +ReturnCode rfalAnalogConfigListRead( + rfalAnalogConfigOffset* configOffset, + uint8_t* more, + rfalAnalogConfig* config, + rfalAnalogConfigNum numConfig) { + uint16_t configSize; + rfalAnalogConfigOffset offset = *configOffset; + rfalAnalogConfigNum numConfigSet; + + /* Check if the number of register-mask-value settings for the respective Configuration ID will fit into the buffer passed in. */ + if(gRfalAnalogConfigMgmt.currentAnalogConfigTbl[offset + sizeof(rfalAnalogConfigId)] > + numConfig) { + return ERR_NOMEM; + } + + /* Get the number of Configuration set */ + numConfigSet = + gRfalAnalogConfigMgmt.currentAnalogConfigTbl[offset + sizeof(rfalAnalogConfigId)]; + + /* Pass Configuration Register-Mask-Value sets */ + configSize = + (sizeof(rfalAnalogConfigId) + sizeof(rfalAnalogConfigNum) + + (uint16_t)(numConfigSet * sizeof(rfalAnalogConfigRegAddrMaskVal))); + ST_MEMCPY((uint8_t*)config, &gRfalAnalogConfigMgmt.currentAnalogConfigTbl[offset], configSize); + *configOffset = offset + configSize; + + /* Check if it is the last Analog Configuration in the Table.*/ + *more = (uint8_t)((*configOffset >= gRfalAnalogConfigMgmt.configTblSize) ? + RFAL_ANALOG_CONFIG_UPDATE_LAST : + RFAL_ANALOG_CONFIG_UPDATE_MORE); + + return ERR_NONE; +} /* rfalAnalogConfigListRead() */ + +ReturnCode rfalSetAnalogConfig(rfalAnalogConfigId configId) { + rfalAnalogConfigOffset configOffset = 0; + rfalAnalogConfigNum numConfigSet; + const rfalAnalogConfigRegAddrMaskVal* configTbl; + ReturnCode retCode = ERR_NONE; + rfalAnalogConfigNum i; + + if(true != gRfalAnalogConfigMgmt.ready) { + return ERR_REQUEST; + } + + /* Search LUT for the specific Configuration ID. */ + while(true) { + numConfigSet = rfalAnalogConfigSearch(configId, &configOffset); + if(RFAL_ANALOG_CONFIG_LUT_NOT_FOUND == numConfigSet) { + break; + } + + configTbl = + (rfalAnalogConfigRegAddrMaskVal*)((uint32_t) + gRfalAnalogConfigMgmt.currentAnalogConfigTbl + + (uint32_t)configOffset); + /* Increment the offset to the next index to search from. */ + configOffset += (uint16_t)(numConfigSet * sizeof(rfalAnalogConfigRegAddrMaskVal)); + + if((gRfalAnalogConfigMgmt.configTblSize + 1U) < + configOffset) { /* Error check make sure that the we do not access outside the configuration Table Size */ + return ERR_NOMEM; + } + + for(i = 0; i < numConfigSet; i++) { + if((GETU16(configTbl[i].addr) & RFAL_TEST_REG) != 0U) { + EXIT_ON_ERR( + retCode, + rfalChipChangeTestRegBits( + (GETU16(configTbl[i].addr) & ~RFAL_TEST_REG), + configTbl[i].mask, + configTbl[i].val)); + } else { + EXIT_ON_ERR( + retCode, + rfalChipChangeRegBits( + GETU16(configTbl[i].addr), configTbl[i].mask, configTbl[i].val)); + } + } + + } /* while(found Analog Config Id) */ + + return retCode; + +} /* rfalSetAnalogConfig() */ + +uint16_t rfalAnalogConfigGenModeID(rfalMode md, rfalBitRate br, uint16_t dir) { + uint16_t id; + + /* Assign Poll/Listen Mode */ + id = ((md >= RFAL_MODE_LISTEN_NFCA) ? RFAL_ANALOG_CONFIG_LISTEN : RFAL_ANALOG_CONFIG_POLL); + + /* Assign Technology */ + switch(md) { + case RFAL_MODE_POLL_NFCA: + case RFAL_MODE_POLL_NFCA_T1T: + case RFAL_MODE_LISTEN_NFCA: + id |= RFAL_ANALOG_CONFIG_TECH_NFCA; + break; + + case RFAL_MODE_POLL_NFCB: + case RFAL_MODE_POLL_B_PRIME: + case RFAL_MODE_POLL_B_CTS: + case RFAL_MODE_LISTEN_NFCB: + id |= RFAL_ANALOG_CONFIG_TECH_NFCB; + break; + + case RFAL_MODE_POLL_NFCF: + case RFAL_MODE_LISTEN_NFCF: + id |= RFAL_ANALOG_CONFIG_TECH_NFCF; + break; + + case RFAL_MODE_POLL_NFCV: + case RFAL_MODE_POLL_PICOPASS: + id |= RFAL_ANALOG_CONFIG_TECH_NFCV; + break; + + case RFAL_MODE_POLL_ACTIVE_P2P: + case RFAL_MODE_LISTEN_ACTIVE_P2P: + id |= RFAL_ANALOG_CONFIG_TECH_AP2P; + break; + + default: + id = RFAL_ANALOG_CONFIG_TECH_CHIP; + break; + } + + /* Assign Bitrate */ + id |= + (((((uint16_t)(br) >= (uint16_t)RFAL_BR_52p97) ? (uint16_t)(br) : ((uint16_t)(br) + 1U)) + << RFAL_ANALOG_CONFIG_BITRATE_SHIFT) & + RFAL_ANALOG_CONFIG_BITRATE_MASK); + + /* Assign Direction */ + id |= ((dir << RFAL_ANALOG_CONFIG_DIRECTION_SHIFT) & RFAL_ANALOG_CONFIG_DIRECTION_MASK); + + return id; + +} /* rfalAnalogConfigGenModeID() */ + +/* + ****************************************************************************** + * LOCAL FUNCTIONS + ****************************************************************************** + */ + +/*! + ***************************************************************************** + * \brief Update the link to Analog Configuration LUT + * + * Update the link to the Analog Configuration LUT for the subsequent search + * of Analog Settings. + * + * \param[in] analogConfigTbl: reference to the start of the new Analog Configuration Table + * + ***************************************************************************** + */ +#if RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG +static void rfalAnalogConfigPtrUpdate(const uint8_t* analogConfigTbl) { + gRfalAnalogConfigMgmt.currentAnalogConfigTbl = analogConfigTbl; + gRfalAnalogConfigMgmt.ready = true; + +} /* rfalAnalogConfigPtrUpdate() */ +#endif /* RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG */ + +/*! + ***************************************************************************** + * \brief Search the Analog Configuration LUT for a specific Configuration ID. + * + * Search the Analog Configuration LUT for the Configuration ID. + * + * \param[in] configId: Configuration ID to search for. + * \param[in] configOffset: Configuration Offset in Table + * + * \return number of Configuration Sets + * \return #RFAL_ANALOG_CONFIG_LUT_NOT_FOUND in case Configuration ID is not found. + ***************************************************************************** + */ +static rfalAnalogConfigNum + rfalAnalogConfigSearch(rfalAnalogConfigId configId, uint16_t* configOffset) { + rfalAnalogConfigId foundConfigId; + rfalAnalogConfigId configIdMaskVal; + const uint8_t* configTbl; + const uint8_t* currentConfigTbl; + uint16_t i; + + currentConfigTbl = gRfalAnalogConfigMgmt.currentAnalogConfigTbl; + configIdMaskVal = + ((RFAL_ANALOG_CONFIG_POLL_LISTEN_MODE_MASK | RFAL_ANALOG_CONFIG_BITRATE_MASK) | + ((RFAL_ANALOG_CONFIG_TECH_CHIP == RFAL_ANALOG_CONFIG_ID_GET_TECH(configId)) ? + (RFAL_ANALOG_CONFIG_TECH_MASK | RFAL_ANALOG_CONFIG_CHIP_SPECIFIC_MASK) : + configId) | + ((RFAL_ANALOG_CONFIG_NO_DIRECTION == RFAL_ANALOG_CONFIG_ID_GET_DIRECTION(configId)) ? + RFAL_ANALOG_CONFIG_DIRECTION_MASK : + configId)); + + /* When specific ConfigIDs are to be used, override search mask */ + if((RFAL_ANALOG_CONFIG_ID_GET_DIRECTION(configId) == RFAL_ANALOG_CONFIG_DPO)) { + configIdMaskVal = + (RFAL_ANALOG_CONFIG_POLL_LISTEN_MODE_MASK | RFAL_ANALOG_CONFIG_TECH_MASK | + RFAL_ANALOG_CONFIG_BITRATE_MASK | RFAL_ANALOG_CONFIG_DIRECTION_MASK); + } + + i = *configOffset; + while(i < gRfalAnalogConfigMgmt.configTblSize) { + configTbl = ¤tConfigTbl[i]; + foundConfigId = GETU16(configTbl); + if(configId == (foundConfigId & configIdMaskVal)) { + *configOffset = + (uint16_t)(i + sizeof(rfalAnalogConfigId) + sizeof(rfalAnalogConfigNum)); + return configTbl[sizeof(rfalAnalogConfigId)]; + } + + /* If Config Id does not match, increment to next Configuration Id */ + i += (uint16_t)(sizeof(rfalAnalogConfigId) + sizeof(rfalAnalogConfigNum) + + (configTbl[sizeof(rfalAnalogConfigId)] * + sizeof(rfalAnalogConfigRegAddrMaskVal))); + } /* for */ + + return RFAL_ANALOG_CONFIG_LUT_NOT_FOUND; +} /* rfalAnalogConfigSearch() */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_crc.c b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_crc.c new file mode 100644 index 00000000000..c70f2c5fb4d --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_crc.c @@ -0,0 +1,82 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_crc.c + * + * \author Oliver Regenfelder + * + * \brief CRC calculation implementation + * + */ + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ +#include "../include/rfal_crc.h" + +/* +****************************************************************************** +* LOCAL FUNCTION PROTOTYPES +****************************************************************************** +*/ +static uint16_t rfalCrcUpdateCcitt(uint16_t crcSeed, uint8_t dataByte); + +/* +****************************************************************************** +* GLOBAL FUNCTIONS +****************************************************************************** +*/ +uint16_t rfalCrcCalculateCcitt(uint16_t preloadValue, const uint8_t* buf, uint16_t length) { + uint16_t crc = preloadValue; + uint16_t index; + + for(index = 0; index < length; index++) { + crc = rfalCrcUpdateCcitt(crc, buf[index]); + } + + return crc; +} + +/* +****************************************************************************** +* LOCAL FUNCTIONS +****************************************************************************** +*/ +static uint16_t rfalCrcUpdateCcitt(uint16_t crcSeed, uint8_t dataByte) { + uint16_t crc = crcSeed; + uint8_t dat = dataByte; + + dat ^= (uint8_t)(crc & 0xFFU); + dat ^= (dat << 4); + + crc = (crc >> 8) ^ (((uint16_t)dat) << 8) ^ (((uint16_t)dat) << 3) ^ (((uint16_t)dat) >> 4); + + return crc; +} diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_dpo.c b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_dpo.c new file mode 100644 index 00000000000..5cbae4b18fc --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_dpo.c @@ -0,0 +1,232 @@ + +/****************************************************************************** + * @attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * $Revision: $ + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_dpo.c + * + * \author Martin Zechleitner + * + * \brief Functions to manage and set dynamic power settings. + * + */ + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "st25r3916/rfal_dpoTbl.h" +#include "../include/rfal_dpo.h" +#include "../platform.h" +#include "../include/rfal_rf.h" +#include "../include/rfal_chip.h" +#include "../include/rfal_analogConfig.h" +#include "../utils.h" + +/* + ****************************************************************************** + * ENABLE SWITCH + ****************************************************************************** + */ + +#ifndef RFAL_FEATURE_DPO +#define RFAL_FEATURE_DPO \ + false /* Dynamic Power Module configuration missing. Disabled by default */ +#endif + +#if RFAL_FEATURE_DPO + +/* + ****************************************************************************** + * DEFINES + ****************************************************************************** + */ +#define RFAL_DPO_ANALOGCONFIG_SHIFT 13U +#define RFAL_DPO_ANALOGCONFIG_MASK 0x6000U + +/* + ****************************************************************************** + * LOCAL DATA TYPES + ****************************************************************************** + */ + +static bool gRfalDpoIsEnabled = false; +static uint8_t* gRfalCurrentDpo; +static uint8_t gRfalDpoTableEntries; +static uint8_t gRfalDpo[RFAL_DPO_TABLE_SIZE_MAX]; +static uint8_t gRfalDpoTableEntry; +static rfalDpoMeasureFunc gRfalDpoMeasureCallback = NULL; + +/* + ****************************************************************************** + * GLOBAL FUNCTIONS + ****************************************************************************** + */ +void rfalDpoInitialize(void) { + /* Use the default Dynamic Power values */ + gRfalCurrentDpo = (uint8_t*)rfalDpoDefaultSettings; + gRfalDpoTableEntries = (sizeof(rfalDpoDefaultSettings) / RFAL_DPO_TABLE_PARAMETER); + + ST_MEMCPY(gRfalDpo, gRfalCurrentDpo, sizeof(rfalDpoDefaultSettings)); + + /* by default use amplitude measurement */ + gRfalDpoMeasureCallback = rfalChipMeasureAmplitude; + + /* by default DPO is disabled */ + gRfalDpoIsEnabled = false; + + gRfalDpoTableEntry = 0; +} + +void rfalDpoSetMeasureCallback(rfalDpoMeasureFunc pMeasureFunc) { + gRfalDpoMeasureCallback = pMeasureFunc; +} + +/*******************************************************************************/ +ReturnCode rfalDpoTableWrite(rfalDpoEntry* powerTbl, uint8_t powerTblEntries) { + uint8_t entry = 0; + + /* check if the table size parameter is too big */ + if((powerTblEntries * RFAL_DPO_TABLE_PARAMETER) > RFAL_DPO_TABLE_SIZE_MAX) { + return ERR_NOMEM; + } + + /* check if the first increase entry is 0xFF */ + if((powerTblEntries == 0) || (powerTbl == NULL)) { + return ERR_PARAM; + } + + /* check if the entries of the dynamic power table are valid */ + for(entry = 0; entry < powerTblEntries; entry++) { + if(powerTbl[entry].inc < powerTbl[entry].dec) { + return ERR_PARAM; + } + } + + /* copy the data set */ + ST_MEMCPY(gRfalDpo, powerTbl, (powerTblEntries * RFAL_DPO_TABLE_PARAMETER)); + gRfalCurrentDpo = gRfalDpo; + gRfalDpoTableEntries = powerTblEntries; + + if(gRfalDpoTableEntry > powerTblEntries) { + /* is always greater then zero, otherwise we already returned ERR_PARAM */ + gRfalDpoTableEntry = (powerTblEntries - 1); + } + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalDpoTableRead(rfalDpoEntry* tblBuf, uint8_t tblBufEntries, uint8_t* tableEntries) { + /* wrong request */ + if((tblBuf == NULL) || (tblBufEntries < gRfalDpoTableEntries) || (tableEntries == NULL)) { + return ERR_PARAM; + } + + /* Copy the whole Table to the given buffer */ + ST_MEMCPY(tblBuf, gRfalCurrentDpo, (tblBufEntries * RFAL_DPO_TABLE_PARAMETER)); + *tableEntries = gRfalDpoTableEntries; + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalDpoAdjust(void) { + uint8_t refValue = 0; + uint16_t modeID; + rfalBitRate br; + rfalDpoEntry* dpoTable = (rfalDpoEntry*)gRfalCurrentDpo; + + /* Check if the Power Adjustment is disabled and * + * if the callback to the measurement method is properly set */ + if((gRfalCurrentDpo == NULL) || (!gRfalDpoIsEnabled) || (gRfalDpoMeasureCallback == NULL)) { + return ERR_PARAM; + } + + /* Ensure that the current mode is Passive Poller */ + if(!rfalIsModePassivePoll(rfalGetMode())) { + return ERR_WRONG_STATE; + } + + /* Ensure a proper measure reference value */ + if(ERR_NONE != gRfalDpoMeasureCallback(&refValue)) { + return ERR_IO; + } + + if(refValue >= dpoTable[gRfalDpoTableEntry].inc) { /* Increase the output power */ + /* the top of the table represents the highest amplitude value*/ + if(gRfalDpoTableEntry == 0) { + /* maximum driver value has been reached */ + } else { + /* go up in the table to decrease the driver resistance */ + gRfalDpoTableEntry--; + } + } else if(refValue <= dpoTable[gRfalDpoTableEntry].dec) { /* decrease the output power */ + /* The bottom is the highest possible value */ + if((gRfalDpoTableEntry + 1) >= gRfalDpoTableEntries) { + /* minimum driver value has been reached */ + } else { + /* go down in the table to increase the driver resistance */ + gRfalDpoTableEntry++; + } + } else { + /* Fall through to always write dpo and its associated analog configs */ + } + + /* Get the new value for RFO resistance form the table and apply the new RFO resistance setting */ + rfalChipSetRFO(dpoTable[gRfalDpoTableEntry].rfoRes); + + /* Apply the DPO Analog Config according to this treshold */ + /* Technology field is being extended for DPO: 2msb are used for treshold step (only 4 allowed) */ + rfalGetBitRate(&br, NULL); /* Obtain current Tx bitrate */ + modeID = rfalAnalogConfigGenModeID( + rfalGetMode(), br, RFAL_ANALOG_CONFIG_DPO); /* Generate Analog Config mode ID */ + modeID |= + ((gRfalDpoTableEntry << RFAL_DPO_ANALOGCONFIG_SHIFT) & + RFAL_DPO_ANALOGCONFIG_MASK); /* Add DPO treshold step|level */ + rfalSetAnalogConfig(modeID); /* Apply DPO Analog Config */ + + return ERR_NONE; +} + +/*******************************************************************************/ +rfalDpoEntry* rfalDpoGetCurrentTableEntry(void) { + rfalDpoEntry* dpoTable = (rfalDpoEntry*)gRfalCurrentDpo; + return &dpoTable[gRfalDpoTableEntry]; +} + +/*******************************************************************************/ +void rfalDpoSetEnabled(bool enable) { + gRfalDpoIsEnabled = enable; +} + +/*******************************************************************************/ +bool rfalDpoIsEnabled(void) { + return gRfalDpoIsEnabled; +} + +#endif /* RFAL_FEATURE_DPO */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_iso15693_2.c b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_iso15693_2.c new file mode 100644 index 00000000000..814a966f217 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_iso15693_2.c @@ -0,0 +1,516 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_iso15693_2.c + * + * \author Ulrich Herrmann + * + * \brief Implementation of ISO-15693-2 + * + */ + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ +#include "../include/rfal_iso15693_2.h" +#include "../include/rfal_crc.h" +#include "../utils.h" + +/* + ****************************************************************************** + * ENABLE SWITCH + ****************************************************************************** + */ + +#ifndef RFAL_FEATURE_NFCV +#define RFAL_FEATURE_NFCV false /* NFC-V module configuration missing. Disabled by default */ +#endif + +#if RFAL_FEATURE_NFCV + +/* +****************************************************************************** +* LOCAL MACROS +****************************************************************************** +*/ + +#define ISO_15693_DEBUG(...) /*!< Macro for the log method */ + +/* +****************************************************************************** +* LOCAL DEFINES +****************************************************************************** +*/ +#define ISO15693_DAT_SOF_1_4 0x21 /* LSB constants */ +#define ISO15693_DAT_EOF_1_4 0x04 +#define ISO15693_DAT_00_1_4 0x02 +#define ISO15693_DAT_01_1_4 0x08 +#define ISO15693_DAT_10_1_4 0x20 +#define ISO15693_DAT_11_1_4 0x80 + +#define ISO15693_DAT_SOF_1_256 0x81 +#define ISO15693_DAT_EOF_1_256 0x04 +#define ISO15693_DAT_SLOT0_1_256 0x02 +#define ISO15693_DAT_SLOT1_1_256 0x08 +#define ISO15693_DAT_SLOT2_1_256 0x20 +#define ISO15693_DAT_SLOT3_1_256 0x80 + +#define ISO15693_PHY_DAT_MANCHESTER_1 0xaaaa + +#define ISO15693_PHY_BIT_BUFFER_SIZE \ + 1000 /*!< size of the receiving buffer. Might be adjusted if longer datastreams are expected. */ + +/* +****************************************************************************** +* LOCAL VARIABLES +****************************************************************************** +*/ +static iso15693PhyConfig_t iso15693PhyConfig; /*!< current phy configuration */ + +/* +****************************************************************************** +* LOCAL FUNCTION PROTOTYPES +****************************************************************************** +*/ +static ReturnCode iso15693PhyVCDCode1Of4( + const uint8_t data, + uint8_t* outbuffer, + uint16_t maxOutBufLen, + uint16_t* outBufLen); +static ReturnCode iso15693PhyVCDCode1Of256( + const uint8_t data, + uint8_t* outbuffer, + uint16_t maxOutBufLen, + uint16_t* outBufLen); + +/* +****************************************************************************** +* GLOBAL FUNCTIONS +****************************************************************************** +*/ +ReturnCode iso15693PhyConfigure( + const iso15693PhyConfig_t* config, + const struct iso15693StreamConfig** needed_stream_config) { + static struct iso15693StreamConfig stream_config = { + /* MISRA 8.9 */ + .useBPSK = 0, /* 0: subcarrier, 1:BPSK */ + .din = 5, /* 2^5*fc = 423750 Hz: divider for the in subcarrier frequency */ + .dout = 7, /*!< 2^7*fc = 105937 : divider for the in subcarrier frequency */ + .report_period_length = 3, /*!< 8=2^3 the length of the reporting period */ + }; + + /* make a copy of the configuration */ + ST_MEMCPY((uint8_t*)&iso15693PhyConfig, (const uint8_t*)config, sizeof(iso15693PhyConfig_t)); + + if(config->speedMode <= 3U) { /* If valid speed mode adjust report period accordingly */ + stream_config.report_period_length = (3U - (uint8_t)config->speedMode); + } else { /* If invalid default to normal (high) speed */ + stream_config.report_period_length = 3; + } + + *needed_stream_config = &stream_config; + + return ERR_NONE; +} + +ReturnCode iso15693PhyGetConfiguration(iso15693PhyConfig_t* config) { + ST_MEMCPY(config, &iso15693PhyConfig, sizeof(iso15693PhyConfig_t)); + + return ERR_NONE; +} + +ReturnCode iso15693VCDCode( + uint8_t* buffer, + uint16_t length, + bool sendCrc, + bool sendFlags, + bool picopassMode, + uint16_t* subbit_total_length, + uint16_t* offset, + uint8_t* outbuf, + uint16_t outBufSize, + uint16_t* actOutBufSize) { + ReturnCode err = ERR_NONE; + uint8_t eof, sof; + uint8_t transbuf[2]; + uint16_t crc = 0; + ReturnCode (*txFunc)( + const uint8_t data, uint8_t* outbuffer, uint16_t maxOutBufLen, uint16_t* outBufLen); + uint8_t crc_len; + uint8_t* outputBuf; + uint16_t outputBufSize; + + crc_len = (uint8_t)((sendCrc) ? 2 : 0); + + *actOutBufSize = 0; + + if(ISO15693_VCD_CODING_1_4 == iso15693PhyConfig.coding) { + sof = ISO15693_DAT_SOF_1_4; + eof = ISO15693_DAT_EOF_1_4; + txFunc = iso15693PhyVCDCode1Of4; + *subbit_total_length = + ((1U /* SOF */ + + ((length + (uint16_t)crc_len) * 4U) + 1U) /* EOF */ + ); + if(outBufSize < 5U) { /* 5 should be safe: enough for sof + 1byte data in 1of4 */ + return ERR_NOMEM; + } + } else { + sof = ISO15693_DAT_SOF_1_256; + eof = ISO15693_DAT_EOF_1_256; + txFunc = iso15693PhyVCDCode1Of256; + *subbit_total_length = + ((1U /* SOF */ + + ((length + (uint16_t)crc_len) * 64U) + 1U) /* EOF */ + ); + + if(*offset != 0U) { + if(outBufSize < 64U) { /* 64 should be safe: enough a single byte data in 1of256 */ + return ERR_NOMEM; + } + } else { + if(outBufSize < + 65U) { /* At beginning of a frame we need at least 65 bytes to start: enough for sof + 1byte data in 1of256 */ + return ERR_NOMEM; + } + } + } + + if(length == 0U) { + *subbit_total_length = 1; + } + + if((length != 0U) && (0U == *offset) && sendFlags && !picopassMode) { + /* set high datarate flag */ + buffer[0] |= (uint8_t)ISO15693_REQ_FLAG_HIGH_DATARATE; + /* clear sub-carrier flag - we only support single sub-carrier */ + buffer[0] = (uint8_t)(buffer[0] & ~ISO15693_REQ_FLAG_TWO_SUBCARRIERS); /* MISRA 10.3 */ + } + + outputBuf = outbuf; /* MISRA 17.8: Use intermediate variable */ + outputBufSize = outBufSize; /* MISRA 17.8: Use intermediate variable */ + + /* Send SOF if at 0 offset */ + if((length != 0U) && (0U == *offset)) { + *outputBuf = sof; + (*actOutBufSize)++; + outputBufSize--; + outputBuf++; + } + + while((*offset < length) && (err == ERR_NONE)) { + uint16_t filled_size; + /* send data */ + err = txFunc(buffer[*offset], outputBuf, outputBufSize, &filled_size); + (*actOutBufSize) += filled_size; + outputBuf = &outputBuf[filled_size]; /* MISRA 18.4: Avoid pointer arithmetic */ + outputBufSize -= filled_size; + if(err == ERR_NONE) { + (*offset)++; + } + } + if(err != ERR_NONE) { + return ERR_AGAIN; + } + + while((err == ERR_NONE) && sendCrc && (*offset < (length + 2U))) { + uint16_t filled_size; + if(0U == crc) { + crc = rfalCrcCalculateCcitt( + (uint16_t)((picopassMode) ? + 0xE012U : + 0xFFFFU), /* In PicoPass Mode a different Preset Value is used */ + ((picopassMode) ? + (buffer + 1U) : + buffer), /* CMD byte is not taken into account in PicoPass mode */ + ((picopassMode) ? + (length - 1U) : + length)); /* CMD byte is not taken into account in PicoPass mode */ + + crc = (uint16_t)((picopassMode) ? crc : ~crc); + } + /* send crc */ + transbuf[0] = (uint8_t)(crc & 0xffU); + transbuf[1] = (uint8_t)((crc >> 8) & 0xffU); + err = txFunc(transbuf[*offset - length], outputBuf, outputBufSize, &filled_size); + (*actOutBufSize) += filled_size; + outputBuf = &outputBuf[filled_size]; /* MISRA 18.4: Avoid pointer arithmetic */ + outputBufSize -= filled_size; + if(err == ERR_NONE) { + (*offset)++; + } + } + if(err != ERR_NONE) { + return ERR_AGAIN; + } + + if((!sendCrc && (*offset == length)) || (sendCrc && (*offset == (length + 2U)))) { + *outputBuf = eof; + (*actOutBufSize)++; + outputBufSize--; + outputBuf++; + } else { + return ERR_AGAIN; + } + + return err; +} + +ReturnCode iso15693VICCDecode( + const uint8_t* inBuf, + uint16_t inBufLen, + uint8_t* outBuf, + uint16_t outBufLen, + uint16_t* outBufPos, + uint16_t* bitsBeforeCol, + uint16_t ignoreBits, + bool picopassMode) { + ReturnCode err = ERR_NONE; + uint16_t crc; + uint16_t mp; /* Current bit position in manchester bit inBuf*/ + uint16_t bp; /* Current bit position in outBuf */ + + *bitsBeforeCol = 0; + *outBufPos = 0; + + /* first check for valid SOF. Since it starts with 3 unmodulated pulses it is 0x17. */ + if((inBuf[0] & 0x1fU) != 0x17U) { + ISO_15693_DEBUG("0x%x\n", iso15693PhyBitBuffer[0]); + return ERR_FRAMING; + } + ISO_15693_DEBUG("SOF\n"); + + if(outBufLen == 0U) { + return ERR_NONE; + } + + mp = 5; /* 5 bits were SOF, now manchester starts: 2 bits per payload bit */ + bp = 0; + + ST_MEMSET(outBuf, 0, outBufLen); + + if(inBufLen == 0U) { + return ERR_CRC; + } + + for(; mp < ((inBufLen * 8U) - 2U); mp += 2U) { + bool isEOF = false; + + uint8_t man; + man = (inBuf[mp / 8U] >> (mp % 8U)) & 0x1U; + man |= ((inBuf[(mp + 1U) / 8U] >> ((mp + 1U) % 8U)) & 0x1U) << 1; + if(1U == man) { + bp++; + } + if(2U == man) { + outBuf[bp / 8U] = (uint8_t)(outBuf[bp / 8U] | (1U << (bp % 8U))); /* MISRA 10.3 */ + bp++; + } + if((bp % 8U) == 0U) { /* Check for EOF */ + ISO_15693_DEBUG("ceof %hhx %hhx\n", inBuf[mp / 8U], inBuf[mp / 8 + 1]); + if(((inBuf[mp / 8U] & 0xe0U) == 0xa0U) && + (inBuf[(mp / 8U) + 1U] == 0x03U)) { /* Now we know that it was 10111000 = EOF */ + ISO_15693_DEBUG("EOF\n"); + isEOF = true; + } + } + if(((0U == man) || (3U == man)) && !isEOF) { + if(bp >= ignoreBits) { + err = ERR_RF_COLLISION; + } else { + /* ignored collision: leave as 0 */ + bp++; + } + } + if((bp >= (outBufLen * 8U)) || (err == ERR_RF_COLLISION) || + isEOF) { /* Don't write beyond the end */ + break; + } + } + + *outBufPos = (bp / 8U); + *bitsBeforeCol = bp; + + if(err != ERR_NONE) { + return err; + } + + if((bp % 8U) != 0U) { + return ERR_CRC; + } + + if(*outBufPos > 2U) { + /* finally, check crc */ + ISO_15693_DEBUG("Calculate CRC, val: 0x%x, outBufLen: ", *outBuf); + ISO_15693_DEBUG("0x%x ", *outBufPos - 2); + + crc = rfalCrcCalculateCcitt(((picopassMode) ? 0xE012U : 0xFFFFU), outBuf, *outBufPos - 2U); + crc = (uint16_t)((picopassMode) ? crc : ~crc); + + if(((crc & 0xffU) == outBuf[*outBufPos - 2U]) && + (((crc >> 8U) & 0xffU) == outBuf[*outBufPos - 1U])) { + err = ERR_NONE; + ISO_15693_DEBUG("OK\n"); + } else { + ISO_15693_DEBUG("error! Expected: 0x%x, got ", crc); + ISO_15693_DEBUG("0x%hhx 0x%hhx\n", outBuf[*outBufPos - 2], outBuf[*outBufPos - 1]); + err = ERR_CRC; + } + } else { + err = ERR_CRC; + } + + return err; +} + +/* +****************************************************************************** +* LOCAL FUNCTIONS +****************************************************************************** +*/ +/*! + ***************************************************************************** + * \brief Perform 1 of 4 coding and send coded data + * + * This function takes \a length bytes from \a buffer, perform 1 of 4 coding + * (see ISO15693-2 specification) and sends the data using stream mode. + * + * \param[in] sendSof : send SOF prior to data. + * \param[in] buffer : data to send. + * \param[in] length : number of bytes to send. + * + * \return ERR_IO : Error during communication. + * \return ERR_NONE : No error. + * + ***************************************************************************** + */ +static ReturnCode iso15693PhyVCDCode1Of4( + const uint8_t data, + uint8_t* outbuffer, + uint16_t maxOutBufLen, + uint16_t* outBufLen) { + uint8_t tmp; + ReturnCode err = ERR_NONE; + uint16_t a; + uint8_t* outbuf = outbuffer; + + *outBufLen = 0; + + if(maxOutBufLen < 4U) { + return ERR_NOMEM; + } + + tmp = data; + for(a = 0; a < 4U; a++) { + switch(tmp & 0x3U) { + case 0: + *outbuf = ISO15693_DAT_00_1_4; + break; + case 1: + *outbuf = ISO15693_DAT_01_1_4; + break; + case 2: + *outbuf = ISO15693_DAT_10_1_4; + break; + case 3: + *outbuf = ISO15693_DAT_11_1_4; + break; + default: + /* MISRA 16.4: mandatory default statement */ + break; + } + outbuf++; + (*outBufLen)++; + tmp >>= 2; + } + return err; +} + +/*! + ***************************************************************************** + * \brief Perform 1 of 256 coding and send coded data + * + * This function takes \a length bytes from \a buffer, perform 1 of 256 coding + * (see ISO15693-2 specification) and sends the data using stream mode. + * \note This function sends SOF prior to the data. + * + * \param[in] sendSof : send SOF prior to data. + * \param[in] buffer : data to send. + * \param[in] length : number of bytes to send. + * + * \return ERR_IO : Error during communication. + * \return ERR_NONE : No error. + * + ***************************************************************************** + */ +static ReturnCode iso15693PhyVCDCode1Of256( + const uint8_t data, + uint8_t* outbuffer, + uint16_t maxOutBufLen, + uint16_t* outBufLen) { + uint8_t tmp; + ReturnCode err = ERR_NONE; + uint16_t a; + uint8_t* outbuf = outbuffer; + + *outBufLen = 0; + + if(maxOutBufLen < 64U) { + return ERR_NOMEM; + } + + tmp = data; + for(a = 0; a < 64U; a++) { + switch(tmp) { + case 0: + *outbuf = ISO15693_DAT_SLOT0_1_256; + break; + case 1: + *outbuf = ISO15693_DAT_SLOT1_1_256; + break; + case 2: + *outbuf = ISO15693_DAT_SLOT2_1_256; + break; + case 3: + *outbuf = ISO15693_DAT_SLOT3_1_256; + break; + default: + *outbuf = 0; + break; + } + outbuf++; + (*outBufLen)++; + tmp -= 4U; + } + + return err; +} + +#endif /* RFAL_FEATURE_NFCV */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_isoDep.c b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_isoDep.c new file mode 100644 index 00000000000..9b8cd63feea --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_isoDep.c @@ -0,0 +1,3045 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: NFCC firmware + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_isoDep.c + * + * \author Gustavo Patricio + * + * \brief Implementation of ISO-DEP protocol + * + * This implementation was based on the following specs: + * - ISO/IEC 14443-4 2nd Edition 2008-07-15 + * - NFC Forum Digital Protocol 1.1 2014-01-14 + * + */ + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ + +#include "../include/rfal_isoDep.h" +#include "../include/rfal_rf.h" +#include "../utils.h" + +/* + ****************************************************************************** + * ENABLE SWITCH + ****************************************************************************** + */ + +#if RFAL_FEATURE_ISO_DEP + +#if(!RFAL_FEATURE_ISO_DEP_POLL && !RFAL_FEATURE_ISO_DEP_LISTEN) +#error \ + " RFAL: Invalid ISO-DEP Configuration. Please select at least one mode: Poller and/or Listener. " +#endif + +/* Check for valid I-Block length [RFAL_ISODEP_FSX_16 ; RFAL_ISODEP_FSX_4096]*/ +#if((RFAL_FEATURE_ISO_DEP_IBLOCK_MAX_LEN > 4096) || (RFAL_FEATURE_ISO_DEP_IBLOCK_MAX_LEN < 16)) +#error \ + " RFAL: Invalid ISO-DEP IBlock Max length. Please change RFAL_FEATURE_ISO_DEP_IBLOCK_MAX_LEN. " +#endif + +/* Check for valid APDU length. */ +#if((RFAL_FEATURE_ISO_DEP_APDU_MAX_LEN < RFAL_FEATURE_ISO_DEP_IBLOCK_MAX_LEN)) +#error " RFAL: Invalid ISO-DEP APDU Max length. Please change RFAL_FEATURE_ISO_DEP_APDU_MAX_LEN. " +#endif + +/* + ****************************************************************************** + * DEFINES + ****************************************************************************** + */ +#define ISODEP_CRC_LEN RFAL_CRC_LEN /*!< ISO1443 CRC Length */ + +#define ISODEP_PCB_POS (0U) /*!< PCB position on message header*/ +#define ISODEP_SWTX_INF_POS (1U) /*!< INF position in a S-WTX */ + +#define ISODEP_DID_POS (1U) /*!< DID position on message header*/ +#define ISODEP_SWTX_PARAM_LEN (1U) /*!< SWTX parameter length */ + +#define ISODEP_DSL_MAX_LEN \ + (RFAL_ISODEP_PCB_LEN + RFAL_ISODEP_DID_LEN) /*!< Deselect Req/Res length */ + +#define ISODEP_PCB_xBLOCK_MASK (0xC0U) /*!< Bit mask for Block type */ +#define ISODEP_PCB_IBLOCK (0x00U) /*!< Bit mask indicating a I-Block */ +#define ISODEP_PCB_RBLOCK (0x80U) /*!< Bit mask indicating a R-Block */ +#define ISODEP_PCB_SBLOCK (0xC0U) /*!< Bit mask indicating a S-Block */ +#define ISODEP_PCB_INVALID (0x40U) /*!< Bit mask of an Invalid PCB */ + +#define ISODEP_HDR_MAX_LEN \ + (RFAL_ISODEP_PCB_LEN + RFAL_ISODEP_DID_LEN + \ + RFAL_ISODEP_NAD_LEN) /*!< Max header length (PCB + DID + NAD) */ + +#define ISODEP_PCB_IB_VALID_MASK \ + (ISODEP_PCB_B6_BIT | ISODEP_PCB_B2_BIT) /*!< Bit mask for the MUST bits on I-Block */ +#define ISODEP_PCB_IB_VALID_VAL \ + (ISODEP_PCB_B2_BIT) /*!< Value for the MUST bits on I-Block */ +#define ISODEP_PCB_RB_VALID_MASK \ + (ISODEP_PCB_B6_BIT | ISODEP_PCB_B3_BIT | \ + ISODEP_PCB_B2_BIT) /*!< Bit mask for the MUST bits on R-Block */ +#define ISODEP_PCB_RB_VALID_VAL \ + (ISODEP_PCB_B6_BIT | ISODEP_PCB_B2_BIT) /*!< Value for the MUST bits on R-Block */ +#define ISODEP_PCB_SB_VALID_MASK \ + (ISODEP_PCB_B3_BIT | ISODEP_PCB_B2_BIT | \ + ISODEP_PCB_B1_BIT) /*!< Bit mask for the MUST bits on I-Block */ +#define ISODEP_PCB_SB_VALID_VAL \ + (ISODEP_PCB_B2_BIT) /*!< Value for the MUST bits on I-Block */ + +#define ISODEP_PCB_B1_BIT \ + (0x01U) /*!< Bit mask for the RFU S Blocks */ +#define ISODEP_PCB_B2_BIT \ + (0x02U) /*!< Bit mask for the RFU bit2 in I,S,R Blocks */ +#define ISODEP_PCB_B3_BIT \ + (0x04U) /*!< Bit mask for the RFU bit3 in R Blocks */ +#define ISODEP_PCB_B6_BIT \ + (0x20U) /*!< Bit mask for the RFU bit2 in R Blocks */ +#define ISODEP_PCB_CHAINING_BIT \ + (0x10U) /*!< Bit mask for the chaining bit of an ISO DEP I-Block in PCB. */ +#define ISODEP_PCB_DID_BIT \ + (0x08U) /*!< Bit mask for the DID presence bit of an ISO DEP I,S,R Blocks PCB. */ +#define ISODEP_PCB_NAD_BIT \ + (0x04U) /*!< Bit mask for the NAD presence bit of an ISO DEP I,S,R Blocks in PCB */ +#define ISODEP_PCB_BN_MASK \ + (0x01U) /*!< Bit mask for the block number of an ISO DEP I,R Block in PCB */ + +#define ISODEP_SWTX_PL_MASK \ + (0xC0U) /*!< Bit mask for the Power Level bits of the inf byte of an WTX request or response */ +#define ISODEP_SWTX_WTXM_MASK \ + (0x3FU) /*!< Bit mask for the WTXM bits of the inf byte of an WTX request or response */ + +#define ISODEP_RBLOCK_INF_LEN (0U) /*!< INF length of R-Block Digital 1.1 15.1.3 */ +#define ISODEP_SDSL_INF_LEN (0U) /*!< INF length of S(DSL) Digital 1.1 15.1.3 */ +#define ISODEP_SWTX_INF_LEN (1U) /*!< INF length of S(WTX) Digital 1.1 15.2.2 */ + +#define ISODEP_WTXM_MIN (1U) /*!< Minimum allowed value for the WTXM, Digital 1.0 13.2.2 */ +#define ISODEP_WTXM_MAX (59U) /*!< Maximum allowed value for the WTXM, Digital 1.0 13.2.2 */ + +#define ISODEP_PCB_Sxx_MASK (0x30U) /*!< Bit mask for the S-Block type */ +#define ISODEP_PCB_DESELECT (0x00U) /*!< Bit mask for S-Block indicating Deselect */ +#define ISODEP_PCB_WTX (0x30U) /*!< Bit mask for S-Block indicating Waiting Time eXtension */ + +#define ISODEP_PCB_Rx_MASK (0x10U) /*!< Bit mask for the R-Block type */ +#define ISODEP_PCB_ACK (0x00U) /*!< Bit mask for R-Block indicating ACK */ +#define ISODEP_PCB_NAK (0x10U) /*!< Bit mask for R-Block indicating NAK */ + +/*! Maximum length of control message (no INF) */ +#define ISODEP_CONTROLMSG_BUF_LEN \ + (RFAL_ISODEP_PCB_LEN + RFAL_ISODEP_DID_LEN + RFAL_ISODEP_NAD_LEN + ISODEP_SWTX_PARAM_LEN) + +#define ISODEP_FWT_DEACTIVATION \ + (71680U) /*!< FWT used for DESELECT Digital 2.2 B10 ISO1444-4 7.2 & 8.1 */ +#define ISODEP_MAX_RERUNS (0x0FFFFFFFU) /*!< Maximum rerun retrys for a blocking protocol run*/ + +#define ISODEP_PCBSBLOCK \ + (0x00U | ISODEP_PCB_SBLOCK | ISODEP_PCB_B2_BIT) /*!< PCB Value of a S-Block */ +#define ISODEP_PCB_SDSL \ + (ISODEP_PCBSBLOCK | ISODEP_PCB_DESELECT) /*!< PCB Value of a S-Block with DESELECT */ +#define ISODEP_PCB_SWTX \ + (ISODEP_PCBSBLOCK | ISODEP_PCB_WTX) /*!< PCB Value of a S-Block with WTX */ +#define ISODEP_PCB_SPARAMETERS \ + (ISODEP_PCB_SBLOCK | ISODEP_PCB_WTX) /*!< PCB Value of a S-Block with PARAMETERS */ + +#define ISODEP_FWI_LIS_MAX_NFC \ + 8U /*!< FWT Listener Max FWIT4ATmax FWIBmax Digital 1.1 A6 & A3 */ +#define ISODEP_FWI_LIS_MAX_EMVCO \ + 7U /*!< FWT Listener Max FWIMAX EMVCo 2.6 A.5 */ +#define ISODEP_FWI_LIS_MAX \ + (uint8_t)( \ + (gIsoDep.compMode == RFAL_COMPLIANCE_MODE_EMV) ? \ + ISODEP_FWI_LIS_MAX_EMVCO : \ + ISODEP_FWI_LIS_MAX_NFC) /*!< FWI Listener Max as NFC / EMVCo */ +#define ISODEP_FWT_LIS_MAX \ + rfalIsoDepFWI2FWT(ISODEP_FWI_LIS_MAX) /*!< FWT Listener Max */ + +#define ISODEP_FWI_MIN_10 (1U) /*!< Minimum value for FWI Digital 1.0 11.6.2.17 */ +#define ISODEP_FWI_MIN_11 (0U) /*!< Default value for FWI Digital 1.1 13.6.2 */ +#define ISODEP_FWI_MAX (14U) /*!< Maximum value for FWI Digital 1.0 11.6.2.17 */ +#define ISODEP_SFGI_MIN (0U) /*!< Default value for FWI Digital 1.1 13.6.2.22 */ +#define ISODEP_SFGI_MAX (14U) /*!< Maximum value for FWI Digital 1.1 13.6.2.22 */ + +#define RFAL_ISODEP_SPARAM_TVL_HDR_LEN (2U) /*!< S(PARAMETERS) TVL header length: Tag + Len */ +#define RFAL_ISODEP_SPARAM_HDR_LEN \ + (RFAL_ISODEP_PCB_LEN + \ + RFAL_ISODEP_SPARAM_TVL_HDR_LEN) /*!< S(PARAMETERS) header length: PCB + Tag + Len */ + +/**********************************************************************************************************************/ +/**********************************************************************************************************************/ +#define RFAL_ISODEP_NO_PARAM (0U) /*!< No parameter flag for isoDepHandleControlMsg() */ + +#define RFAL_ISODEP_CMD_RATS (0xE0U) /*!< RATS command Digital 1.1 13.6.1 */ + +#define RFAL_ISODEP_ATS_MIN_LEN (1U) /*!< Minimum ATS length Digital 1.1 13.6.2 */ +#define RFAL_ISODEP_ATS_HDR_LEN (5U) /*!< ATS headerlength Digital 1.1 13.6.2 */ +#define RFAL_ISODEP_ATS_MAX_LEN \ + (RFAL_ISODEP_ATS_HDR_LEN + \ + RFAL_ISODEP_ATS_HB_MAX_LEN) /*!< Maximum ATS length Digital 1.1 13.6.2 */ +#define RFAL_ISODEP_ATS_T0_FSCI_MASK (0x0FU) /*!< ATS T0's FSCI mask Digital 1.1 13.6.2 */ +#define RFAL_ISODEP_ATS_TB_FWI_SHIFT (4U) /*!< ATS TB's FWI shift Digital 1.1 13.6.2 */ +#define RFAL_ISODEP_ATS_FWI_MASK (0x0FU) /*!< ATS TB's FWI shift Digital 1.1 13.6.2 */ +#define RFAL_ISODEP_ATS_TL_POS (0x00U) /*!< ATS TL's position Digital 1.1 13.6.2 */ + +#define RFAL_ISODEP_PPS_SB (0xD0U) /*!< PPS REQ PPSS's SB value (no CID) ISO14443-4 5.3 */ +#define RFAL_ISODEP_PPS_MASK (0xF0U) /*!< PPS REQ PPSS's SB mask ISO14443-4 5.3 */ +#define RFAL_ISODEP_PPS_SB_DID_MASK \ + (0x0FU) /*!< PPS REQ PPSS's DID|CID mask ISO14443-4 5.3 */ +#define RFAL_ISODEP_PPS_PPS0_PPS1_PRESENT \ + (0x11U) /*!< PPS REQ PPS0 indicating that PPS1 is present */ +#define RFAL_ISODEP_PPS_PPS1 (0x00U) /*!< PPS REQ PPS1 fixed value ISO14443-4 5.3 */ +#define RFAL_ISODEP_PPS_PPS1_DSI_SHIFT \ + (2U) /*!< PPS REQ PPS1 fixed value ISO14443-4 5.3 */ +#define RFAL_ISODEP_PPS_PPS1_DXI_MASK \ + (0x0FU) /*!< PPS REQ PPS1 fixed value ISO14443-4 5.3 */ +#define RFAL_ISODEP_PPS_RES_LEN (1U) /*!< PPS Response length ISO14443-4 5.4 */ +#define RFAL_ISODEP_PPS_STARTBYTE_POS \ + (0U) /*!< PPS REQ PPSS's byte position ISO14443-4 5.4 */ +#define RFAL_ISODEP_PPS_PPS0_POS (1U) /*!< PPS REQ PPS0's byte position ISO14443-4 5.4 */ +#define RFAL_ISODEP_PPS_PPS1_POS (2U) /*!< PPS REQ PPS1's byte position ISO14443-4 5.4 */ +#define RFAL_ISODEP_PPS0_VALID_MASK \ + (0xEFU) /*!< PPS REQ PPS0 valid coding mask ISO14443-4 5.4 */ + +#define RFAL_ISODEP_CMD_ATTRIB (0x1DU) /*!< ATTRIB command Digital 1.1 14.6.1 */ +#define RFAL_ISODEP_ATTRIB_PARAM2_DSI_SHIFT \ + (6U) /*!< ATTRIB PARAM2 DSI shift Digital 1.1 14.6.1 */ +#define RFAL_ISODEP_ATTRIB_PARAM2_DRI_SHIFT \ + (4U) /*!< ATTRIB PARAM2 DRI shift Digital 1.1 14.6.1 */ +#define RFAL_ISODEP_ATTRIB_PARAM2_DXI_MASK \ + (0xF0U) /*!< ATTRIB PARAM2 DxI mask Digital 1.1 14.6.1 */ +#define RFAL_ISODEP_ATTRIB_PARAM2_FSDI_MASK \ + (0x0FU) /*!< ATTRIB PARAM2 FSDI mask Digital 1.1 14.6.1 */ +#define RFAL_ISODEP_ATTRIB_PARAM4_DID_MASK \ + (0x0FU) /*!< ATTRIB PARAM4 DID mask Digital 1.1 14.6.1 */ +#define RFAL_ISODEP_ATTRIB_HDR_LEN (9U) /*!< ATTRIB REQ header length Digital 1.1 14.6.1 */ + +#define RFAL_ISODEP_ATTRIB_RES_HDR_LEN \ + (1U) /*!< ATTRIB RES header length Digital 1.1 14.6.2 */ +#define RFAL_ISODEP_ATTRIB_RES_MBLIDID_POS \ + (0U) /*!< ATTRIB RES MBLI|DID position Digital 1.1 14.6.2 */ +#define RFAL_ISODEP_ATTRIB_RES_DID_MASK \ + (0x0FU) /*!< ATTRIB RES DID mask Digital 1.1 14.6.2 */ +#define RFAL_ISODEP_ATTRIB_RES_MBLI_MASK \ + (0x0FU) /*!< ATTRIB RES MBLI mask Digital 1.1 14.6.2 */ +#define RFAL_ISODEP_ATTRIB_RES_MBLI_SHIFT \ + (4U) /*!< ATTRIB RES MBLI shift Digital 1.1 14.6.2 */ + +#define RFAL_ISODEP_DID_MASK (0x0FU) /*!< ISODEP's DID mask */ +#define RFAL_ISODEP_DID_00 (0U) /*!< ISODEP's DID value 0 */ + +#define RFAL_ISODEP_FSDI_MAX_NFC (8U) /*!< Max FSDI value Digital 2.0 14.6.1.9 & B7 & B8 */ +#define RFAL_ISODEP_FSDI_MAX_NFC_21 \ + (0x0CU) /*!< Max FSDI value Digital 2.1 14.6.1.9 & Table 72 */ +#define RFAL_ISODEP_FSDI_MAX_EMV (0x0CU) /*!< Max FSDI value EMVCo 3.0 5.7.2.5 */ + +#define RFAL_ISODEP_RATS_PARAM_FSDI_MASK \ + (0xF0U) /*!< Mask bits for FSDI in RATS */ +#define RFAL_ISODEP_RATS_PARAM_FSDI_SHIFT \ + (4U) /*!< Shift for FSDI in RATS */ +#define RFAL_ISODEP_RATS_PARAM_DID_MASK \ + (0x0FU) /*!< Mask bits for DID in RATS */ + +#define RFAL_ISODEP_ATS_TL_OFFSET \ + (0x00U) /*!< Offset of TL on ATS */ +#define RFAL_ISODEP_ATS_TA_OFFSET \ + (0x02U) /*!< Offset of TA if it is present on ATS */ +#define RFAL_ISODEP_ATS_TB_OFFSET \ + (0x03U) /*!< Offset of TB if both TA and TB is present on ATS */ +#define RFAL_ISODEP_ATS_TC_OFFSET \ + (0x04U) /*!< Offset of TC if both TA,TB & TC are present on ATS */ +#define RFAL_ISODEP_ATS_HIST_OFFSET \ + (0x05U) /*!< Offset of Historical Bytes if TA, TB & TC are present on ATS */ +#define RFAL_ISODEP_ATS_TC_ADV_FEAT \ + (0x10U) /*!< Bit mask indicating support for Advanced protocol features: DID & NAD */ +#define RFAL_ISODEP_ATS_TC_DID (0x02U) /*!< Bit mask indicating support for DID */ +#define RFAL_ISODEP_ATS_TC_NAD (0x01U) /*!< Bit mask indicating support for NAD */ + +#define RFAL_ISODEP_PPS0_PPS1_PRESENT \ + (0x11U) /*!< PPS0 byte indicating that PPS1 is present */ +#define RFAL_ISODEP_PPS0_PPS1_NOT_PRESENT \ + (0x01U) /*!< PPS0 byte indicating that PPS1 is NOT present */ +#define RFAL_ISODEP_PPS1_DRI_MASK \ + (0x03U) /*!< PPS1 byte DRI mask bits */ +#define RFAL_ISODEP_PPS1_DSI_MASK \ + (0x0CU) /*!< PPS1 byte DSI mask bits */ +#define RFAL_ISODEP_PPS1_DSI_SHIFT \ + (2U) /*!< PPS1 byte DSI shift */ +#define RFAL_ISODEP_PPS1_DxI_MASK \ + (0x03U) /*!< PPS1 byte DSI/DRS mask bits */ + +/*! Delta Time for polling during Activation (ATS) : 20ms Digital 1.0 11.7.1.1 & A.7 */ +#define RFAL_ISODEP_T4T_DTIME_POLL_10 rfalConvMsTo1fc(20) + +/*! Delta Time for polling during Activation (ATS) : 16.4ms Digital 1.1 13.8.1.1 & A.6 + * Use 16 ms as testcase T4AT_BI_10_03 sends a frame exactly at the border */ +#define RFAL_ISODEP_T4T_DTIME_POLL_11 216960U + +/*! Activation frame waiting time FWT(act) = 71680/fc (~5286us) Digital 1.1 13.8.1.1 & A.6 */ +#define RFAL_ISODEP_T4T_FWT_ACTIVATION (71680U + RFAL_ISODEP_T4T_DTIME_POLL_11) + +/*! Delta frame waiting time = 16/fc Digital 1.0 11.7.1.3 & A.7*/ +#define RFAL_ISODEP_DFWT_10 16U + +/*! Delta frame waiting time = 16/fc Digital 2.0 14.8.1.3 & B.7*/ +#define RFAL_ISODEP_DFWT_20 49152U + +/* + ****************************************************************************** + * MACROS + ****************************************************************************** + */ + +#define isoDep_PCBisIBlock(pcb) \ + (((pcb) & (ISODEP_PCB_xBLOCK_MASK | ISODEP_PCB_IB_VALID_MASK)) == \ + (ISODEP_PCB_IBLOCK | ISODEP_PCB_IB_VALID_VAL)) /*!< Checks if pcb is a I-Block */ +#define isoDep_PCBisRBlock(pcb) \ + (((pcb) & (ISODEP_PCB_xBLOCK_MASK | ISODEP_PCB_RB_VALID_MASK)) == \ + (ISODEP_PCB_RBLOCK | ISODEP_PCB_RB_VALID_VAL)) /*!< Checks if pcb is a R-Block */ +#define isoDep_PCBisSBlock(pcb) \ + (((pcb) & (ISODEP_PCB_xBLOCK_MASK | ISODEP_PCB_SB_VALID_MASK)) == \ + (ISODEP_PCB_SBLOCK | ISODEP_PCB_SB_VALID_VAL)) /*!< Checks if pcb is a S-Block */ + +#define isoDep_PCBisChaining(pcb) \ + (((pcb) & ISODEP_PCB_CHAINING_BIT) == \ + ISODEP_PCB_CHAINING_BIT) /*!< Checks if pcb is indicating chaining */ + +#define isoDep_PCBisDeselect(pcb) \ + (((pcb) & ISODEP_PCB_Sxx_MASK) == \ + ISODEP_PCB_DESELECT) /*!< Checks if pcb is indicating DESELECT */ +#define isoDep_PCBisWTX(pcb) \ + (((pcb) & ISODEP_PCB_Sxx_MASK) == ISODEP_PCB_WTX) /*!< Checks if pcb is indicating WTX */ + +#define isoDep_PCBisACK(pcb) \ + (((pcb) & ISODEP_PCB_Rx_MASK) == ISODEP_PCB_ACK) /*!< Checks if pcb is indicating ACK */ +#define isoDep_PCBisNAK(pcb) \ + (((pcb) & ISODEP_PCB_Rx_MASK) == ISODEP_PCB_NAK) /*!< Checks if pcb is indicating ACK */ + +#define isoDep_PCBhasDID(pcb) \ + (((pcb) & ISODEP_PCB_DID_BIT) == \ + ISODEP_PCB_DID_BIT) /*!< Checks if pcb is indicating DID */ +#define isoDep_PCBhasNAD(pcb) \ + (((pcb) & ISODEP_PCB_NAD_BIT) == \ + ISODEP_PCB_NAD_BIT) /*!< Checks if pcb is indicating NAD */ + +#define isoDep_PCBisIChaining(pcb) \ + (isoDep_PCBisIBlock(pcb) && \ + isoDep_PCBisChaining(pcb)) /*!< Checks if pcb is I-Block indicating chaining*/ + +#define isoDep_PCBisSDeselect(pcb) \ + (isoDep_PCBisSBlock(pcb) && \ + isoDep_PCBisDeselect(pcb)) /*!< Checks if pcb is S-Block indicating DESELECT*/ +#define isoDep_PCBisSWTX(pcb) \ + (isoDep_PCBisSBlock(pcb) && \ + isoDep_PCBisWTX(pcb)) /*!< Checks if pcb is S-Block indicating WTX */ + +#define isoDep_PCBisRACK(pcb) \ + (isoDep_PCBisRBlock(pcb) && \ + isoDep_PCBisACK(pcb)) /*!< Checks if pcb is R-Block indicating ACK */ +#define isoDep_PCBisRNAK(pcb) \ + (isoDep_PCBisRBlock(pcb) && \ + isoDep_PCBisNAK(pcb)) /*!< Checks if pcb is R-Block indicating NAK */ + +#define isoDep_PCBIBlock(bn) \ + ((uint8_t)(0x00U | ISODEP_PCB_IBLOCK | ISODEP_PCB_B2_BIT | \ + ((bn) & \ + ISODEP_PCB_BN_MASK))) /*!< Returns an I-Block with the given block number (bn) */ +#define isoDep_PCBIBlockChaining(bn) \ + ((uint8_t)(isoDep_PCBIBlock(bn) | \ + ISODEP_PCB_CHAINING_BIT)) /*!< Returns an I-Block with the given block number (bn) indicating chaining */ + +#define isoDep_PCBRBlock(bn) \ + ((uint8_t)(0x00U | ISODEP_PCB_RBLOCK | ISODEP_PCB_B6_BIT | ISODEP_PCB_B2_BIT | \ + ((bn) & \ + ISODEP_PCB_BN_MASK))) /*!< Returns an R-Block with the given block number (bn) */ +#define isoDep_PCBRACK(bn) \ + ((uint8_t)(isoDep_PCBRBlock(bn) | \ + ISODEP_PCB_ACK)) /*!< Returns an R-Block with the given block number (bn) indicating ACK */ +#define isoDep_PCBRNAK(bn) \ + ((uint8_t)(isoDep_PCBRBlock(bn) | \ + ISODEP_PCB_NAK)) /*!< Returns an R-Block with the given block number (bn) indicating NAK */ + +#define isoDep_GetBN(pcb) \ + ((uint8_t)((pcb) & \ + ISODEP_PCB_BN_MASK)) /*!< Returns the block number (bn) from the given pcb */ +#define isoDep_GetWTXM(inf) \ + ((uint8_t)((inf) & \ + ISODEP_SWTX_WTXM_MASK)) /*!< Returns the WTX value from the given inf byte */ +#define isoDep_isWTXMValid(wtxm) \ + (((wtxm) >= ISODEP_WTXM_MIN) && \ + ((wtxm) <= ISODEP_WTXM_MAX)) /*!< Checks if the given wtxm is valid */ + +#define isoDep_WTXMListenerMax(fwt) \ + (MIN( \ + (uint8_t)(ISODEP_FWT_LIS_MAX / (fwt)), \ + ISODEP_WTXM_MAX)) /*!< Calculates the Max WTXM value for the given fwt as a Listener */ + +#define isoDepCalcdSGFT(s) \ + (384U * ((uint32_t)1U \ + << (s))) /*!< Calculates the dSFGT with given SFGI Digital 1.1 13.8.2.1 & A.6*/ +#define isoDepCalcSGFT(s) \ + (4096U * ((uint32_t)1U \ + << (s))) /*!< Calculates the SFGT with given SFGI Digital 1.1 13.8.2 */ + +#define isoDep_PCBNextBN(bn) \ + (((uint8_t)(bn) ^ 0x01U) & \ + ISODEP_PCB_BN_MASK) /*!< Returns the value of the next block number based on bn */ +#define isoDep_PCBPrevBN(bn) \ + isoDep_PCBNextBN(bn) /*!< Returns the value of the previous block number based on bn */ +#define isoDep_ToggleBN(bn) \ + ((bn) = \ + (((bn) ^ 0x01U) & \ + ISODEP_PCB_BN_MASK)) /*!< Toggles the block number value of the given bn */ + +#define isoDep_WTXAdjust(v) \ + ((v) - ((v) >> 3)) /*!< Adjust WTX timer value to a percentage of the total, current 88% */ + +/*! ISO 14443-4 7.5.6.2 & Digital 1.1 - 15.2.6.2 The CE SHALL NOT attempt error recovery and remains in Rx mode upon Transmission or a Protocol Error */ +#define isoDepReEnableRx(rxB, rxBL, rxL) \ + rfalTransceiveBlockingTx(NULL, 0, rxB, rxBL, rxL, RFAL_TXRX_FLAGS_DEFAULT, RFAL_FWT_NONE) + +/*! Macro used for the blocking methods */ +#define rfalIsoDepRunBlocking(e, fn) \ + do { \ + (e) = (fn); \ + rfalWorker(); \ + } while((e) == ERR_BUSY) + +#define isoDepTimerStart(timer, time_ms) \ + do { \ + platformTimerDestroy(timer); \ + (timer) = platformTimerCreate((uint16_t)(time_ms)); \ + } while(0) /*!< Configures and starts the WTX timer */ +#define isoDepTimerisExpired(timer) \ + platformTimerIsExpired(timer) /*!< Checks WTX timer has expired */ +#define isoDepTimerDestroy(timer) \ + platformTimerDestroy(timer) /*!< Destroys WTX timer */ + +/* + ****************************************************************************** + * LOCAL DATA TYPES + ****************************************************************************** + */ + +/*! Internal structure to be used in handling of S(PARAMETERS) only */ +typedef struct { + uint8_t pcb; /*!< PCB byte */ + rfalIsoDepSParameter sParam; /*!< S(PARAMETERS) */ +} rfalIsoDepControlMsgSParam; + +/*! Enumeration of the possible control message types */ +typedef enum { + ISODEP_R_ACK, /*!< R-ACK Acknowledge */ + ISODEP_R_NAK, /*!< R-NACK Negative acknowledge */ + ISODEP_S_WTX, /*!< S-WTX Waiting Time Extension */ + ISODEP_S_DSL /*!< S-DSL Deselect */ +} rfalIsoDepControlMsg; + +/*! Enumeration of the IsoDep roles */ +typedef enum { + ISODEP_ROLE_PCD, /*!< Perform as Reader/PCD */ + ISODEP_ROLE_PICC /*!< Perform as Card/PICC */ +} rfalIsoDepRole; + +/*! ISO-DEP layer states */ +typedef enum { + ISODEP_ST_IDLE, /*!< Idle State */ + ISODEP_ST_PCD_TX, /*!< PCD Transmission State */ + ISODEP_ST_PCD_RX, /*!< PCD Reception State */ + ISODEP_ST_PCD_WAIT_DSL, /*!< PCD Wait for DSL response */ + + ISODEP_ST_PICC_ACT_ATS, /*!< PICC has replied to RATS (ATS) */ + ISODEP_ST_PICC_ACT_ATTRIB, /*!< PICC has replied to ATTRIB */ + ISODEP_ST_PICC_RX, /*!< PICC Reception State */ + ISODEP_ST_PICC_SWTX, /*!< PICC Waiting Time eXtension */ + ISODEP_ST_PICC_SDSL, /*!< PICC S(DSL) response ongoing */ + ISODEP_ST_PICC_TX, /*!< PICC Transmission State */ + + ISODEP_ST_PCD_ACT_RATS, /*!< PCD activation (RATS) */ + ISODEP_ST_PCD_ACT_PPS, /*!< PCD activation (PPS) */ + +} rfalIsoDepState; + +/*! Holds all ISO-DEP data(counters, buffers, ID, timeouts, frame size) */ +typedef struct { + rfalIsoDepState state; /*!< ISO-DEP module state */ + rfalIsoDepRole role; /*!< Current ISO-DEP role */ + + uint8_t blockNumber; /*!< Current block number */ + uint8_t did; /*!< Current DID */ + uint8_t nad; /*!< Current DID */ + uint8_t cntIRetrys; /*!< I-Block retry counter */ + uint8_t cntRRetrys; /*!< R-Block retry counter */ + uint8_t cntSDslRetrys; /*!< S(DESELECT) retry counter */ + uint8_t cntSWtxRetrys; /*!< Overall S(WTX) retry counter */ + uint8_t cntSWtxNack; /*!< R(NACK) answered with S(WTX) counter */ + uint32_t fwt; /*!< Current FWT (Frame Waiting Time) */ + uint32_t dFwt; /*!< Current delta FWT */ + uint16_t fsx; /*!< Current FSx FSC or FSD (max Frame size) */ + bool isTxChaining; /*!< Flag for chaining on Tx */ + bool isRxChaining; /*!< Flag for chaining on Rx */ + uint8_t* txBuf; /*!< Tx buffer pointer */ + uint8_t* rxBuf; /*!< Rx buffer pointer */ + uint16_t txBufLen; /*!< Tx buffer length */ + uint16_t rxBufLen; /*!< Rx buffer length */ + uint8_t txBufInfPos; /*!< Start of payload in txBuf */ + uint8_t rxBufInfPos; /*!< Start of payload in rxBuf */ + + uint16_t ourFsx; /*!< Our current FSx FSC or FSD (Frame size) */ + uint8_t lastPCB; /*!< Last PCB sent */ + uint8_t lastWTXM; /*!< Last WTXM sent */ + uint8_t atsTA; /*!< TA on ATS */ + uint8_t hdrLen; /*!< Current ISO-DEP length */ + rfalBitRate txBR; /*!< Current Tx Bit Rate */ + rfalBitRate rxBR; /*!< Current Rx Bit Rate */ + uint16_t* rxLen; /*!< Output parameter ptr to Rx length */ + bool* rxChaining; /*!< Output parameter ptr to Rx chaining flag */ + uint32_t WTXTimer; /*!< Timer used for WTX */ + bool lastDID00; /*!< Last PCD block had DID flag (for DID = 0) */ + + bool isTxPending; /*!< Flag pending Block while waiting WTX Ack */ + bool isWait4WTX; /*!< Flag for waiting WTX Ack */ + + uint8_t maxRetriesI; /*!< Number of retries for a I-Block */ + uint8_t maxRetriesR; /*!< Number of retries for a R-Block */ + uint8_t maxRetriesSDSL; /*!< Number of retries for S(DESELECT) errors */ + uint8_t maxRetriesSWTX; /*!< Number of retries for S(WTX) errors */ + uint8_t maxRetriesSnWTX; /*!< Number of retries S(WTX) replied w NACK */ + uint8_t maxRetriesRATS; /*!< Number of retries for RATS */ + + rfalComplianceMode compMode; /*!< Compliance mode */ + + uint8_t ctrlBuf[ISODEP_CONTROLMSG_BUF_LEN]; /*!< Control msg buf */ + uint16_t ctrlRxLen; /*!< Control msg rcvd len */ + + union { /* PRQA S 0750 # MISRA 19.2 - Members of the union will not be used concurrently, only one frame at a time */ +#if RFAL_FEATURE_NFCA + rfalIsoDepRats ratsReq; + rfalIsoDepPpsReq ppsReq; +#endif /* RFAL_FEATURE_NFCA */ + +#if RFAL_FEATURE_NFCB + rfalIsoDepAttribCmd attribReq; +#endif /* RFAL_FEATURE_NFCB */ + } actv; /*!< Activation buffer */ + + uint8_t* rxLen8; /*!< Receive length (8-bit) */ + rfalIsoDepDevice* actvDev; /*!< Activation Device Info */ + rfalIsoDepListenActvParam actvParam; /*!< Listen Activation context */ + + rfalIsoDepApduTxRxParam APDUParam; /*!< APDU TxRx params */ + uint16_t APDUTxPos; /*!< APDU Tx position */ + uint16_t APDURxPos; /*!< APDU Rx position */ + bool isAPDURxChaining; /*!< APDU Transceive chaining flag */ + +} rfalIsoDep; + +/* + ****************************************************************************** + * LOCAL VARIABLES + ****************************************************************************** + */ + +static rfalIsoDep gIsoDep; /*!< ISO-DEP Module instance */ + +/* + ****************************************************************************** + * LOCAL FUNCTION PROTOTYPES + ****************************************************************************** + */ +static void isoDepClearCounters(void); +static ReturnCode + isoDepTx(uint8_t pcb, const uint8_t* txBuf, uint8_t* infBuf, uint16_t infLen, uint32_t fwt); +static ReturnCode isoDepHandleControlMsg(rfalIsoDepControlMsg controlMsg, uint8_t param); +static void rfalIsoDepApdu2IBLockParam( + rfalIsoDepApduTxRxParam apduParam, + rfalIsoDepTxRxParam* iBlockParam, + uint16_t txPos, + uint16_t rxPos); + +#if RFAL_FEATURE_ISO_DEP_POLL +static ReturnCode isoDepDataExchangePCD(uint16_t* outActRxLen, bool* outIsChaining); +static void rfalIsoDepCalcBitRate( + rfalBitRate maxAllowedBR, + uint8_t piccBRCapability, + rfalBitRate* dsi, + rfalBitRate* dri); +static uint32_t rfalIsoDepSFGI2SFGT(uint8_t sfgi); + +#if RFAL_FEATURE_NFCA +static ReturnCode + rfalIsoDepStartRATS(rfalIsoDepFSxI FSDI, uint8_t DID, rfalIsoDepAts* ats, uint8_t* atsLen); +static ReturnCode rfalIsoDepGetRATSStatus(void); +static ReturnCode + rfalIsoDepStartPPS(uint8_t DID, rfalBitRate DSI, rfalBitRate DRI, rfalIsoDepPpsRes* ppsRes); +static ReturnCode rfalIsoDepGetPPSSTatus(void); +#endif /* RFAL_FEATURE_NFCA */ + +#if RFAL_FEATURE_NFCB +static ReturnCode rfalIsoDepStartATTRIB( + const uint8_t* nfcid0, + uint8_t PARAM1, + rfalBitRate DSI, + rfalBitRate DRI, + rfalIsoDepFSxI FSDI, + uint8_t PARAM3, + uint8_t DID, + const uint8_t* HLInfo, + uint8_t HLInfoLen, + uint32_t fwt, + rfalIsoDepAttribRes* attribRes, + uint8_t* attribResLen); +static ReturnCode rfalIsoDepGetATTRIBStatus(void); +#endif /* RFAL_FEATURE_NFCB */ + +#endif /* RFAL_FEATURE_ISO_DEP_POLL */ + +#if RFAL_FEATURE_ISO_DEP_LISTEN +static ReturnCode isoDepDataExchangePICC(void); +static ReturnCode isoDepReSendControlMsg(void); +#endif + +/* + ****************************************************************************** + * LOCAL FUNCTIONS + ****************************************************************************** + */ + +/*******************************************************************************/ +static void isoDepClearCounters(void) { + gIsoDep.cntIRetrys = 0; + gIsoDep.cntRRetrys = 0; + gIsoDep.cntSDslRetrys = 0; + gIsoDep.cntSWtxRetrys = 0; + gIsoDep.cntSWtxNack = 0; +} + +/*******************************************************************************/ +static ReturnCode + isoDepTx(uint8_t pcb, const uint8_t* txBuf, uint8_t* infBuf, uint16_t infLen, uint32_t fwt) { + uint8_t* txBlock; + uint16_t txBufLen; + uint8_t computedPcb; + rfalTransceiveContext ctx; + + txBlock = infBuf; /* Point to beginning of the INF, and go backwards */ + gIsoDep.lastPCB = pcb; /* Store the last PCB sent */ + + if(infLen > 0U) { + if(((uint32_t)infBuf - (uint32_t)txBuf) < + gIsoDep.hdrLen) /* Check that we can fit the header in the given space */ + { + return ERR_NOMEM; + } + } + + /*******************************************************************************/ + /* Compute optional PCB bits */ + computedPcb = pcb; + if((gIsoDep.did != RFAL_ISODEP_NO_DID) || + ((gIsoDep.did == RFAL_ISODEP_DID_00) && gIsoDep.lastDID00)) { + computedPcb |= ISODEP_PCB_DID_BIT; + } + if(gIsoDep.nad != RFAL_ISODEP_NO_NAD) { + computedPcb |= ISODEP_PCB_NAD_BIT; + } + if((gIsoDep.isTxChaining) && (isoDep_PCBisIBlock(computedPcb))) { + computedPcb |= ISODEP_PCB_CHAINING_BIT; + } + + /*******************************************************************************/ + /* Compute Payload on the given txBuf, start by the PCB | DID | NAD | before INF */ + + if(gIsoDep.nad != RFAL_ISODEP_NO_NAD) { + *(--txBlock) = gIsoDep.nad; /* NAD is optional */ + } + + if((gIsoDep.did != RFAL_ISODEP_NO_DID) || + ((gIsoDep.did == RFAL_ISODEP_DID_00) && gIsoDep.lastDID00)) { + *(--txBlock) = gIsoDep.did; /* DID is optional */ + } + + *(--txBlock) = computedPcb; /* PCB always present */ + + txBufLen = + (infLen + + (uint16_t)((uint32_t)infBuf - (uint32_t)txBlock)); /* Calculate overall buffer size */ + + if(txBufLen > (gIsoDep.fsx - + ISODEP_CRC_LEN)) /* Check if msg length violates the maximum frame size FSC */ + { + return ERR_NOTSUPP; + } + + rfalCreateByteFlagsTxRxContext( + ctx, + txBlock, + txBufLen, + gIsoDep.rxBuf, + gIsoDep.rxBufLen, + gIsoDep.rxLen, + RFAL_TXRX_FLAGS_DEFAULT, + ((gIsoDep.role == ISODEP_ROLE_PICC) ? RFAL_FWT_NONE : fwt)); + return rfalStartTransceive(&ctx); +} + +/*******************************************************************************/ +static ReturnCode isoDepHandleControlMsg(rfalIsoDepControlMsg controlMsg, uint8_t param) { + uint8_t pcb; + uint8_t infLen; + uint32_t fwtTemp; + + infLen = 0; + fwtTemp = (gIsoDep.fwt + gIsoDep.dFwt); + ST_MEMSET(gIsoDep.ctrlBuf, 0x00, ISODEP_CONTROLMSG_BUF_LEN); + + switch(controlMsg) { + /*******************************************************************************/ + case ISODEP_R_ACK: + + if(gIsoDep.cntRRetrys++ > gIsoDep.maxRetriesR) { + return ERR_TIMEOUT; /* NFC Forum mandates timeout or transmission error depending on previous errors */ + } + + pcb = isoDep_PCBRACK(gIsoDep.blockNumber); + break; + + /*******************************************************************************/ + case ISODEP_R_NAK: + + if((gIsoDep.cntRRetrys++ > gIsoDep.maxRetriesR) || /* Max R Block retries reached */ + (gIsoDep.cntSWtxNack >= + gIsoDep + .maxRetriesSnWTX)) /* Max number PICC is allowed to respond with S(WTX) to R(NAK) */ + { + return ERR_TIMEOUT; + } + + pcb = isoDep_PCBRNAK(gIsoDep.blockNumber); + break; + + /*******************************************************************************/ + case ISODEP_S_WTX: + + if((gIsoDep.cntSWtxRetrys++ > gIsoDep.maxRetriesSWTX) && + (gIsoDep.maxRetriesSWTX != RFAL_ISODEP_MAX_WTX_RETRYS_ULTD)) { + return ERR_PROTO; + } + + /* Check if WTXM is valid */ + if(!isoDep_isWTXMValid(param)) { + return ERR_PROTO; + } + + if(gIsoDep.role == ISODEP_ROLE_PCD) { + /* Calculate temp Wait Time eXtension */ + fwtTemp = (gIsoDep.fwt * param); + fwtTemp = MIN(RFAL_ISODEP_MAX_FWT, fwtTemp); + fwtTemp += gIsoDep.dFwt; + } + + pcb = ISODEP_PCB_SWTX; + gIsoDep.ctrlBuf[RFAL_ISODEP_PCB_LEN + RFAL_ISODEP_DID_LEN + infLen++] = param; + break; + + /*******************************************************************************/ + case ISODEP_S_DSL: + + if(gIsoDep.cntSDslRetrys++ > gIsoDep.maxRetriesSDSL) { + return ERR_TIMEOUT; /* NFC Forum mandates timeout or transmission error depending on previous errors */ + } + + if(gIsoDep.role == ISODEP_ROLE_PCD) { + /* Digital 1.0 - 13.2.7.3 Poller must wait fwtDEACTIVATION */ + fwtTemp = ISODEP_FWT_DEACTIVATION; + gIsoDep.state = ISODEP_ST_PCD_WAIT_DSL; + } + pcb = ISODEP_PCB_SDSL; + break; + + /*******************************************************************************/ + default: + return ERR_INTERNAL; + } + + return isoDepTx( + pcb, + gIsoDep.ctrlBuf, + &gIsoDep.ctrlBuf[RFAL_ISODEP_PCB_LEN + RFAL_ISODEP_DID_LEN], + infLen, + fwtTemp); +} + +#if RFAL_FEATURE_ISO_DEP_LISTEN +/*******************************************************************************/ +static ReturnCode isoDepReSendControlMsg(void) { + if(isoDep_PCBisRACK(gIsoDep.lastPCB)) { + return isoDepHandleControlMsg(ISODEP_R_ACK, RFAL_ISODEP_NO_PARAM); + } + + if(isoDep_PCBisRNAK(gIsoDep.lastPCB)) { + return isoDepHandleControlMsg(ISODEP_R_NAK, RFAL_ISODEP_NO_PARAM); + } + + if(isoDep_PCBisSDeselect(gIsoDep.lastPCB)) { + return isoDepHandleControlMsg(ISODEP_S_DSL, RFAL_ISODEP_NO_PARAM); + } + + if(isoDep_PCBisSWTX(gIsoDep.lastPCB)) { + return isoDepHandleControlMsg(ISODEP_S_WTX, gIsoDep.lastWTXM); + } + return ERR_WRONG_STATE; +} +#endif /* RFAL_FEATURE_ISO_DEP_LISTEN */ + +/* + ****************************************************************************** + * GLOBAL FUNCTIONS + ****************************************************************************** + */ + +/*******************************************************************************/ +void rfalIsoDepInitialize(void) { + gIsoDep.state = ISODEP_ST_IDLE; + gIsoDep.role = ISODEP_ROLE_PCD; + gIsoDep.did = RFAL_ISODEP_NO_DID; + gIsoDep.nad = RFAL_ISODEP_NO_NAD; + gIsoDep.blockNumber = 0; + gIsoDep.isTxChaining = false; + gIsoDep.isRxChaining = false; + gIsoDep.lastDID00 = false; + gIsoDep.lastPCB = ISODEP_PCB_INVALID; + gIsoDep.fsx = (uint16_t)RFAL_ISODEP_FSX_16; + gIsoDep.ourFsx = (uint16_t)RFAL_ISODEP_FSX_16; + gIsoDep.hdrLen = RFAL_ISODEP_PCB_LEN; + + gIsoDep.rxLen = NULL; + gIsoDep.rxBuf = NULL; + gIsoDep.rxBufInfPos = 0U; + gIsoDep.txBufInfPos = 0U; + + gIsoDep.isTxPending = false; + gIsoDep.isWait4WTX = false; + + gIsoDep.compMode = RFAL_COMPLIANCE_MODE_NFC; + gIsoDep.maxRetriesR = RFAL_ISODEP_MAX_R_RETRYS; + gIsoDep.maxRetriesI = RFAL_ISODEP_MAX_I_RETRYS; + gIsoDep.maxRetriesSDSL = RFAL_ISODEP_MAX_DSL_RETRYS; + gIsoDep.maxRetriesSWTX = RFAL_ISODEP_MAX_WTX_RETRYS; + gIsoDep.maxRetriesSnWTX = RFAL_ISODEP_MAX_WTX_NACK_RETRYS; + gIsoDep.maxRetriesRATS = RFAL_ISODEP_RATS_RETRIES; + + gIsoDep.APDURxPos = 0; + gIsoDep.APDUTxPos = 0; + gIsoDep.APDUParam.rxLen = NULL; + gIsoDep.APDUParam.rxBuf = NULL; + gIsoDep.APDUParam.txBuf = NULL; + + isoDepClearCounters(); + + /* Destroy any ongoing WTX timer */ + isoDepTimerDestroy(gIsoDep.WTXTimer); + gIsoDep.WTXTimer = 0U; +} + +/*******************************************************************************/ +void rfalIsoDepInitializeWithParams( + rfalComplianceMode compMode, + uint8_t maxRetriesR, + uint8_t maxRetriesSnWTX, + uint8_t maxRetriesSWTX, + uint8_t maxRetriesSDSL, + uint8_t maxRetriesI, + uint8_t maxRetriesRATS) { + rfalIsoDepInitialize(); + + gIsoDep.compMode = compMode; + gIsoDep.maxRetriesR = maxRetriesR; + gIsoDep.maxRetriesSnWTX = maxRetriesSnWTX; + gIsoDep.maxRetriesSWTX = maxRetriesSWTX; + gIsoDep.maxRetriesSDSL = maxRetriesSDSL; + gIsoDep.maxRetriesI = maxRetriesI; + gIsoDep.maxRetriesRATS = maxRetriesRATS; +} + +#if RFAL_FEATURE_ISO_DEP_POLL +/*******************************************************************************/ +static ReturnCode isoDepDataExchangePCD(uint16_t* outActRxLen, bool* outIsChaining) { + ReturnCode ret; + uint8_t rxPCB; + + /* Check out parameters */ + if((outActRxLen == NULL) || (outIsChaining == NULL)) { + return ERR_PARAM; + } + + *outIsChaining = false; + + /* Calculate header required and check if the buffers InfPositions are suitable */ + gIsoDep.hdrLen = RFAL_ISODEP_PCB_LEN; + if(gIsoDep.did != RFAL_ISODEP_NO_DID) { + gIsoDep.hdrLen += RFAL_ISODEP_DID_LEN; + } + if(gIsoDep.nad != RFAL_ISODEP_NO_NAD) { + gIsoDep.hdrLen += RFAL_ISODEP_NAD_LEN; + } + + /* Check if there is enough space before the infPos to append ISO-DEP headers on rx and tx */ + if((gIsoDep.rxBufInfPos < gIsoDep.hdrLen) || (gIsoDep.txBufInfPos < gIsoDep.hdrLen)) { + return ERR_PARAM; + } + + /*******************************************************************************/ + switch(gIsoDep.state) { + /*******************************************************************************/ + case ISODEP_ST_IDLE: + return ERR_NONE; + + /*******************************************************************************/ + case ISODEP_ST_PCD_TX: + ret = isoDepTx( + isoDep_PCBIBlock(gIsoDep.blockNumber), + gIsoDep.txBuf, + &gIsoDep.txBuf[gIsoDep.txBufInfPos], + gIsoDep.txBufLen, + (gIsoDep.fwt + gIsoDep.dFwt)); + switch(ret) { + case ERR_NONE: + gIsoDep.state = ISODEP_ST_PCD_RX; + break; + + default: + return ret; + } + /* fall through */ + + /*******************************************************************************/ + case ISODEP_ST_PCD_WAIT_DSL: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + case ISODEP_ST_PCD_RX: + + ret = rfalGetTransceiveStatus(); + switch(ret) { + /* Data rcvd with error or timeout -> Send R-NAK */ + case ERR_TIMEOUT: + case ERR_CRC: + case ERR_PAR: + case ERR_FRAMING: /* added to handle test cases scenario TC_POL_NFCB_T4AT_BI_82_x_y & TC_POL_NFCB_T4BT_BI_82_x_y */ + case ERR_INCOMPLETE_BYTE: /* added to handle test cases scenario TC_POL_NFCB_T4AT_BI_82_x_y & TC_POL_NFCB_T4BT_BI_82_x_y */ + + if(gIsoDep + .isRxChaining) { /* Rule 5 - In PICC chaining when a invalid/timeout occurs -> R-ACK */ + EXIT_ON_ERR(ret, isoDepHandleControlMsg(ISODEP_R_ACK, RFAL_ISODEP_NO_PARAM)); + } else if( + gIsoDep.state == + ISODEP_ST_PCD_WAIT_DSL) { /* Rule 8 - If s-Deselect response fails MAY retransmit */ + EXIT_ON_ERR(ret, isoDepHandleControlMsg(ISODEP_S_DSL, RFAL_ISODEP_NO_PARAM)); + } else { /* Rule 4 - When a invalid block or timeout occurs -> R-NACK */ + EXIT_ON_ERR(ret, isoDepHandleControlMsg(ISODEP_R_NAK, RFAL_ISODEP_NO_PARAM)); + } + return ERR_BUSY; + + case ERR_NONE: + break; + + case ERR_BUSY: + return ERR_BUSY; /* Debug purposes */ + + default: + return ret; + } + + /*******************************************************************************/ + /* No error, process incoming msg */ + /*******************************************************************************/ + + (*outActRxLen) = rfalConvBitsToBytes(*outActRxLen); + + /* Check rcvd msg length, cannot be less then the expected header */ + if(((*outActRxLen) < gIsoDep.hdrLen) || ((*outActRxLen) >= gIsoDep.ourFsx)) { + return ERR_PROTO; + } + + /* Grab rcvd PCB */ + rxPCB = gIsoDep.rxBuf[ISODEP_PCB_POS]; + + /* EMVCo doesn't allow usage of for CID or NAD EMVCo 2.6 TAble 10.2 */ + if((gIsoDep.compMode == RFAL_COMPLIANCE_MODE_EMV) && + (isoDep_PCBhasDID(rxPCB) || isoDep_PCBhasNAD(rxPCB))) { + return ERR_PROTO; + } + + /* If we are expecting DID, check if PCB signals its presence and if device ID match*/ + if((gIsoDep.did != RFAL_ISODEP_NO_DID) && + (!isoDep_PCBhasDID(rxPCB) || (gIsoDep.did != gIsoDep.rxBuf[ISODEP_DID_POS]))) { + return ERR_PROTO; + } + + /*******************************************************************************/ + /* Process S-Block */ + /*******************************************************************************/ + if(isoDep_PCBisSBlock(rxPCB)) { + /* Check if is a Wait Time eXtension */ + if(isoDep_PCBisSWTX(rxPCB)) { + /* Check if PICC has requested S(WTX) as response to R(NAK) EMVCo 3.0 10.3.5.5 / Digital 2.0 16.2.6.5 */ + if(isoDep_PCBisRNAK(gIsoDep.lastPCB)) { + gIsoDep.cntSWtxNack++; /* Count S(WTX) upon R(NAK) */ + gIsoDep.cntRRetrys = 0; /* Reset R-Block counter has PICC has responded */ + } else { + gIsoDep.cntSWtxNack = 0; /* Reset R(NACK)->S(WTX) counter */ + } + + /* Rule 3 - respond to S-block: get 1st INF byte S(STW): Power + WTXM */ + EXIT_ON_ERR( + ret, + isoDepHandleControlMsg( + ISODEP_S_WTX, isoDep_GetWTXM(gIsoDep.rxBuf[gIsoDep.hdrLen]))); + return ERR_BUSY; + } + + /* Check if is a deselect response */ + if(isoDep_PCBisSDeselect(rxPCB)) { + if(gIsoDep.state == ISODEP_ST_PCD_WAIT_DSL) { + rfalIsoDepInitialize(); /* Session finished reInit vars */ + return ERR_NONE; + } + + /* Deselect response not expected */ + /* fall through to PROTO error */ + } + /* Unexpected S-Block */ + return ERR_PROTO; + } + + /*******************************************************************************/ + /* Process R-Block */ + /*******************************************************************************/ + else if(isoDep_PCBisRBlock(rxPCB)) { + if(isoDep_PCBisRACK(rxPCB)) /* Check if is a R-ACK */ + { + if(isoDep_GetBN(rxPCB) == gIsoDep.blockNumber) /* Expected block number */ + { + /* Rule B - ACK with expected bn -> Increment block number */ + gIsoDep.blockNumber = isoDep_PCBNextBN(gIsoDep.blockNumber); + + /* R-ACK only allowed when PCD chaining */ + if(!gIsoDep.isTxChaining) { + return ERR_PROTO; + } + + /* Rule 7 - Chaining transaction done, continue chaining */ + isoDepClearCounters(); + return ERR_NONE; /* This block has been transmitted */ + } else { + /* Rule 6 - R-ACK with wrong block number retransmit */ + /* Digital 2.0 16.2.5.4 - Retransmit maximum two times */ + /* EMVCo 3.0 10.3.4.3 - PCD may re-transmit the last I-Block or report error */ + if(gIsoDep.cntIRetrys++ < gIsoDep.maxRetriesI) { + gIsoDep.cntRRetrys = 0; /* Clear R counter only */ + gIsoDep.state = ISODEP_ST_PCD_TX; + return ERR_BUSY; + } + return ERR_TIMEOUT; /* NFC Forum mandates timeout or transmission error depending on previous errors */ + } + } else /* Unexpected R-Block */ + { + return ERR_PROTO; + } + } + + /*******************************************************************************/ + /* Process I-Block */ + /*******************************************************************************/ + else if(isoDep_PCBisIBlock(rxPCB)) { + /*******************************************************************************/ + /* is PICC performing chaining */ + if(isoDep_PCBisChaining(rxPCB)) { + gIsoDep.isRxChaining = true; + *outIsChaining = true; + + if(isoDep_GetBN(rxPCB) == gIsoDep.blockNumber) { + /* Rule B - ACK with correct block number -> Increase Block number */ + isoDep_ToggleBN(gIsoDep.blockNumber); + + isoDepClearCounters(); /* Clear counters in case R counter is already at max */ + + /* Rule 2 - Send ACK */ + EXIT_ON_ERR(ret, isoDepHandleControlMsg(ISODEP_R_ACK, RFAL_ISODEP_NO_PARAM)); + + /* Received I-Block with chaining, send current data to DH */ + + /* remove ISO DEP header, check is necessary to move the INF data on the buffer */ + *outActRxLen -= gIsoDep.hdrLen; + if((gIsoDep.hdrLen != gIsoDep.rxBufInfPos) && (*outActRxLen > 0U)) { + ST_MEMMOVE( + &gIsoDep.rxBuf[gIsoDep.rxBufInfPos], + &gIsoDep.rxBuf[gIsoDep.hdrLen], + *outActRxLen); + } + + isoDepClearCounters(); + return ERR_AGAIN; /* Send Again signalling to run again, but some chaining data has arrived */ + } else { + /* Rule 5 - PICC chaining invalid I-Block -> R-ACK */ + EXIT_ON_ERR(ret, isoDepHandleControlMsg(ISODEP_R_ACK, RFAL_ISODEP_NO_PARAM)); + } + return ERR_BUSY; + } + + gIsoDep.isRxChaining = false; /* clear PICC chaining flag */ + + if(isoDep_GetBN(rxPCB) == gIsoDep.blockNumber) { + /* Rule B - I-Block with correct block number -> Increase Block number */ + isoDep_ToggleBN(gIsoDep.blockNumber); + + /* I-Block transaction done successfully */ + + /* remove ISO DEP header, check is necessary to move the INF data on the buffer */ + *outActRxLen -= gIsoDep.hdrLen; + if((gIsoDep.hdrLen != gIsoDep.rxBufInfPos) && (*outActRxLen > 0U)) { + ST_MEMMOVE( + &gIsoDep.rxBuf[gIsoDep.rxBufInfPos], + &gIsoDep.rxBuf[gIsoDep.hdrLen], + *outActRxLen); + } + + gIsoDep.state = ISODEP_ST_IDLE; + isoDepClearCounters(); + return ERR_NONE; + } else { + if((gIsoDep.compMode != RFAL_COMPLIANCE_MODE_ISO)) { + /* Invalid Block (not chaining) -> Raise error Digital 1.1 15.2.6.4 EMVCo 2.6 10.3.5.4 */ + return ERR_PROTO; + } + + /* Rule 4 - Invalid Block -> R-NAK */ + EXIT_ON_ERR(ret, isoDepHandleControlMsg(ISODEP_R_NAK, RFAL_ISODEP_NO_PARAM)); + return ERR_BUSY; + } + } else /* not S/R/I - Block */ + { + return ERR_PROTO; + } + /* fall through */ + + /*******************************************************************************/ + default: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + /* MISRA 16.4: no empty default (comment will suffice) */ + break; + } + + return ERR_INTERNAL; +} + +/*******************************************************************************/ +ReturnCode rfalIsoDepDeselect(void) { + ReturnCode ret; + uint32_t cntRerun; + bool dummyB; + + /*******************************************************************************/ + /* Using local static vars and static config to cope with a Deselect after * + * RATS\ATTRIB without any I-Block exchanged */ + gIsoDep.rxLen = &gIsoDep.ctrlRxLen; + gIsoDep.rxBuf = gIsoDep.ctrlBuf; + gIsoDep.rxBufLen = ISODEP_CONTROLMSG_BUF_LEN - (RFAL_ISODEP_PCB_LEN + RFAL_ISODEP_DID_LEN); + gIsoDep.rxBufInfPos = (RFAL_ISODEP_PCB_LEN + RFAL_ISODEP_DID_LEN); + gIsoDep.txBufInfPos = (RFAL_ISODEP_PCB_LEN + RFAL_ISODEP_DID_LEN); + + /*******************************************************************************/ + /* The Deselect process is being done blocking, Digital 1.0 - 13.2.7.1 MUST wait response and retry*/ + /* Set the maximum reruns while we will wait for a response */ + cntRerun = ISODEP_MAX_RERUNS; + + /* Send DSL request and run protocol until get a response, error or "timeout" */ + EXIT_ON_ERR(ret, isoDepHandleControlMsg(ISODEP_S_DSL, RFAL_ISODEP_NO_PARAM)); + do { + ret = isoDepDataExchangePCD(gIsoDep.rxLen, &dummyB); + rfalWorker(); + } while(((cntRerun--) != 0U) && (ret == ERR_BUSY)); + + rfalIsoDepInitialize(); + return ((cntRerun == 0U) ? ERR_TIMEOUT : ret); +} + +#endif /* RFAL_FEATURE_ISO_DEP_POLL */ + +/*******************************************************************************/ +uint32_t rfalIsoDepFWI2FWT(uint8_t fwi) { + uint32_t result; + uint8_t tmpFWI; + + tmpFWI = fwi; + + /* RFU values -> take the default value + * Digital 1.0 11.6.2.17 FWI[1,14] + * Digital 1.1 7.6.2.22 FWI[0,14] + * EMVCo 2.6 Table A.5 FWI[0,14] */ + if(tmpFWI > ISODEP_FWI_MAX) { + tmpFWI = RFAL_ISODEP_FWI_DEFAULT; + } + + /* FWT = (256 x 16/fC) x 2^FWI => 2^(FWI+12) Digital 1.1 13.8.1 & 7.9.1 */ + + result = ((uint32_t)1U << (tmpFWI + 12U)); + result = MIN(RFAL_ISODEP_MAX_FWT, result); /* Maximum Frame Waiting Time must be fulfilled */ + + return result; +} + +/*******************************************************************************/ +uint16_t rfalIsoDepFSxI2FSx(uint8_t FSxI) { + uint16_t fsx; + uint8_t fsi; + + /* Enforce maximum FSxI/FSx allowed - NFC Forum and EMVCo differ */ + fsi = + ((gIsoDep.compMode == RFAL_COMPLIANCE_MODE_EMV) ? MIN(FSxI, RFAL_ISODEP_FSDI_MAX_EMV) : + MIN(FSxI, RFAL_ISODEP_FSDI_MAX_NFC)); + + switch(fsi) { + case(uint8_t)RFAL_ISODEP_FSXI_16: + fsx = (uint16_t)RFAL_ISODEP_FSX_16; + break; + case(uint8_t)RFAL_ISODEP_FSXI_24: + fsx = (uint16_t)RFAL_ISODEP_FSX_24; + break; + case(uint8_t)RFAL_ISODEP_FSXI_32: + fsx = (uint16_t)RFAL_ISODEP_FSX_32; + break; + case(uint8_t)RFAL_ISODEP_FSXI_40: + fsx = (uint16_t)RFAL_ISODEP_FSX_40; + break; + case(uint8_t)RFAL_ISODEP_FSXI_48: + fsx = (uint16_t)RFAL_ISODEP_FSX_48; + break; + case(uint8_t)RFAL_ISODEP_FSXI_64: + fsx = (uint16_t)RFAL_ISODEP_FSX_64; + break; + case(uint8_t)RFAL_ISODEP_FSXI_96: + fsx = (uint16_t)RFAL_ISODEP_FSX_96; + break; + case(uint8_t)RFAL_ISODEP_FSXI_128: + fsx = (uint16_t)RFAL_ISODEP_FSX_128; + break; + case(uint8_t)RFAL_ISODEP_FSXI_256: + fsx = (uint16_t)RFAL_ISODEP_FSX_256; + break; + case(uint8_t)RFAL_ISODEP_FSXI_512: + fsx = (uint16_t)RFAL_ISODEP_FSX_512; + break; + case(uint8_t)RFAL_ISODEP_FSXI_1024: + fsx = (uint16_t)RFAL_ISODEP_FSX_1024; + break; + case(uint8_t)RFAL_ISODEP_FSXI_2048: + fsx = (uint16_t)RFAL_ISODEP_FSX_2048; + break; + case(uint8_t)RFAL_ISODEP_FSXI_4096: + fsx = (uint16_t)RFAL_ISODEP_FSX_4096; + break; + default: + fsx = (uint16_t)RFAL_ISODEP_FSX_256; + break; + } + return fsx; +} + +#if RFAL_FEATURE_ISO_DEP_LISTEN + +/*******************************************************************************/ +bool rfalIsoDepIsRats(const uint8_t* buf, uint8_t bufLen) { + if(buf != NULL) { + if((RFAL_ISODEP_CMD_RATS == (uint8_t)*buf) && (sizeof(rfalIsoDepRats) == bufLen)) { + return true; + } + } + return false; +} + +/*******************************************************************************/ +bool rfalIsoDepIsAttrib(const uint8_t* buf, uint8_t bufLen) { + if(buf != NULL) { + if((RFAL_ISODEP_CMD_ATTRIB == (uint8_t)*buf) && + (RFAL_ISODEP_ATTRIB_REQ_MIN_LEN <= bufLen) && + ((RFAL_ISODEP_ATTRIB_REQ_MIN_LEN + RFAL_ISODEP_ATTRIB_HLINFO_LEN) >= bufLen)) { + return true; + } + } + return false; +} + +/*******************************************************************************/ +ReturnCode rfalIsoDepListenStartActivation( + rfalIsoDepAtsParam* atsParam, + const rfalIsoDepAttribResParam* attribResParam, + const uint8_t* buf, + uint16_t bufLen, + rfalIsoDepListenActvParam actParam) { + uint8_t* txBuf; + uint8_t bufIt; + const uint8_t* buffer = buf; + + /*******************************************************************************/ + bufIt = 0; + txBuf = + (uint8_t*)actParam + .rxBuf; /* Use the rxBuf as TxBuf as well, the struct enforces a size enough MAX( NFCA_ATS_MAX_LEN, NFCB_ATTRIB_RES_MAX_LEN ) */ + gIsoDep.txBR = RFAL_BR_106; + gIsoDep.rxBR = RFAL_BR_106; + + /* Check for a valid buffer pointer */ + if(buffer == NULL) { + return ERR_PARAM; + } + + /*******************************************************************************/ + if(*buffer == RFAL_ISODEP_CMD_RATS) { + /* Check ATS parameters */ + if(atsParam == NULL) { + return ERR_PARAM; + } + + /* If requested copy RATS to device info */ + if(actParam.isoDepDev != NULL) { + ST_MEMCPY( + (uint8_t*)&actParam.isoDepDev->activation.A.Poller.RATS, + buffer, + sizeof(rfalIsoDepRats)); /* Copy RATS' CMD + PARAM */ + } + + /*******************************************************************************/ + /* Process RATS */ + buffer++; + gIsoDep.fsx = rfalIsoDepFSxI2FSx( + (((*buffer) & RFAL_ISODEP_RATS_PARAM_FSDI_MASK) >> RFAL_ISODEP_RATS_PARAM_FSDI_SHIFT)); + gIsoDep.did = (*buffer & RFAL_ISODEP_DID_MASK); + + /*******************************************************************************/ + /* Digital 1.1 13.6.1.8 - DID as to between 0 and 14 */ + if(gIsoDep.did > RFAL_ISODEP_DID_MAX) { + return ERR_PROTO; + } + + /* Check if we are configured to support DID */ + if((gIsoDep.did != RFAL_ISODEP_DID_00) && (!atsParam->didSupport)) { + return ERR_NOTSUPP; + } + + /*******************************************************************************/ + /* Check RFAL supported bit rates */ + if((!(RFAL_SUPPORT_BR_CE_A_212) && + (((atsParam->ta & RFAL_ISODEP_ATS_TA_DPL_212) != 0U) || + ((atsParam->ta & RFAL_ISODEP_ATS_TA_DLP_212) != 0U))) || + (!(RFAL_SUPPORT_BR_CE_A_424) && + (((atsParam->ta & RFAL_ISODEP_ATS_TA_DPL_424) != 0U) || + ((atsParam->ta & RFAL_ISODEP_ATS_TA_DLP_424) != 0U))) || + (!(RFAL_SUPPORT_BR_CE_A_848) && + (((atsParam->ta & RFAL_ISODEP_ATS_TA_DPL_848) != 0U) || + ((atsParam->ta & RFAL_ISODEP_ATS_TA_DLP_848) != 0U)))) { + return ERR_NOTSUPP; + } + + /* Enforce proper FWI configuration */ + if(atsParam->fwi > ISODEP_FWI_LIS_MAX) { + atsParam->fwi = ISODEP_FWI_LIS_MAX; + } + + gIsoDep.atsTA = atsParam->ta; + gIsoDep.fwt = rfalIsoDepFWI2FWT(atsParam->fwi); + gIsoDep.ourFsx = rfalIsoDepFSxI2FSx(atsParam->fsci); + + /* Ensure proper/maximum Historical Bytes length */ + atsParam->hbLen = MIN(RFAL_ISODEP_ATS_HB_MAX_LEN, atsParam->hbLen); + + /*******************************************************************************/ + /* Compute ATS */ + + txBuf[bufIt++] = (RFAL_ISODEP_ATS_HIST_OFFSET + atsParam->hbLen); /* TL */ + txBuf[bufIt++] = + ((RFAL_ISODEP_ATS_T0_TA_PRESENCE_MASK | RFAL_ISODEP_ATS_T0_TB_PRESENCE_MASK | + RFAL_ISODEP_ATS_T0_TC_PRESENCE_MASK) | + atsParam->fsci); /* T0 */ + txBuf[bufIt++] = atsParam->ta; /* TA */ + txBuf[bufIt++] = + ((atsParam->fwi << RFAL_ISODEP_RATS_PARAM_FSDI_SHIFT) | + (atsParam->sfgi & RFAL_ISODEP_RATS_PARAM_FSDI_MASK)); /* TB */ + txBuf[bufIt++] = (uint8_t)((atsParam->didSupport) ? RFAL_ISODEP_ATS_TC_DID : 0U); /* TC */ + + if(atsParam->hbLen > 0U) /* MISRA 21.18 */ + { + ST_MEMCPY(&txBuf[bufIt], atsParam->hb, atsParam->hbLen); /* T1-Tk */ + bufIt += atsParam->hbLen; + } + + gIsoDep.state = ISODEP_ST_PICC_ACT_ATS; + + } + /*******************************************************************************/ + else if(*buffer == RFAL_ISODEP_CMD_ATTRIB) { + /* Check ATTRIB parameters */ + if(attribResParam == NULL) { + return ERR_PARAM; + } + + /* REMARK: ATTRIB handling */ + NO_WARNING(attribResParam); + NO_WARNING(bufLen); + return ERR_NOT_IMPLEMENTED; + } else { + return ERR_PARAM; + } + + gIsoDep.actvParam = actParam; + + /*******************************************************************************/ + /* If requested copy to ISO-DEP device info */ + if(actParam.isoDepDev != NULL) { + actParam.isoDepDev->info.DID = gIsoDep.did; + actParam.isoDepDev->info.FSx = gIsoDep.fsx; + actParam.isoDepDev->info.FWT = gIsoDep.fwt; + actParam.isoDepDev->info.dFWT = 0; + actParam.isoDepDev->info.DSI = gIsoDep.txBR; + actParam.isoDepDev->info.DRI = gIsoDep.rxBR; + } + + return rfalTransceiveBlockingTx( + txBuf, + bufIt, + (uint8_t*)actParam.rxBuf, + sizeof(rfalIsoDepBufFormat), + actParam.rxLen, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_FWT_NONE); +} + +/*******************************************************************************/ +ReturnCode rfalIsoDepListenGetActivationStatus(void) { + ReturnCode err; + uint8_t* txBuf; + uint8_t bufIt; + + rfalBitRate dsi; + rfalBitRate dri; + + /* Check if Activation is running */ + if(gIsoDep.state < ISODEP_ST_PICC_ACT_ATS) { + return ERR_WRONG_STATE; + } + + /* Check if Activation has finished already */ + if(gIsoDep.state >= ISODEP_ST_PICC_RX) { + return ERR_NONE; + } + + /*******************************************************************************/ + /* Check for incoming msg */ + err = rfalGetTransceiveStatus(); + switch(err) { + /*******************************************************************************/ + case ERR_NONE: + break; + + /*******************************************************************************/ + case ERR_LINK_LOSS: + case ERR_BUSY: + return err; + + /*******************************************************************************/ + case ERR_CRC: + case ERR_PAR: + case ERR_FRAMING: + + /* ISO14443 4 5.6.2.2 2 If ATS has been replied upon a invalid block, PICC disables the PPS responses */ + if(gIsoDep.state == ISODEP_ST_PICC_ACT_ATS) { + gIsoDep.state = ISODEP_ST_PICC_RX; + break; + } + /* fall through */ + + /*******************************************************************************/ + default: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + /* ReEnable the receiver and wait for another frame */ + isoDepReEnableRx( + (uint8_t*)gIsoDep.actvParam.rxBuf, + sizeof(rfalIsoDepBufFormat), + gIsoDep.actvParam.rxLen); + + return ERR_BUSY; + } + + txBuf = + (uint8_t*)gIsoDep.actvParam + .rxBuf; /* Use the rxBuf as TxBuf as well, the struct enforces a size enough MAX(NFCA_PPS_RES_LEN, ISODEP_DSL_MAX_LEN) */ + dri = RFAL_BR_KEEP; /* The RFAL_BR_KEEP is used to check if PPS with BR change was requested */ + dsi = RFAL_BR_KEEP; /* MISRA 9.1 */ + bufIt = 0; + + /*******************************************************************************/ + gIsoDep.role = ISODEP_ROLE_PICC; + + /*******************************************************************************/ + if(gIsoDep.state == ISODEP_ST_PICC_ACT_ATS) { + /* Check for a PPS ISO 14443-4 5.3 */ + if((((uint8_t*)gIsoDep.actvParam.rxBuf)[RFAL_ISODEP_PPS_STARTBYTE_POS] & + RFAL_ISODEP_PPS_MASK) == RFAL_ISODEP_PPS_SB) { + /* ISO 14443-4 5.3.1 Check if the we are the addressed DID/CID */ + /* ISO 14443-4 5.3.2 Check for a valid PPS0 */ + if(((((uint8_t*)gIsoDep.actvParam.rxBuf)[RFAL_ISODEP_PPS_STARTBYTE_POS] & + RFAL_ISODEP_DID_MASK) != gIsoDep.did) || + ((((uint8_t*)gIsoDep.actvParam.rxBuf)[RFAL_ISODEP_PPS_PPS0_POS] & + RFAL_ISODEP_PPS0_VALID_MASK) != RFAL_ISODEP_PPS0_PPS1_NOT_PRESENT)) { + /* Invalid DID on PPS request or Invalid PPS0, reEnable the receiver and wait another frame */ + isoDepReEnableRx( + (uint8_t*)gIsoDep.actvParam.rxBuf, + sizeof(rfalIsoDepBufFormat), + gIsoDep.actvParam.rxLen); + + return ERR_BUSY; + } + + /*******************************************************************************/ + /* Check PPS1 presence */ + if(((uint8_t*)gIsoDep.actvParam.rxBuf)[RFAL_ISODEP_PPS_PPS0_POS] == + RFAL_ISODEP_PPS0_PPS1_PRESENT) { + uint8_t newdri = ((uint8_t*)gIsoDep.actvParam.rxBuf)[RFAL_ISODEP_PPS_PPS1_POS] & + RFAL_ISODEP_PPS1_DxI_MASK; /* MISRA 10.8 */ + uint8_t newdsi = (((uint8_t*)gIsoDep.actvParam.rxBuf)[RFAL_ISODEP_PPS_PPS1_POS] >> + RFAL_ISODEP_PPS1_DSI_SHIFT) & + RFAL_ISODEP_PPS1_DxI_MASK; /* MISRA 10.8 */ + /* PRQA S 4342 2 # MISRA 10.5 - Layout of enum rfalBitRate and above masks guarantee no invalid enum values to be created */ + dri = (rfalBitRate)(newdri); + dsi = (rfalBitRate)(newdsi); + + if((!(RFAL_SUPPORT_BR_CE_A_106) && + ((dsi == RFAL_BR_106) || (dri == RFAL_BR_106))) || + (!(RFAL_SUPPORT_BR_CE_A_212) && + ((dsi == RFAL_BR_212) || (dri == RFAL_BR_212))) || + (!(RFAL_SUPPORT_BR_CE_A_424) && + ((dsi == RFAL_BR_424) || (dri == RFAL_BR_424))) || + (!(RFAL_SUPPORT_BR_CE_A_848) && + ((dsi == RFAL_BR_848) || (dri == RFAL_BR_848)))) { + return ERR_PROTO; + } + } + + /*******************************************************************************/ + /* Compute and send PPS RES / Ack */ + txBuf[bufIt++] = ((uint8_t*)gIsoDep.actvParam.rxBuf)[RFAL_ISODEP_PPS_STARTBYTE_POS]; + + rfalTransceiveBlockingTx( + txBuf, + bufIt, + (uint8_t*)gIsoDep.actvParam.rxBuf, + sizeof(rfalIsoDepBufFormat), + gIsoDep.actvParam.rxLen, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_FWT_NONE); + + /*******************************************************************************/ + /* Exchange the bit rates if requested */ + if(dri != RFAL_BR_KEEP) { + rfalSetBitRate( + dsi, + dri); /* PRQA S 2880 # MISRA 2.1 - Unreachable code due to configuration option being set/unset above (RFAL_SUPPORT_BR_CE_A_xxx) */ + + gIsoDep.txBR = dsi; /* DSI codes the divisor from PICC to PCD */ + gIsoDep.rxBR = dri; /* DRI codes the divisor from PCD to PICC */ + + if(gIsoDep.actvParam.isoDepDev != NULL) { + gIsoDep.actvParam.isoDepDev->info.DSI = dsi; + gIsoDep.actvParam.isoDepDev->info.DRI = dri; + } + } + } + /* Check for a S-Deselect is done on Data Exchange Activity */ + } + + /*******************************************************************************/ + gIsoDep.hdrLen = RFAL_ISODEP_PCB_LEN; + gIsoDep.hdrLen += + RFAL_ISODEP_DID_LEN; /* Always assume DID to be aligned with Digital 1.1 15.1.2 and ISO14443 4 5.6.3 #454 */ + gIsoDep.hdrLen += (uint8_t)((gIsoDep.nad != RFAL_ISODEP_NO_NAD) ? RFAL_ISODEP_NAD_LEN : 0U); + + /*******************************************************************************/ + /* Rule C - The PICC block number shall be initialized to 1 at activation */ + gIsoDep.blockNumber = 1; + + /* Activation done, keep the rcvd data in, reMap the activation buffer to the global to be retrieved by the DEP method */ + gIsoDep.rxBuf = (uint8_t*)gIsoDep.actvParam.rxBuf; + gIsoDep.rxBufLen = sizeof(rfalIsoDepBufFormat); + gIsoDep.rxBufInfPos = (uint8_t)((uint32_t)gIsoDep.actvParam.rxBuf->inf - + (uint32_t)gIsoDep.actvParam.rxBuf->prologue); + gIsoDep.rxLen = gIsoDep.actvParam.rxLen; + gIsoDep.rxChaining = gIsoDep.actvParam.isRxChaining; + + gIsoDep.state = ISODEP_ST_PICC_RX; + return ERR_NONE; +} + +#endif /* RFAL_FEATURE_ISO_DEP_LISTEN */ + +/*******************************************************************************/ +uint16_t rfalIsoDepGetMaxInfLen(void) { + /* Check whether all parameters are valid, otherwise return minimum default value */ + if((gIsoDep.fsx < (uint16_t)RFAL_ISODEP_FSX_16) || + (gIsoDep.fsx > (uint16_t)RFAL_ISODEP_FSX_4096) || (gIsoDep.hdrLen > ISODEP_HDR_MAX_LEN)) { + uint16_t isodepFsx16 = (uint16_t)RFAL_ISODEP_FSX_16; /* MISRA 10.1 */ + return (isodepFsx16 - RFAL_ISODEP_PCB_LEN - ISODEP_CRC_LEN); + } + + return (gIsoDep.fsx - gIsoDep.hdrLen - ISODEP_CRC_LEN); +} + +/*******************************************************************************/ +ReturnCode rfalIsoDepStartTransceive(rfalIsoDepTxRxParam param) { + gIsoDep.txBuf = param.txBuf->prologue; + gIsoDep.txBufInfPos = (uint8_t)((uint32_t)param.txBuf->inf - (uint32_t)param.txBuf->prologue); + gIsoDep.txBufLen = param.txBufLen; + gIsoDep.isTxChaining = param.isTxChaining; + + gIsoDep.rxBuf = param.rxBuf->prologue; + gIsoDep.rxBufInfPos = (uint8_t)((uint32_t)param.rxBuf->inf - (uint32_t)param.rxBuf->prologue); + gIsoDep.rxBufLen = sizeof(rfalIsoDepBufFormat); + + gIsoDep.rxLen = param.rxLen; + gIsoDep.rxChaining = param.isRxChaining; + + gIsoDep.fwt = param.FWT; + gIsoDep.dFwt = param.dFWT; + gIsoDep.fsx = param.FSx; + gIsoDep.did = param.DID; + + /* Only change the FSx from activation if no to Keep */ + gIsoDep.ourFsx = ((param.ourFSx != RFAL_ISODEP_FSX_KEEP) ? param.ourFSx : gIsoDep.ourFsx); + + /* Clear inner control params for next dataExchange */ + gIsoDep.isRxChaining = false; + isoDepClearCounters(); + + if(gIsoDep.role == ISODEP_ROLE_PICC) { + if(gIsoDep.txBufLen > 0U) { + /* Ensure that an RTOX Ack is not being expected at moment */ + if(!gIsoDep.isWait4WTX) { + gIsoDep.state = ISODEP_ST_PICC_TX; + return ERR_NONE; + } else { + /* If RTOX Ack is expected, signal a pending Tx to be transmitted right after */ + gIsoDep.isTxPending = true; + } + } + + /* Digital 1.1 15.2.5.1 The first block SHALL be sent by the Reader/Writer */ + gIsoDep.state = ISODEP_ST_PICC_RX; + return ERR_NONE; + } + + gIsoDep.state = ISODEP_ST_PCD_TX; + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalIsoDepGetTransceiveStatus(void) { + if(gIsoDep.role == ISODEP_ROLE_PICC) { +#if RFAL_FEATURE_ISO_DEP_LISTEN + return isoDepDataExchangePICC(); +#else + return ERR_NOTSUPP; +#endif /* RFAL_FEATURE_ISO_DEP_LISTEN */ + } else { +#if RFAL_FEATURE_ISO_DEP_POLL + return isoDepDataExchangePCD(gIsoDep.rxLen, gIsoDep.rxChaining); +#else + return ERR_NOTSUPP; +#endif /* RFAL_FEATURE_ISO_DEP_POLL */ + } +} + +#if RFAL_FEATURE_ISO_DEP_LISTEN + +/*******************************************************************************/ +static ReturnCode isoDepDataExchangePICC(void) { + uint8_t rxPCB; + ReturnCode ret; + + switch(gIsoDep.state) { + /*******************************************************************************/ + case ISODEP_ST_IDLE: + return ERR_NONE; + + /*******************************************************************************/ + case ISODEP_ST_PICC_TX: + + ret = isoDepTx( + isoDep_PCBIBlock(gIsoDep.blockNumber), + gIsoDep.txBuf, + &gIsoDep.txBuf[gIsoDep.txBufInfPos], + gIsoDep.txBufLen, + RFAL_FWT_NONE); + + /* Clear pending Tx flag */ + gIsoDep.isTxPending = false; + + switch(ret) { + case ERR_NONE: + gIsoDep.state = ISODEP_ST_PICC_RX; + return ERR_BUSY; + + default: + /* MISRA 16.4: no empty default statement (a comment being enough) */ + break; + } + return ret; + + /*******************************************************************************/ + case ISODEP_ST_PICC_RX: + + ret = rfalGetTransceiveStatus(); + switch(ret) { + /*******************************************************************************/ + /* Data rcvd with error or timeout -> mute */ + case ERR_TIMEOUT: + case ERR_CRC: + case ERR_PAR: + case ERR_FRAMING: + + /* Digital 1.1 - 15.2.6.2 The CE SHALL NOT attempt error recovery and remains in Rx mode upon Transmission or a Protocol Error */ + isoDepReEnableRx((uint8_t*)gIsoDep.rxBuf, sizeof(rfalIsoDepBufFormat), gIsoDep.rxLen); + + return ERR_BUSY; + + /*******************************************************************************/ + case ERR_LINK_LOSS: + return ret; /* Debug purposes */ + + case ERR_BUSY: + return ret; /* Debug purposes */ + + /*******************************************************************************/ + case ERR_NONE: + *gIsoDep.rxLen = rfalConvBitsToBytes(*gIsoDep.rxLen); + break; + + /*******************************************************************************/ + default: + return ret; + } + break; + + /*******************************************************************************/ + case ISODEP_ST_PICC_SWTX: + + if(!isoDepTimerisExpired(gIsoDep.WTXTimer)) /* Do nothing until WTX timer has expired */ + { + return ERR_BUSY; + } + + /* Set waiting for WTX Ack Flag */ + gIsoDep.isWait4WTX = true; + + /* Digital 1.1 15.2.2.9 - Calculate the WTXM such that FWTtemp <= FWTmax */ + gIsoDep.lastWTXM = (uint8_t)isoDep_WTXMListenerMax(gIsoDep.fwt); + EXIT_ON_ERR(ret, isoDepHandleControlMsg(ISODEP_S_WTX, gIsoDep.lastWTXM)); + + gIsoDep.state = ISODEP_ST_PICC_RX; /* Go back to Rx to process WTX ack */ + return ERR_BUSY; + + /*******************************************************************************/ + case ISODEP_ST_PICC_SDSL: + + if(rfalIsTransceiveInRx()) /* Wait until DSL response has been sent */ + { + rfalIsoDepInitialize(); /* Session finished reInit vars */ + return ERR_SLEEP_REQ; /* Notify Deselect request */ + } + return ERR_BUSY; + + /*******************************************************************************/ + default: + return ERR_INTERNAL; + } + + /* ISO 14443-4 7.5.6.2 CE SHALL NOT attempt error recovery -> clear counters */ + isoDepClearCounters(); + + /*******************************************************************************/ + /* No error, process incoming msg */ + /*******************************************************************************/ + + /* Grab rcvd PCB */ + rxPCB = gIsoDep.rxBuf[ISODEP_PCB_POS]; + + /*******************************************************************************/ + /* When DID=0 PCD may or may not use DID, therefore check whether current PCD request + * has DID present to be reflected on max INF length #454 */ + + /* ReCalculate Header Length */ + gIsoDep.hdrLen = RFAL_ISODEP_PCB_LEN; + gIsoDep.hdrLen += (uint8_t)((isoDep_PCBhasDID(rxPCB)) ? RFAL_ISODEP_DID_LEN : 0U); + gIsoDep.hdrLen += (uint8_t)((isoDep_PCBhasNAD(rxPCB)) ? RFAL_ISODEP_NAD_LEN : 0U); + + /* Store whether last PCD block had DID. for PICC special handling of DID = 0 */ + if(gIsoDep.did == RFAL_ISODEP_DID_00) { + gIsoDep.lastDID00 = ((isoDep_PCBhasDID(rxPCB)) ? true : false); + } + + /*******************************************************************************/ + /* Check rcvd msg length, cannot be less then the expected header OR * + * if the rcvd msg exceeds our announced frame size (FSD) */ + if(((*gIsoDep.rxLen) < gIsoDep.hdrLen) || + ((*gIsoDep.rxLen) > (gIsoDep.ourFsx - ISODEP_CRC_LEN))) { + isoDepReEnableRx( + (uint8_t*)gIsoDep.actvParam.rxBuf, + sizeof(rfalIsoDepBufFormat), + gIsoDep.actvParam.rxLen); + return ERR_BUSY; /* ERR_PROTO Ignore this protocol request */ + } + + /* If we are expecting DID, check if PCB signals its presence and if device ID match OR + * If our DID=0 and DID is sent but with an incorrect value */ + if(((gIsoDep.did != RFAL_ISODEP_DID_00) && + (!isoDep_PCBhasDID(rxPCB) || (gIsoDep.did != gIsoDep.rxBuf[ISODEP_DID_POS]))) || + ((gIsoDep.did == RFAL_ISODEP_DID_00) && isoDep_PCBhasDID(rxPCB) && + (RFAL_ISODEP_DID_00 != gIsoDep.rxBuf[ISODEP_DID_POS]))) { + isoDepReEnableRx( + (uint8_t*)gIsoDep.actvParam.rxBuf, + sizeof(rfalIsoDepBufFormat), + gIsoDep.actvParam.rxLen); + return ERR_BUSY; /* Ignore a wrong DID request */ + } + + /* If we aren't expecting NAD and it's received */ + if((gIsoDep.nad == RFAL_ISODEP_NO_NAD) && isoDep_PCBhasNAD(rxPCB)) { + isoDepReEnableRx( + (uint8_t*)gIsoDep.actvParam.rxBuf, + sizeof(rfalIsoDepBufFormat), + gIsoDep.actvParam.rxLen); + return ERR_BUSY; /* Ignore a unexpected NAD request */ + } + + /*******************************************************************************/ + /* Process S-Block */ + /*******************************************************************************/ + if(isoDep_PCBisSBlock(rxPCB)) { + /* Check if is a Wait Time eXtension */ + if(isoDep_PCBisSWTX(rxPCB)) { + /* Check if we're expecting a S-WTX */ + if(isoDep_PCBisWTX(gIsoDep.lastPCB)) { + /* Digital 1.1 15.2.2.11 S(WTX) Ack with different WTXM -> Protocol Error * + * Power level indication also should be set to 0 */ + if((gIsoDep.rxBuf[gIsoDep.hdrLen] == gIsoDep.lastWTXM) && + ((*gIsoDep.rxLen - gIsoDep.hdrLen) == ISODEP_SWTX_INF_LEN)) { + /* Clear waiting for RTOX Ack Flag */ + gIsoDep.isWait4WTX = false; + + /* Check if a Tx is already pending */ + if(gIsoDep.isTxPending) { + /* Has a pending Tx, go immediately to TX */ + gIsoDep.state = ISODEP_ST_PICC_TX; + return ERR_BUSY; + } + + /* Set WTX timer */ + isoDepTimerStart( + gIsoDep.WTXTimer, + isoDep_WTXAdjust((gIsoDep.lastWTXM * rfalConv1fcToMs(gIsoDep.fwt)))); + + gIsoDep.state = ISODEP_ST_PICC_SWTX; + return ERR_BUSY; + } + } + /* Unexpected/Incorrect S-WTX, fall into reRenable */ + } + + /* Check if is a Deselect request */ + if(isoDep_PCBisSDeselect(rxPCB) && + ((*gIsoDep.rxLen - gIsoDep.hdrLen) == ISODEP_SDSL_INF_LEN)) { + EXIT_ON_ERR(ret, isoDepHandleControlMsg(ISODEP_S_DSL, RFAL_ISODEP_NO_PARAM)); + + /* S-DSL transmission ongoing, wait until complete */ + gIsoDep.state = ISODEP_ST_PICC_SDSL; + return ERR_BUSY; + } + + /* Unexpected S-Block, fall into reRenable */ + } + + /*******************************************************************************/ + /* Process R-Block */ + /*******************************************************************************/ + else if(isoDep_PCBisRBlock(rxPCB) && ((*gIsoDep.rxLen - gIsoDep.hdrLen) == ISODEP_RBLOCK_INF_LEN)) { + if(isoDep_PCBisRACK(rxPCB)) /* Check if is a R-ACK */ + { + if(isoDep_GetBN(rxPCB) == gIsoDep.blockNumber) /* Check block number */ + { + /* Rule 11 - R(ACK) with current bn -> re-transmit */ + if(!isoDep_PCBisIBlock(gIsoDep.lastPCB)) { + isoDepReSendControlMsg(); + } else { + gIsoDep.state = ISODEP_ST_PICC_TX; + } + + return ERR_BUSY; + } else { + if(!gIsoDep.isTxChaining) { + /* Rule 13 violation R(ACK) without performing chaining */ + isoDepReEnableRx( + (uint8_t*)gIsoDep.rxBuf, sizeof(rfalIsoDepBufFormat), gIsoDep.rxLen); + return ERR_BUSY; + } + + /* Rule E - R(ACK) with not current bn -> toggle bn */ + isoDep_ToggleBN(gIsoDep.blockNumber); + + /* This block has been transmitted and acknowledged, perform WTX until next data is provided */ + + /* Rule 9 - PICC is allowed to send an S(WTX) instead of an I-block or an R(ACK) */ + isoDepTimerStart(gIsoDep.WTXTimer, isoDep_WTXAdjust(rfalConv1fcToMs(gIsoDep.fwt))); + gIsoDep.state = ISODEP_ST_PICC_SWTX; + + /* Rule 13 - R(ACK) with not current bn -> continue chaining */ + return ERR_NONE; /* This block has been transmitted */ + } + } else if(isoDep_PCBisRNAK(rxPCB)) /* Check if is a R-NACK */ + { + if(isoDep_GetBN(rxPCB) == gIsoDep.blockNumber) /* Check block number */ + { + /* Rule 11 - R(NAK) with current bn -> re-transmit last x-Block */ + if(!isoDep_PCBisIBlock(gIsoDep.lastPCB)) { + isoDepReSendControlMsg(); + } else { + gIsoDep.state = ISODEP_ST_PICC_TX; + } + + return ERR_BUSY; + } else { + /* Rule 12 - R(NAK) with not current bn -> R(ACK) */ + EXIT_ON_ERR(ret, isoDepHandleControlMsg(ISODEP_R_ACK, RFAL_ISODEP_NO_PARAM)); + + return ERR_BUSY; + } + } else { + /* MISRA 15.7 - Empty else */ + } + + /* Unexpected R-Block, fall into reRenable */ + } + + /*******************************************************************************/ + /* Process I-Block */ + /*******************************************************************************/ + else if(isoDep_PCBisIBlock(rxPCB)) { + /* Rule D - When an I-block is received, the PICC shall toggle its block number before sending a block */ + isoDep_ToggleBN(gIsoDep.blockNumber); + + /*******************************************************************************/ + /* Check if the block number is the one expected */ + /* Check if PCD sent an I-Block instead ACK/NACK when we are chaining */ + if((isoDep_GetBN(rxPCB) != gIsoDep.blockNumber) || (gIsoDep.isTxChaining)) { + /* Remain in the same Block Number */ + isoDep_ToggleBN(gIsoDep.blockNumber); + + /* ISO 14443-4 7.5.6.2 & Digital 1.1 - 15.2.6.2 The CE SHALL NOT attempt error recovery and remains in Rx mode upon Transmission or a Protocol Error */ + isoDepReEnableRx((uint8_t*)gIsoDep.rxBuf, sizeof(rfalIsoDepBufFormat), gIsoDep.rxLen); + return ERR_BUSY; + } + + /*******************************************************************************/ + /* is PCD performing chaining ? */ + if(isoDep_PCBisChaining(rxPCB)) { + gIsoDep.isRxChaining = true; + *gIsoDep.rxChaining = true; /* Output Parameter*/ + + EXIT_ON_ERR(ret, isoDepHandleControlMsg(ISODEP_R_ACK, RFAL_ISODEP_NO_PARAM)); + + /* Received I-Block with chaining, send current data to DH */ + + /* remove ISO DEP header, check is necessary to move the INF data on the buffer */ + *gIsoDep.rxLen -= gIsoDep.hdrLen; + if((gIsoDep.hdrLen != gIsoDep.rxBufInfPos) && (*gIsoDep.rxLen > 0U)) { + ST_MEMMOVE( + &gIsoDep.rxBuf[gIsoDep.rxBufInfPos], + &gIsoDep.rxBuf[gIsoDep.hdrLen], + *gIsoDep.rxLen); + } + return ERR_AGAIN; /* Send Again signalling to run again, but some chaining data has arrived*/ + } + + /*******************************************************************************/ + /* PCD is not performing chaining */ + gIsoDep.isRxChaining = false; /* clear PCD chaining flag */ + *gIsoDep.rxChaining = false; /* Output Parameter */ + + /* remove ISO DEP header, check is necessary to move the INF data on the buffer */ + *gIsoDep.rxLen -= gIsoDep.hdrLen; + if((gIsoDep.hdrLen != gIsoDep.rxBufInfPos) && (*gIsoDep.rxLen > 0U)) { + ST_MEMMOVE( + &gIsoDep.rxBuf[gIsoDep.rxBufInfPos], + &gIsoDep.rxBuf[gIsoDep.hdrLen], + *gIsoDep.rxLen); + } + + /*******************************************************************************/ + /* Reception done, send data back and start WTX timer */ + isoDepTimerStart(gIsoDep.WTXTimer, isoDep_WTXAdjust(rfalConv1fcToMs(gIsoDep.fwt))); + + gIsoDep.state = ISODEP_ST_PICC_SWTX; + return ERR_NONE; + } else { + /* MISRA 15.7 - Empty else */ + } + + /* Unexpected/Unknown Block */ + /* ISO 14443-4 7.5.6.2 & Digital 1.1 - 15.2.6.2 The CE SHALL NOT attempt error recovery and remains in Rx mode upon Transmission or a Protocol Error */ + isoDepReEnableRx((uint8_t*)gIsoDep.rxBuf, sizeof(rfalIsoDepBufFormat), gIsoDep.rxLen); + + return ERR_BUSY; +} +#endif /* RFAL_FEATURE_ISO_DEP_LISTEN */ + +#if RFAL_FEATURE_ISO_DEP_POLL + +#if RFAL_FEATURE_NFCA + +/*******************************************************************************/ +static ReturnCode + rfalIsoDepStartRATS(rfalIsoDepFSxI FSDI, uint8_t DID, rfalIsoDepAts* ats, uint8_t* atsLen) { + rfalTransceiveContext ctx; + + if(ats == NULL) { + return ERR_PARAM; + } + + gIsoDep.rxBuf = (uint8_t*)ats; + gIsoDep.rxLen8 = atsLen; + gIsoDep.did = DID; + + /*******************************************************************************/ + /* Compose RATS */ + gIsoDep.actv.ratsReq.CMD = RFAL_ISODEP_CMD_RATS; + gIsoDep.actv.ratsReq.PARAM = + (((uint8_t)FSDI << RFAL_ISODEP_RATS_PARAM_FSDI_SHIFT) & RFAL_ISODEP_RATS_PARAM_FSDI_MASK) | + (DID & RFAL_ISODEP_RATS_PARAM_DID_MASK); + + rfalCreateByteFlagsTxRxContext( + ctx, + (uint8_t*)&gIsoDep.actv.ratsReq, + sizeof(rfalIsoDepRats), + (uint8_t*)ats, + sizeof(rfalIsoDepAts), + &gIsoDep.rxBufLen, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_ISODEP_T4T_FWT_ACTIVATION); + return rfalStartTransceive(&ctx); +} + +/*******************************************************************************/ +static ReturnCode rfalIsoDepGetRATSStatus(void) { + ReturnCode ret; + + ret = rfalGetTransceiveStatus(); + if(ret == ERR_NONE) { + gIsoDep.rxBufLen = rfalConvBitsToBytes(gIsoDep.rxBufLen); + + /* Check for valid ATS length Digital 1.1 13.6.2.1 & 13.6.2.3 */ + if((gIsoDep.rxBufLen < RFAL_ISODEP_ATS_MIN_LEN) || + (gIsoDep.rxBufLen > RFAL_ISODEP_ATS_MAX_LEN) || + (gIsoDep.rxBuf[RFAL_ISODEP_ATS_TL_POS] != gIsoDep.rxBufLen)) { + return ERR_PROTO; + } + + /* Assign our FSx, in case the a Deselect is send without Transceive */ + gIsoDep.ourFsx = rfalIsoDepFSxI2FSx( + (uint8_t)(gIsoDep.actv.ratsReq.PARAM >> RFAL_ISODEP_RATS_PARAM_FSDI_SHIFT)); + + /* Check and assign if ATS length was requested (length also available on TL) */ + if(gIsoDep.rxLen8 != NULL) { + *gIsoDep.rxLen8 = (uint8_t)gIsoDep.rxBufLen; + } + } + + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalIsoDepRATS(rfalIsoDepFSxI FSDI, uint8_t DID, rfalIsoDepAts* ats, uint8_t* atsLen) { + ReturnCode ret; + + EXIT_ON_ERR(ret, rfalIsoDepStartRATS(FSDI, DID, ats, atsLen)); + rfalIsoDepRunBlocking(ret, rfalIsoDepGetRATSStatus()); + + return ret; +} + +/*******************************************************************************/ +static ReturnCode + rfalIsoDepStartPPS(uint8_t DID, rfalBitRate DSI, rfalBitRate DRI, rfalIsoDepPpsRes* ppsRes) { + rfalTransceiveContext ctx; + + if((ppsRes == NULL) || (DSI > RFAL_BR_848) || (DRI > RFAL_BR_848) || + (DID > RFAL_ISODEP_DID_MAX)) { + return ERR_PARAM; + } + + gIsoDep.rxBuf = (uint8_t*)ppsRes; + + /*******************************************************************************/ + /* Compose PPS Request */ + gIsoDep.actv.ppsReq.PPSS = (RFAL_ISODEP_PPS_SB | (DID & RFAL_ISODEP_PPS_SB_DID_MASK)); + gIsoDep.actv.ppsReq.PPS0 = RFAL_ISODEP_PPS_PPS0_PPS1_PRESENT; + gIsoDep.actv.ppsReq.PPS1 = + (RFAL_ISODEP_PPS_PPS1 | + ((((uint8_t)DSI << RFAL_ISODEP_PPS_PPS1_DSI_SHIFT) | (uint8_t)DRI) & + RFAL_ISODEP_PPS_PPS1_DXI_MASK)); + + rfalCreateByteFlagsTxRxContext( + ctx, + (uint8_t*)&gIsoDep.actv.ppsReq, + sizeof(rfalIsoDepPpsReq), + (uint8_t*)ppsRes, + sizeof(rfalIsoDepPpsRes), + &gIsoDep.rxBufLen, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_ISODEP_T4T_FWT_ACTIVATION); + return rfalStartTransceive(&ctx); +} + +/*******************************************************************************/ +static ReturnCode rfalIsoDepGetPPSSTatus(void) { + ReturnCode ret; + + ret = rfalGetTransceiveStatus(); + if(ret == ERR_NONE) { + gIsoDep.rxBufLen = rfalConvBitsToBytes(gIsoDep.rxBufLen); + + /* Check for valid PPS Response */ + if((gIsoDep.rxBufLen != RFAL_ISODEP_PPS_RES_LEN) || + (*gIsoDep.rxBuf != gIsoDep.actv.ppsReq.PPSS)) { + return ERR_PROTO; + } + } + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalIsoDepPPS(uint8_t DID, rfalBitRate DSI, rfalBitRate DRI, rfalIsoDepPpsRes* ppsRes) { + ReturnCode ret; + + EXIT_ON_ERR(ret, rfalIsoDepStartPPS(DID, DSI, DRI, ppsRes)); + rfalIsoDepRunBlocking(ret, rfalIsoDepGetPPSSTatus()); + + return ret; +} + +#endif /* RFAL_FEATURE_NFCA */ + +#if RFAL_FEATURE_NFCB + +static ReturnCode rfalIsoDepStartATTRIB( + const uint8_t* nfcid0, + uint8_t PARAM1, + rfalBitRate DSI, + rfalBitRate DRI, + rfalIsoDepFSxI FSDI, + uint8_t PARAM3, + uint8_t DID, + const uint8_t* HLInfo, + uint8_t HLInfoLen, + uint32_t fwt, + rfalIsoDepAttribRes* attribRes, + uint8_t* attribResLen) { + rfalTransceiveContext ctx; + + if((attribRes == NULL) || (attribResLen == NULL) || (DSI > RFAL_BR_848) || + (DRI > RFAL_BR_848) || (DID > RFAL_ISODEP_DID_MAX)) { + return ERR_NONE; + } + + gIsoDep.rxBuf = (uint8_t*)attribRes; + gIsoDep.rxLen8 = attribResLen; + gIsoDep.did = DID; + + /*******************************************************************************/ + /* Compose ATTRIB command */ + gIsoDep.actv.attribReq.cmd = RFAL_ISODEP_CMD_ATTRIB; + gIsoDep.actv.attribReq.Param.PARAM1 = PARAM1; + gIsoDep.actv.attribReq.Param.PARAM2 = + (((((uint8_t)DSI << RFAL_ISODEP_ATTRIB_PARAM2_DSI_SHIFT) | + ((uint8_t)DRI << RFAL_ISODEP_ATTRIB_PARAM2_DRI_SHIFT)) & + RFAL_ISODEP_ATTRIB_PARAM2_DXI_MASK) | + ((uint8_t)FSDI & RFAL_ISODEP_ATTRIB_PARAM2_FSDI_MASK)); + gIsoDep.actv.attribReq.Param.PARAM3 = PARAM3; + gIsoDep.actv.attribReq.Param.PARAM4 = (DID & RFAL_ISODEP_ATTRIB_PARAM4_DID_MASK); + ST_MEMCPY(gIsoDep.actv.attribReq.nfcid0, nfcid0, RFAL_NFCB_NFCID0_LEN); + + /* Append the Higher layer Info if provided */ + if((HLInfo != NULL) && (HLInfoLen > 0U)) { + ST_MEMCPY( + gIsoDep.actv.attribReq.HLInfo, HLInfo, MIN(HLInfoLen, RFAL_ISODEP_ATTRIB_HLINFO_LEN)); + } + + rfalCreateByteFlagsTxRxContext( + ctx, + (uint8_t*)&gIsoDep.actv.attribReq, + (uint16_t)(RFAL_ISODEP_ATTRIB_HDR_LEN + + MIN((uint16_t)HLInfoLen, RFAL_ISODEP_ATTRIB_HLINFO_LEN)), + (uint8_t*)gIsoDep.rxBuf, + sizeof(rfalIsoDepAttribRes), + &gIsoDep.rxBufLen, + RFAL_TXRX_FLAGS_DEFAULT, + fwt); + return rfalStartTransceive(&ctx); +} + +/*******************************************************************************/ +static ReturnCode rfalIsoDepGetATTRIBStatus(void) { + ReturnCode ret; + + ret = rfalGetTransceiveStatus(); + if(ret == ERR_NONE) { + gIsoDep.rxBufLen = rfalConvBitsToBytes(gIsoDep.rxBufLen); + + /* Check a for valid ATTRIB Response Digital 1.1 15.6.2.1 */ + if((gIsoDep.rxBufLen < RFAL_ISODEP_ATTRIB_RES_HDR_LEN) || + ((gIsoDep.rxBuf[RFAL_ISODEP_ATTRIB_RES_MBLIDID_POS] & + RFAL_ISODEP_ATTRIB_RES_DID_MASK) != gIsoDep.did)) { + return ERR_PROTO; + } + + if(gIsoDep.rxLen8 != NULL) { + *gIsoDep.rxLen8 = (uint8_t)gIsoDep.rxBufLen; + } + + gIsoDep.ourFsx = rfalIsoDepFSxI2FSx( + (uint8_t)(gIsoDep.actv.attribReq.Param.PARAM2 & RFAL_ISODEP_ATTRIB_PARAM2_FSDI_MASK)); + } + + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalIsoDepATTRIB( + const uint8_t* nfcid0, + uint8_t PARAM1, + rfalBitRate DSI, + rfalBitRate DRI, + rfalIsoDepFSxI FSDI, + uint8_t PARAM3, + uint8_t DID, + const uint8_t* HLInfo, + uint8_t HLInfoLen, + uint32_t fwt, + rfalIsoDepAttribRes* attribRes, + uint8_t* attribResLen) { + ReturnCode ret; + + EXIT_ON_ERR( + ret, + rfalIsoDepStartATTRIB( + nfcid0, + PARAM1, + DSI, + DRI, + FSDI, + PARAM3, + DID, + HLInfo, + HLInfoLen, + fwt, + attribRes, + attribResLen)); + rfalIsoDepRunBlocking(ret, rfalIsoDepGetATTRIBStatus()); + + return ret; +} + +#endif /* RFAL_FEATURE_NFCB */ + +#if RFAL_FEATURE_NFCA + +/*******************************************************************************/ +ReturnCode rfalIsoDepPollAHandleActivation( + rfalIsoDepFSxI FSDI, + uint8_t DID, + rfalBitRate maxBR, + rfalIsoDepDevice* isoDepDev) { + ReturnCode ret; + + EXIT_ON_ERR(ret, rfalIsoDepPollAStartActivation(FSDI, DID, maxBR, isoDepDev)); + rfalIsoDepRunBlocking(ret, rfalIsoDepPollAGetActivationStatus()); + + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalIsoDepPollAStartActivation( + rfalIsoDepFSxI FSDI, + uint8_t DID, + rfalBitRate maxBR, + rfalIsoDepDevice* isoDepDev) { + ReturnCode ret; + + if(isoDepDev == NULL) { + return ERR_PARAM; + } + + /* Enable EMD handling according Digital 1.1 4.1.1.1 ; EMVCo 2.6 4.9.2 */ + rfalSetErrorHandling(RFAL_ERRORHANDLING_EMVCO); + + /* Start RATS Transceive */ + EXIT_ON_ERR( + ret, + rfalIsoDepStartRATS( + FSDI, + DID, + &isoDepDev->activation.A.Listener.ATS, + &isoDepDev->activation.A.Listener.ATSLen)); + + isoDepDev->info.DSI = maxBR; + gIsoDep.actvDev = isoDepDev; + gIsoDep.cntRRetrys = gIsoDep.maxRetriesRATS; + gIsoDep.state = ISODEP_ST_PCD_ACT_RATS; + + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalIsoDepPollAGetActivationStatus(void) { + ReturnCode ret; + uint8_t msgIt; + rfalBitRate maxBR; + + switch(gIsoDep.state) { + /*******************************************************************************/ + case ISODEP_ST_PCD_ACT_RATS: + + ret = rfalIsoDepGetRATSStatus(); + if(ret != ERR_BUSY) { + if(ret != ERR_NONE) { + /* EMVCo 2.6 9.6.1.1 & 9.6.1.2 If a timeout error is detected retransmit, on transmission error abort */ + if((gIsoDep.compMode == RFAL_COMPLIANCE_MODE_EMV) && (ret != ERR_TIMEOUT)) { + break; + } + + if(gIsoDep.cntRRetrys != 0U) { + /* Ensure FDT before retransmission (reuse RFAL GT timer) */ + rfalSetGT(rfalGetFDTPoll()); + rfalFieldOnAndStartGT(); + + /* Send RATS retransmission */ /* PRQA S 4342 1 # MISRA 10.5 - Layout of enum rfalIsoDepFSxI is guaranteed within 4bit range */ + EXIT_ON_ERR( + ret, + rfalIsoDepStartRATS( + (rfalIsoDepFSxI)(uint8_t)(gIsoDep.actv.ratsReq.PARAM >> + RFAL_ISODEP_RATS_PARAM_FSDI_SHIFT), + gIsoDep.did, + &gIsoDep.actvDev->activation.A.Listener.ATS, + &gIsoDep.actvDev->activation.A.Listener.ATSLen)); + gIsoDep.cntRRetrys--; + ret = ERR_BUSY; + } + /* Switch between NFC Forum and ISO14443-4 behaviour #595 + * ISO14443-4 5.6.1 If RATS fails, a Deactivation sequence should be performed as defined on clause 8 + * Activity 1.1 9.6 Device Deactivation Activity is to be only performed when there's an active device */ + else if(gIsoDep.compMode == RFAL_COMPLIANCE_MODE_ISO) { + rfalIsoDepDeselect(); + } else { + /* MISRA 15.7 - Empty else */ + } + } else /* ATS received */ + { + maxBR = gIsoDep.actvDev->info.DSI; /* Retrieve requested max bitrate */ + + /*******************************************************************************/ + /* Process ATS Response */ + gIsoDep.actvDev->info.FWI = + RFAL_ISODEP_FWI_DEFAULT; /* Default value EMVCo 2.6 5.7.2.6 */ + gIsoDep.actvDev->info.SFGI = 0U; + gIsoDep.actvDev->info.MBL = 0U; + gIsoDep.actvDev->info.DSI = RFAL_BR_106; + gIsoDep.actvDev->info.DRI = RFAL_BR_106; + gIsoDep.actvDev->info.FSxI = (uint8_t) + RFAL_ISODEP_FSXI_32; /* FSC default value is 32 bytes ISO14443-A 5.2.3 */ + + /*******************************************************************************/ + /* Check for ATS optional fields */ + if(gIsoDep.actvDev->activation.A.Listener.ATS.TL > RFAL_ISODEP_ATS_MIN_LEN) { + msgIt = RFAL_ISODEP_ATS_MIN_LEN; + + /* Format byte T0 is optional, if present assign FSDI */ + gIsoDep.actvDev->info.FSxI = + (gIsoDep.actvDev->activation.A.Listener.ATS.T0 & + RFAL_ISODEP_ATS_T0_FSCI_MASK); + + /* T0 has already been processed, always the same position */ + msgIt++; + + /* Check if TA is present */ + if((gIsoDep.actvDev->activation.A.Listener.ATS.T0 & + RFAL_ISODEP_ATS_T0_TA_PRESENCE_MASK) != 0U) { + rfalIsoDepCalcBitRate( + maxBR, + ((uint8_t*)&gIsoDep.actvDev->activation.A.Listener.ATS)[msgIt++], + &gIsoDep.actvDev->info.DSI, + &gIsoDep.actvDev->info.DRI); + } + + /* Check if TB is present */ + if((gIsoDep.actvDev->activation.A.Listener.ATS.T0 & + RFAL_ISODEP_ATS_T0_TB_PRESENCE_MASK) != 0U) { + gIsoDep.actvDev->info.SFGI = + ((uint8_t*)&gIsoDep.actvDev->activation.A.Listener.ATS)[msgIt++]; + gIsoDep.actvDev->info.FWI = (uint8_t)((gIsoDep.actvDev->info.SFGI >> + RFAL_ISODEP_ATS_TB_FWI_SHIFT) & + RFAL_ISODEP_ATS_FWI_MASK); + gIsoDep.actvDev->info.SFGI &= RFAL_ISODEP_ATS_TB_SFGI_MASK; + } + + /* Check if TC is present */ + if((gIsoDep.actvDev->activation.A.Listener.ATS.T0 & + RFAL_ISODEP_ATS_T0_TC_PRESENCE_MASK) != 0U) { + /* Check for Protocol features support */ + /* Advanced protocol features defined on Digital 1.0 Table 69, removed after */ + gIsoDep.actvDev->info.supAdFt = + (((((uint8_t*)&gIsoDep.actvDev->activation.A.Listener.ATS)[msgIt] & + RFAL_ISODEP_ATS_TC_ADV_FEAT) != 0U) ? + true : + false); + gIsoDep.actvDev->info.supDID = + (((((uint8_t*)&gIsoDep.actvDev->activation.A.Listener.ATS)[msgIt] & + RFAL_ISODEP_ATS_TC_DID) != 0U) ? + true : + false); + gIsoDep.actvDev->info.supNAD = + (((((uint8_t*)&gIsoDep.actvDev->activation.A.Listener.ATS)[msgIt++] & + RFAL_ISODEP_ATS_TC_NAD) != 0U) ? + true : + false); + } + } + + gIsoDep.actvDev->info.FSx = rfalIsoDepFSxI2FSx(gIsoDep.actvDev->info.FSxI); + gIsoDep.fsx = gIsoDep.actvDev->info.FSx; + + gIsoDep.actvDev->info.SFGT = + rfalIsoDepSFGI2SFGT((uint8_t)gIsoDep.actvDev->info.SFGI); + + /* Ensure SFGT before following frame (reuse RFAL GT timer) */ + rfalSetGT(rfalConvMsTo1fc(gIsoDep.actvDev->info.SFGT)); + rfalFieldOnAndStartGT(); + + gIsoDep.actvDev->info.FWT = rfalIsoDepFWI2FWT(gIsoDep.actvDev->info.FWI); + gIsoDep.actvDev->info.dFWT = RFAL_ISODEP_DFWT_20; + + gIsoDep.actvDev->info.DID = + ((gIsoDep.actvDev->info.supDID) ? gIsoDep.did : RFAL_ISODEP_NO_DID); + gIsoDep.actvDev->info.NAD = RFAL_ISODEP_NO_NAD; + + /*******************************************************************************/ + /* If higher bit rates are supported by both devices, send PPS */ + if((gIsoDep.actvDev->info.DSI != RFAL_BR_106) || + (gIsoDep.actvDev->info.DRI != RFAL_BR_106)) { + /* Send PPS */ /* PRQA S 0310 1 # MISRA 11.3 - Intentional safe cast to avoiding buffer duplication */ + EXIT_ON_ERR( + ret, + rfalIsoDepStartPPS( + gIsoDep.actvDev->info.DID, + gIsoDep.actvDev->info.DSI, + gIsoDep.actvDev->info.DRI, + (rfalIsoDepPpsRes*)&gIsoDep.ctrlBuf)); + + gIsoDep.state = ISODEP_ST_PCD_ACT_PPS; + return ERR_BUSY; + } + + return ERR_NONE; + } + } + break; + + /*******************************************************************************/ + case ISODEP_ST_PCD_ACT_PPS: + ret = rfalIsoDepGetPPSSTatus(); + if(ret != ERR_BUSY) { + /* Check whether PPS has been acknowledge */ + if(ret == ERR_NONE) { + /* DSI code the divisor from PICC to PCD */ + /* DRI code the divisor from PCD to PICC */ + rfalSetBitRate(gIsoDep.actvDev->info.DRI, gIsoDep.actvDev->info.DSI); + } else { + /* If PPS has faled keep activation bit rate */ + gIsoDep.actvDev->info.DSI = RFAL_BR_106; + gIsoDep.actvDev->info.DRI = RFAL_BR_106; + } + } + break; + + /*******************************************************************************/ + default: + ret = ERR_WRONG_STATE; + break; + } + + return ret; +} +#endif /* RFAL_FEATURE_NFCA */ + +#if RFAL_FEATURE_NFCB + +/*******************************************************************************/ +ReturnCode rfalIsoDepPollBHandleActivation( + rfalIsoDepFSxI FSDI, + uint8_t DID, + rfalBitRate maxBR, + uint8_t PARAM1, + const rfalNfcbListenDevice* nfcbDev, + const uint8_t* HLInfo, + uint8_t HLInfoLen, + rfalIsoDepDevice* isoDepDev) { + ReturnCode ret; + + EXIT_ON_ERR( + ret, + rfalIsoDepPollBStartActivation( + FSDI, DID, maxBR, PARAM1, nfcbDev, HLInfo, HLInfoLen, isoDepDev)); + rfalIsoDepRunBlocking(ret, rfalIsoDepPollBGetActivationStatus()); + + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalIsoDepPollBStartActivation( + rfalIsoDepFSxI FSDI, + uint8_t DID, + rfalBitRate maxBR, + uint8_t PARAM1, + const rfalNfcbListenDevice* nfcbDev, + const uint8_t* HLInfo, + uint8_t HLInfoLen, + rfalIsoDepDevice* isoDepDev) { + ReturnCode ret; + + /***************************************************************************/ + /* Initialize ISO-DEP Device with info from SENSB_RES */ + isoDepDev->info.FWI = + ((nfcbDev->sensbRes.protInfo.FwiAdcFo >> RFAL_NFCB_SENSB_RES_FWI_SHIFT) & + RFAL_NFCB_SENSB_RES_FWI_MASK); + isoDepDev->info.FWT = rfalIsoDepFWI2FWT(isoDepDev->info.FWI); + isoDepDev->info.dFWT = RFAL_NFCB_DFWT; + isoDepDev->info.SFGI = + (((uint32_t)nfcbDev->sensbRes.protInfo.SFGI >> RFAL_NFCB_SENSB_RES_SFGI_SHIFT) & + RFAL_NFCB_SENSB_RES_SFGI_MASK); + isoDepDev->info.SFGT = rfalIsoDepSFGI2SFGT((uint8_t)isoDepDev->info.SFGI); + isoDepDev->info.FSxI = + ((nfcbDev->sensbRes.protInfo.FsciProType >> RFAL_NFCB_SENSB_RES_FSCI_SHIFT) & + RFAL_NFCB_SENSB_RES_FSCI_MASK); + isoDepDev->info.FSx = rfalIsoDepFSxI2FSx(isoDepDev->info.FSxI); + isoDepDev->info.DID = DID; + isoDepDev->info.supDID = + (((nfcbDev->sensbRes.protInfo.FwiAdcFo & RFAL_NFCB_SENSB_RES_FO_DID_MASK) != 0U) ? true : + false); + isoDepDev->info.supNAD = + (((nfcbDev->sensbRes.protInfo.FwiAdcFo & RFAL_NFCB_SENSB_RES_FO_NAD_MASK) != 0U) ? true : + false); + + /* Check if DID requested is supported by PICC */ + if((DID != RFAL_ISODEP_NO_DID) && (!isoDepDev->info.supDID)) { + return ERR_PARAM; + } + + /* Enable EMD handling according Digital 2.1 4.1.1.1 ; EMVCo 3.0 4.9.2 */ + rfalSetErrorHandling(RFAL_ERRORHANDLING_EMVCO); + + /***************************************************************************/ + /* Set FDT Poll to be used on upcoming communications */ + if(gIsoDep.compMode == RFAL_COMPLIANCE_MODE_EMV) { + /* Disregard Minimum TR2 returned by PICC, always use FDTb MIN EMVCo 3.0 6.3.2.10 */ + rfalSetFDTPoll(RFAL_FDT_POLL_NFCB_POLLER); + } else { + /* Apply minimum TR2 from SENSB_RES Digital 2.1 7.6.2.23 */ + rfalSetFDTPoll(rfalNfcbTR2ToFDT( + ((nfcbDev->sensbRes.protInfo.FsciProType >> RFAL_NFCB_SENSB_RES_PROTO_TR2_SHIFT) & + RFAL_NFCB_SENSB_RES_PROTO_TR2_MASK))); + } + + /* Calculate max Bit Rate */ + rfalIsoDepCalcBitRate( + maxBR, nfcbDev->sensbRes.protInfo.BRC, &isoDepDev->info.DSI, &isoDepDev->info.DRI); + + /***************************************************************************/ + /* Send ATTRIB Command */ + EXIT_ON_ERR( + ret, + rfalIsoDepStartATTRIB( + (const uint8_t*)&nfcbDev->sensbRes.nfcid0, + (((nfcbDev->sensbRes.protInfo.FwiAdcFo & RFAL_NFCB_SENSB_RES_ADC_ADV_FEATURE_MASK) != + 0U) ? + PARAM1 : + RFAL_ISODEP_ATTRIB_REQ_PARAM1_DEFAULT), + isoDepDev->info.DSI, + isoDepDev->info.DRI, + FSDI, + (gIsoDep.compMode == RFAL_COMPLIANCE_MODE_EMV) ? + RFAL_NFCB_SENSB_RES_PROTO_ISO_MASK : + (nfcbDev->sensbRes.protInfo.FsciProType & + ((RFAL_NFCB_SENSB_RES_PROTO_TR2_MASK << RFAL_NFCB_SENSB_RES_PROTO_TR2_SHIFT) | + RFAL_NFCB_SENSB_RES_PROTO_ISO_MASK)), /* EMVCo 2.6 6.4.1.9 */ + DID, + HLInfo, + HLInfoLen, + (isoDepDev->info.FWT + isoDepDev->info.dFWT), + &isoDepDev->activation.B.Listener.ATTRIB_RES, + &isoDepDev->activation.B.Listener.ATTRIB_RESLen)); + + gIsoDep.actvDev = isoDepDev; + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalIsoDepPollBGetActivationStatus(void) { + ReturnCode ret; + uint8_t mbli; + + /***************************************************************************/ + /* Process ATTRIB Response */ + ret = rfalIsoDepGetATTRIBStatus(); + if(ret != ERR_BUSY) { + if(ret == ERR_NONE) { + /* Digital 1.1 14.6.2.3 - Check if received DID match */ + if((gIsoDep.actvDev->activation.B.Listener.ATTRIB_RES.mbliDid & + RFAL_ISODEP_ATTRIB_RES_DID_MASK) != gIsoDep.did) { + return ERR_PROTO; + } + + /* Retrieve MBLI and calculate new FDS/MBL (Maximum Buffer Length) */ + mbli = + ((gIsoDep.actvDev->activation.B.Listener.ATTRIB_RES.mbliDid >> + RFAL_ISODEP_ATTRIB_RES_MBLI_SHIFT) & + RFAL_ISODEP_ATTRIB_RES_MBLI_MASK); + if(mbli > 0U) { + /* Digital 1.1 14.6.2 Calculate Maximum Buffer Length MBL = FSC x 2^(MBLI-1) */ + gIsoDep.actvDev->info.MBL = + (gIsoDep.actvDev->info.FSx * ((uint32_t)1U << (mbli - 1U))); + } + + /* DSI code the divisor from PICC to PCD */ + /* DRI code the divisor from PCD to PICC */ + rfalSetBitRate(gIsoDep.actvDev->info.DRI, gIsoDep.actvDev->info.DSI); + + /* REMARK: SoF EoF TR0 and TR1 are not passed on to RF layer */ + + /* Start the SFGT timer (reuse RFAL GT timer) */ + rfalSetGT(rfalConvMsTo1fc(gIsoDep.actvDev->info.SFGT)); + rfalFieldOnAndStartGT(); + } else { + gIsoDep.actvDev->info.DSI = RFAL_BR_106; + gIsoDep.actvDev->info.DRI = RFAL_BR_106; + } + + /*******************************************************************************/ + /* Store already FS info, rfalIsoDepGetMaxInfLen() may be called before setting TxRx params */ + gIsoDep.fsx = gIsoDep.actvDev->info.FSx; + } + + return ret; +} + +#endif /* RFAL_FEATURE_NFCB */ + +/*******************************************************************************/ +ReturnCode rfalIsoDepPollHandleSParameters( + rfalIsoDepDevice* isoDepDev, + rfalBitRate maxTxBR, + rfalBitRate maxRxBR) { + uint8_t it; + uint8_t supPCD2PICC; + uint8_t supPICC2PCD; + uint8_t currenttxBR; + uint8_t currentrxBR; + rfalBitRate txBR; + rfalBitRate rxBR; + uint16_t rcvLen; + ReturnCode ret; + rfalIsoDepControlMsgSParam sParam; + + if((isoDepDev == NULL) || (maxTxBR > RFAL_BR_13560) || (maxRxBR > RFAL_BR_13560)) { + return ERR_PARAM; + } + + it = 0; + supPICC2PCD = 0x00; + supPCD2PICC = 0x00; + txBR = RFAL_BR_106; + rxBR = RFAL_BR_106; + sParam.pcb = ISODEP_PCB_SPARAMETERS; + + /*******************************************************************************/ + /* Send S(PARAMETERS) - Block Info */ + sParam.sParam.tag = RFAL_ISODEP_SPARAM_TAG_BLOCKINFO; + sParam.sParam.value[it++] = RFAL_ISODEP_SPARAM_TAG_BRREQ; + sParam.sParam.value[it++] = RFAL_ISODEP_SPARAM_TAG_BRREQ_LEN; + sParam.sParam.length = it; + + /* Send S(PARAMETERS). Use a fixed FWI of 4 ISO14443-4 2016 7.2 */ + EXIT_ON_ERR( + ret, + rfalTransceiveBlockingTxRx( + (uint8_t*)&sParam, + (RFAL_ISODEP_SPARAM_HDR_LEN + (uint16_t)it), + (uint8_t*)&sParam, + sizeof(rfalIsoDepControlMsgSParam), + &rcvLen, + RFAL_TXRX_FLAGS_DEFAULT, + ISODEP_FWT_DEACTIVATION)); + + it = 0; + + /*******************************************************************************/ + /* Check S(PARAMETERS) response */ + if((sParam.pcb != ISODEP_PCB_SPARAMETERS) || + (sParam.sParam.tag != RFAL_ISODEP_SPARAM_TAG_BLOCKINFO) || + (sParam.sParam.value[it] != RFAL_ISODEP_SPARAM_TAG_BRIND) || + (rcvLen < RFAL_ISODEP_SPARAM_HDR_LEN) || + (rcvLen != ((uint16_t)sParam.sParam.length + RFAL_ISODEP_SPARAM_HDR_LEN))) { + return ERR_PROTO; + } + + /* Retrieve PICC's bit rate PICC capabilities */ + for(it = 0; it < (rcvLen - (uint16_t)RFAL_ISODEP_SPARAM_TAG_LEN); it++) { + if((sParam.sParam.value[it] == RFAL_ISODEP_SPARAM_TAG_SUP_PCD2PICC) && + (sParam.sParam.value[it + (uint16_t)RFAL_ISODEP_SPARAM_TAG_LEN] == + RFAL_ISODEP_SPARAM_TAG_PCD2PICC_LEN)) { + supPCD2PICC = sParam.sParam.value[it + RFAL_ISODEP_SPARAM_TAG_PCD2PICC_LEN]; + } + + if((sParam.sParam.value[it] == RFAL_ISODEP_SPARAM_TAG_SUP_PICC2PCD) && + (sParam.sParam.value[it + (uint16_t)RFAL_ISODEP_SPARAM_TAG_LEN] == + RFAL_ISODEP_SPARAM_TAG_PICC2PCD_LEN)) { + supPICC2PCD = sParam.sParam.value[it + RFAL_ISODEP_SPARAM_TAG_PICC2PCD_LEN]; + } + } + + /*******************************************************************************/ + /* Check if requested bit rates are supported by PICC */ + if((supPICC2PCD == 0x00U) || (supPCD2PICC == 0x00U)) { + return ERR_PROTO; + } + + for(it = 0; it <= (uint8_t)maxTxBR; it++) { + if((supPCD2PICC & (0x01U << it)) != 0U) { + txBR = (rfalBitRate) + it; /* PRQA S 4342 # MISRA 10.5 - Layout of enum rfalBitRate and above clamping of maxTxBR guarantee no invalid enum values to be created */ + } + } + for(it = 0; it <= (uint8_t)maxRxBR; it++) { + if((supPICC2PCD & (0x01U << it)) != 0U) { + rxBR = (rfalBitRate) + it; /* PRQA S 4342 # MISRA 10.5 - Layout of enum rfalBitRate and above clamping of maxTxBR guarantee no invalid enum values to be created */ + } + } + + it = 0; + currenttxBR = (uint8_t)txBR; + currentrxBR = (uint8_t)rxBR; + + /*******************************************************************************/ + /* Send S(PARAMETERS) - Bit rates Activation */ + sParam.sParam.tag = RFAL_ISODEP_SPARAM_TAG_BLOCKINFO; + sParam.sParam.value[it++] = RFAL_ISODEP_SPARAM_TAG_BRACT; + sParam.sParam.value[it++] = + (RFAL_ISODEP_SPARAM_TVL_HDR_LEN + RFAL_ISODEP_SPARAM_TAG_PCD2PICC_LEN + + RFAL_ISODEP_SPARAM_TVL_HDR_LEN + RFAL_ISODEP_SPARAM_TAG_PICC2PCD_LEN); + sParam.sParam.value[it++] = RFAL_ISODEP_SPARAM_TAG_SEL_PCD2PICC; + sParam.sParam.value[it++] = RFAL_ISODEP_SPARAM_TAG_PCD2PICC_LEN; + sParam.sParam.value[it++] = ((uint8_t)0x01U << currenttxBR); + sParam.sParam.value[it++] = 0x00U; + sParam.sParam.value[it++] = RFAL_ISODEP_SPARAM_TAG_SEL_PICC2PCD; + sParam.sParam.value[it++] = RFAL_ISODEP_SPARAM_TAG_PICC2PCD_LEN; + sParam.sParam.value[it++] = ((uint8_t)0x01U << currentrxBR); + sParam.sParam.value[it++] = 0x00U; + sParam.sParam.length = it; + + EXIT_ON_ERR( + ret, + rfalTransceiveBlockingTxRx( + (uint8_t*)&sParam, + (RFAL_ISODEP_SPARAM_HDR_LEN + (uint16_t)it), + (uint8_t*)&sParam, + sizeof(rfalIsoDepControlMsgSParam), + &rcvLen, + RFAL_TXRX_FLAGS_DEFAULT, + (isoDepDev->info.FWT + isoDepDev->info.dFWT))); + + it = 0; + + /*******************************************************************************/ + /* Check S(PARAMETERS) Acknowledge */ + if((sParam.pcb != ISODEP_PCB_SPARAMETERS) || + (sParam.sParam.tag != RFAL_ISODEP_SPARAM_TAG_BLOCKINFO) || + (sParam.sParam.value[it] != RFAL_ISODEP_SPARAM_TAG_BRACK) || + (rcvLen < RFAL_ISODEP_SPARAM_HDR_LEN)) { + return ERR_PROTO; + } + + EXIT_ON_ERR(ret, rfalSetBitRate(txBR, rxBR)); + + isoDepDev->info.DRI = txBR; + isoDepDev->info.DSI = rxBR; + + return ERR_NONE; +} + +/*******************************************************************************/ +static void rfalIsoDepCalcBitRate( + rfalBitRate maxAllowedBR, + uint8_t piccBRCapability, + rfalBitRate* dsi, + rfalBitRate* dri) { + uint8_t driMask; + uint8_t dsiMask; + int8_t i; + bool bitrateFound; + rfalBitRate curMaxBR; + + curMaxBR = maxAllowedBR; + + do { + bitrateFound = true; + + (*dsi) = RFAL_BR_106; + (*dri) = RFAL_BR_106; + + /* Digital 1.0 5.6.2.5 & 11.6.2.14: A received RFU value of b4 = 1b MUST be interpreted as if b7 to b1 ? 0000000b (only 106 kbits/s in both direction) */ + if(((RFAL_ISODEP_BITRATE_RFU_MASK & piccBRCapability) != 0U) || (curMaxBR > RFAL_BR_848) || + (curMaxBR == RFAL_BR_KEEP)) { + return; + } + + /***************************************************************************/ + /* Determine Listen->Poll bit rate */ + dsiMask = (piccBRCapability & RFAL_ISODEP_BSI_MASK); + for(i = 2; i >= 0; i--) // Check supported bit rate from the highest + { + if(((dsiMask & (0x10U << (uint8_t)i)) != 0U) && + (((uint8_t)i + 1U) <= (uint8_t)curMaxBR)) { + uint8_t newdsi = ((uint8_t)i) + 1U; + (*dsi) = (rfalBitRate) + newdsi; /* PRQA S 4342 # MISRA 10.5 - Layout of enum rfalBitRate and range of loop variable guarantee no invalid enum values to be created */ + break; + } + } + + /***************************************************************************/ + /* Determine Poll->Listen bit rate */ + driMask = (piccBRCapability & RFAL_ISODEP_BRI_MASK); + for(i = 2; i >= 0; i--) /* Check supported bit rate from the highest */ + { + if(((driMask & (0x01U << (uint8_t)i)) != 0U) && + (((uint8_t)i + 1U) <= (uint8_t)curMaxBR)) { + uint8_t newdri = ((uint8_t)i) + 1U; + (*dri) = (rfalBitRate) + newdri; /* PRQA S 4342 # MISRA 10.5 - Layout of enum rfalBitRate and range of loop variable guarantee no invalid enum values to be created */ + break; + } + } + + /***************************************************************************/ + /* Check if different bit rate is supported */ + + /* Digital 1.0 Table 67: if b8=1b, then only the same bit rate divisor for both directions is supported */ + if((piccBRCapability & RFAL_ISODEP_SAME_BITRATE_MASK) != 0U) { + (*dsi) = MIN((*dsi), (*dri)); + (*dri) = (*dsi); + /* Check that the baudrate is supported */ + if((RFAL_BR_106 != (*dsi)) && + (!(((dsiMask & (0x10U << ((uint8_t)(*dsi) - 1U))) != 0U) && + ((driMask & (0x01U << ((uint8_t)(*dri) - 1U))) != 0U)))) { + bitrateFound = false; + curMaxBR = + (*dsi); /* set allowed bitrate to be lowest and determine bit rate again */ + } + } + } while(!(bitrateFound)); +} + +/*******************************************************************************/ +static uint32_t rfalIsoDepSFGI2SFGT(uint8_t sfgi) { + uint32_t sfgt; + uint8_t tmpSFGI; + + tmpSFGI = sfgi; + + if(tmpSFGI > ISODEP_SFGI_MAX) { + tmpSFGI = ISODEP_SFGI_MIN; + } + + if(tmpSFGI != ISODEP_SFGI_MIN) { + /* If sfgi != 0 wait SFGT + dSFGT Digital 1.1 13.8.2.1 */ + sfgt = isoDepCalcSGFT(sfgi) + isoDepCalcdSGFT(sfgi); + } + /* Otherwise use FDTPoll min Digital 1.1 13.8.2.3*/ + else { + sfgt = RFAL_FDT_POLL_NFCA_POLLER; + } + + /* Convert carrier cycles to milli seconds */ + return (rfalConv1fcToMs(sfgt) + 1U); +} + +#endif /* RFAL_FEATURE_ISO_DEP_POLL */ + +/*******************************************************************************/ +static void rfalIsoDepApdu2IBLockParam( + rfalIsoDepApduTxRxParam apduParam, + rfalIsoDepTxRxParam* iBlockParam, + uint16_t txPos, + uint16_t rxPos) { + NO_WARNING(rxPos); /* Keep this param for future use */ + + iBlockParam->DID = apduParam.DID; + iBlockParam->FSx = apduParam.FSx; + iBlockParam->ourFSx = apduParam.ourFSx; + iBlockParam->FWT = apduParam.FWT; + iBlockParam->dFWT = apduParam.dFWT; + + if((apduParam.txBufLen - txPos) > rfalIsoDepGetMaxInfLen()) { + iBlockParam->isTxChaining = true; + iBlockParam->txBufLen = rfalIsoDepGetMaxInfLen(); + } else { + iBlockParam->isTxChaining = false; + iBlockParam->txBufLen = (apduParam.txBufLen - txPos); + } + + /* TxBuf is moved to the beginning for every I-Block */ + iBlockParam->txBuf = + (rfalIsoDepBufFormat*)apduParam + .txBuf; /* PRQA S 0310 # MISRA 11.3 - Intentional safe cast to avoiding large buffer duplication */ + iBlockParam->rxBuf = + apduParam + .tmpBuf; /* Simply using the apdu buffer is not possible because of current ACK handling */ + iBlockParam->isRxChaining = &gIsoDep.isAPDURxChaining; + iBlockParam->rxLen = apduParam.rxLen; +} + +/*******************************************************************************/ +ReturnCode rfalIsoDepStartApduTransceive(rfalIsoDepApduTxRxParam param) { + rfalIsoDepTxRxParam txRxParam; + + /* Initialize and store APDU context */ + gIsoDep.APDUParam = param; + gIsoDep.APDUTxPos = 0; + gIsoDep.APDURxPos = 0; + + /* Assign current FSx to calculate INF length (only change the FSx from activation if no to Keep) */ + gIsoDep.ourFsx = ((param.ourFSx != RFAL_ISODEP_FSX_KEEP) ? param.ourFSx : gIsoDep.ourFsx); + gIsoDep.fsx = param.FSx; + + /* Convert APDU TxRxParams to I-Block TxRxParams */ + rfalIsoDepApdu2IBLockParam( + gIsoDep.APDUParam, &txRxParam, gIsoDep.APDUTxPos, gIsoDep.APDURxPos); + + return rfalIsoDepStartTransceive(txRxParam); +} + +/*******************************************************************************/ +ReturnCode rfalIsoDepGetApduTransceiveStatus(void) { + ReturnCode ret; + rfalIsoDepTxRxParam txRxParam; + + ret = rfalIsoDepGetTransceiveStatus(); + switch(ret) { + /*******************************************************************************/ + case ERR_NONE: + + /* Check if we are still doing chaining on Tx */ + if(gIsoDep.isTxChaining) { + /* Add already Tx bytes */ + gIsoDep.APDUTxPos += gIsoDep.txBufLen; + + /* Convert APDU TxRxParams to I-Block TxRxParams */ + rfalIsoDepApdu2IBLockParam( + gIsoDep.APDUParam, &txRxParam, gIsoDep.APDUTxPos, gIsoDep.APDURxPos); + + if(txRxParam.txBufLen > 0U) /* MISRA 21.18 */ + { + /* Move next I-Block to beginning of APDU Tx buffer */ + ST_MEMCPY( + gIsoDep.APDUParam.txBuf->apdu, + &gIsoDep.APDUParam.txBuf->apdu[gIsoDep.APDUTxPos], + txRxParam.txBufLen); + } + + EXIT_ON_ERR(ret, rfalIsoDepStartTransceive(txRxParam)); + return ERR_BUSY; + } + + /* APDU TxRx is done */ + /* fall through */ + + /*******************************************************************************/ + case ERR_AGAIN: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + + /* Check if no APDU transceive has been started before (data from rfalIsoDepListenStartActivation) */ + if(gIsoDep.APDUParam.rxLen == NULL) { + if(ret == ERR_AGAIN) { + /* In Listen mode first chained packet cannot be retrieved via APDU interface */ + return ERR_NOTSUPP; + } + + /* TxRx is complete and full data is already available */ + return ERR_NONE; + } + + if(*gIsoDep.APDUParam.rxLen > 0U) /* MISRA 21.18 */ + { + /* Ensure that data in tmpBuf still fits into APDU buffer */ + if((gIsoDep.APDURxPos + (*gIsoDep.APDUParam.rxLen)) > + (uint16_t)RFAL_FEATURE_ISO_DEP_APDU_MAX_LEN) { + return ERR_NOMEM; + } + + /* Copy chained packet from tmp buffer to APDU buffer */ + ST_MEMCPY( + &gIsoDep.APDUParam.rxBuf->apdu[gIsoDep.APDURxPos], + gIsoDep.APDUParam.tmpBuf->inf, + *gIsoDep.APDUParam.rxLen); + gIsoDep.APDURxPos += *gIsoDep.APDUParam.rxLen; + } + + /* Update output param rxLen */ + *gIsoDep.APDUParam.rxLen = gIsoDep.APDURxPos * 8; + + /* Wait for following I-Block or APDU TxRx has finished */ + return ((ret == ERR_AGAIN) ? ERR_BUSY : ERR_NONE); + + /*******************************************************************************/ + default: + /* MISRA 16.4: no empty default statement (a comment being enough) */ + break; + } + + return ret; +} + +#endif /* RFAL_FEATURE_ISO_DEP */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_nfc.c b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_nfc.c new file mode 100644 index 00000000000..7c5fa8af266 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_nfc.c @@ -0,0 +1,2126 @@ +/** + ****************************************************************************** + * + * COPYRIGHT(c) 2020 STMicroelectronics + * + * 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 STMicroelectronics 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 rfal_nfc.c + * + * \author Gustavo Patricio + * + * \brief RFAL NFC device + * + * This module provides the required features to behave as an NFC Poller + * or Listener device. It grants an easy to use interface for the following + * activities: Technology Detection, Collision Resollution, Activation, + * Data Exchange, and Deactivation + * + * This layer is influenced by (but not fully aligned with) the NFC Forum + * specifications, in particular: Activity 2.0 and NCI 2.0 + * + */ + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "../include/rfal_nfc.h" +#include "../utils.h" +#include "../include/rfal_analogConfig.h" + +/* +****************************************************************************** +* GLOBAL DEFINES +****************************************************************************** +*/ +#define RFAL_NFC_MAX_DEVICES 5U /* Max number of devices supported */ + +/* +****************************************************************************** +* GLOBAL MACROS +****************************************************************************** +*/ + +#define rfalNfcNfcNotify(st) \ + if(gNfcDev.disc.notifyCb != NULL) gNfcDev.disc.notifyCb(st) + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + +/*! Buffer union, only one interface is used at a time */ +typedef union { /* PRQA S 0750 # MISRA 19.2 - Members of the union will not be used concurrently, only one interface at a time */ + rfalIsoDepBufFormat isoDepBuf; /*!< ISO-DEP buffer format (with header/prologue) */ + rfalNfcDepBufFormat nfcDepBuf; /*!< NFC-DEP buffer format (with header/prologue) */ +} rfalNfcTmpBuffer; + +typedef struct { + rfalNfcState state; /* Main state */ + uint16_t techsFound; /* Technologies found bitmask */ + uint16_t techs2do; /* Technologies still to be performed */ + rfalBitRate ap2pBR; /* Bit rate to poll for AP2P */ + uint8_t selDevIdx; /* Selected device index */ + rfalNfcDevice* activeDev; /* Active device pointer */ + rfalNfcDiscoverParam disc; /* Discovery parameters */ + rfalNfcDevice devList[RFAL_NFC_MAX_DEVICES]; /*!< Location of device list */ + uint8_t devCnt; /* Devices found counter */ + uint32_t discTmr; /* Discovery Total duration timer */ + ReturnCode dataExErr; /* Last Data Exchange error */ + bool discRestart; /* Restart discover after deactivation flag */ + bool isRxChaining; /* Flag indicating Other device is chaining */ + uint32_t lmMask; /* Listen Mode mask */ + bool isTechInit; /* Flag indicating technology has been set */ + bool isOperOngoing; /* Flag indicating operation is ongoing */ + + rfalNfcBuffer txBuf; /* Tx buffer for Data Exchange */ + rfalNfcBuffer rxBuf; /* Rx buffer for Data Exchange */ + uint16_t rxLen; /* Length of received data on Data Exchange */ + +#if RFAL_FEATURE_NFC_DEP || RFAL_FEATURE_ISO_DEP + rfalNfcTmpBuffer tmpBuf; /* Tmp buffer for Data Exchange */ +#endif /* RFAL_FEATURE_NFC_DEP || RFAL_FEATURE_ISO_DEP */ + +} rfalNfc; + +/* + ****************************************************************************** + * LOCAL VARIABLES + ****************************************************************************** + */ +#ifdef RFAL_TEST_MODE +rfalNfc gNfcDev; +#else /* RFAL_TEST_MODE */ +static rfalNfc gNfcDev; +#endif /* RFAL_TEST_MODE */ + +/* +****************************************************************************** +* LOCAL FUNCTION PROTOTYPES +****************************************************************************** +*/ +static ReturnCode rfalNfcPollTechDetetection(void); +static ReturnCode rfalNfcPollCollResolution(void); +static ReturnCode rfalNfcPollActivation(uint8_t devIt); +static ReturnCode rfalNfcDeactivation(void); + +#if RFAL_FEATURE_NFC_DEP +static ReturnCode rfalNfcNfcDepActivate( + rfalNfcDevice* device, + rfalNfcDepCommMode commMode, + const uint8_t* atrReq, + uint16_t atrReqLen); +#endif /* RFAL_FEATURE_NFC_DEP */ + +#if RFAL_FEATURE_LISTEN_MODE +static ReturnCode rfalNfcListenActivation(void); +#endif /* RFAL_FEATURE_LISTEN_MODE*/ + +/*******************************************************************************/ +ReturnCode rfalNfcInitialize(void) { + ReturnCode err; + + gNfcDev.state = RFAL_NFC_STATE_NOTINIT; + + rfalAnalogConfigInitialize(); /* Initialize RFAL's Analog Configs */ + EXIT_ON_ERR(err, rfalInitialize()); /* Initialize RFAL */ + + gNfcDev.state = RFAL_NFC_STATE_IDLE; /* Go to initialized */ + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcDiscover(const rfalNfcDiscoverParam* disParams) { + /* Check if initialization has been performed */ + if(gNfcDev.state != RFAL_NFC_STATE_IDLE) { + return ERR_WRONG_STATE; + } + + /* Check valid parameters */ + if((disParams == NULL) || (disParams->devLimit > RFAL_NFC_MAX_DEVICES) || + (disParams->devLimit == 0U) || + ((disParams->maxBR > RFAL_BR_1695) && (disParams->maxBR != RFAL_BR_KEEP)) || + (((disParams->techs2Find & RFAL_NFC_POLL_TECH_F) != 0U) && + (disParams->nfcfBR != RFAL_BR_212) && (disParams->nfcfBR != RFAL_BR_424)) || + ((((disParams->techs2Find & RFAL_NFC_POLL_TECH_AP2P) != 0U) && + (disParams->ap2pBR > RFAL_BR_424)) || + (disParams->GBLen > RFAL_NFCDEP_GB_MAX_LEN))) { + return ERR_PARAM; + } + + if((((disParams->techs2Find & RFAL_NFC_POLL_TECH_A) != 0U) && !((bool)RFAL_FEATURE_NFCA)) || + (((disParams->techs2Find & RFAL_NFC_POLL_TECH_B) != 0U) && !((bool)RFAL_FEATURE_NFCB)) || + (((disParams->techs2Find & RFAL_NFC_POLL_TECH_F) != 0U) && !((bool)RFAL_FEATURE_NFCF)) || + (((disParams->techs2Find & RFAL_NFC_POLL_TECH_V) != 0U) && !((bool)RFAL_FEATURE_NFCV)) || + (((disParams->techs2Find & RFAL_NFC_POLL_TECH_ST25TB) != 0U) && + !((bool)RFAL_FEATURE_ST25TB)) || + (((disParams->techs2Find & RFAL_NFC_POLL_TECH_AP2P) != 0U) && + !((bool)RFAL_FEATURE_NFC_DEP)) || + (((disParams->techs2Find & RFAL_NFC_LISTEN_TECH_A) != 0U) && !((bool)RFAL_FEATURE_NFCA)) || + (((disParams->techs2Find & RFAL_NFC_LISTEN_TECH_B) != 0U) && !((bool)RFAL_FEATURE_NFCB)) || + (((disParams->techs2Find & RFAL_NFC_LISTEN_TECH_F) != 0U) && !((bool)RFAL_FEATURE_NFCF)) || + (((disParams->techs2Find & RFAL_NFC_LISTEN_TECH_AP2P) != 0U) && + !((bool)RFAL_FEATURE_NFC_DEP))) { + return ERR_DISABLED; /* PRQA S 2880 # MISRA 2.1 - Unreachable code due to configuration option being set/unset */ + } + + /* Initialize context for discovery */ + gNfcDev.activeDev = NULL; + gNfcDev.techsFound = RFAL_NFC_TECH_NONE; + gNfcDev.devCnt = 0; + gNfcDev.discRestart = true; + gNfcDev.isTechInit = false; + gNfcDev.disc = *disParams; + + /* Calculate Listen Mask */ + gNfcDev.lmMask = 0U; + gNfcDev.lmMask |= + (((gNfcDev.disc.techs2Find & RFAL_NFC_LISTEN_TECH_A) != 0U) ? RFAL_LM_MASK_NFCA : 0U); + gNfcDev.lmMask |= + (((gNfcDev.disc.techs2Find & RFAL_NFC_LISTEN_TECH_B) != 0U) ? RFAL_LM_MASK_NFCB : 0U); + gNfcDev.lmMask |= + (((gNfcDev.disc.techs2Find & RFAL_NFC_LISTEN_TECH_F) != 0U) ? RFAL_LM_MASK_NFCF : 0U); + gNfcDev.lmMask |= + (((gNfcDev.disc.techs2Find & RFAL_NFC_LISTEN_TECH_AP2P) != 0U) ? RFAL_LM_MASK_ACTIVE_P2P : + 0U); + +#if !RFAL_FEATURE_LISTEN_MODE + /* Check if Listen Mode is supported/Enabled */ + if(gNfcDev.lmMask != 0U) { + return ERR_DISABLED; + } +#endif + + gNfcDev.state = RFAL_NFC_STATE_START_DISCOVERY; + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcDeactivate(bool discovery) { + /* Check for valid state */ + if(gNfcDev.state <= RFAL_NFC_STATE_IDLE) { + return ERR_WRONG_STATE; + } + + /* Check if discovery is to continue afterwards */ + if((discovery == true) && (gNfcDev.disc.techs2Find != RFAL_NFC_TECH_NONE)) { + /* If so let the state machine continue*/ + gNfcDev.discRestart = discovery; + gNfcDev.state = RFAL_NFC_STATE_DEACTIVATION; + } else { + /* Otherwise deactivate immediately and go to IDLE */ + rfalNfcDeactivation(); + gNfcDev.state = RFAL_NFC_STATE_IDLE; + } + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcSelect(uint8_t devIdx) { + /* Check for valid state */ + if(gNfcDev.state != RFAL_NFC_STATE_POLL_SELECT) { + return ERR_WRONG_STATE; + } + + gNfcDev.selDevIdx = devIdx; + gNfcDev.state = RFAL_NFC_STATE_POLL_ACTIVATION; + + return ERR_NONE; +} + +/*******************************************************************************/ +rfalNfcState rfalNfcGetState(void) { + return gNfcDev.state; +} + +/*******************************************************************************/ +ReturnCode rfalNfcGetDevicesFound(rfalNfcDevice** devList, uint8_t* devCnt) { + /* Check for valid state */ + if(gNfcDev.state < RFAL_NFC_STATE_POLL_SELECT) { + return ERR_WRONG_STATE; + } + + /* Check valid parameters */ + if((devList == NULL) || (devCnt == NULL)) { + return ERR_PARAM; + } + + *devCnt = gNfcDev.devCnt; + *devList = gNfcDev.devList; + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcGetActiveDevice(rfalNfcDevice** dev) { + /* Check for valid state */ + if(gNfcDev.state < RFAL_NFC_STATE_ACTIVATED) { + return ERR_WRONG_STATE; + } + + /* Check valid parameter */ + if(dev == NULL) { + return ERR_PARAM; + } + + /* Check for valid state */ + if((gNfcDev.devCnt == 0U) || (gNfcDev.activeDev == NULL)) { + return ERR_REQUEST; + } + + *dev = gNfcDev.activeDev; + return ERR_NONE; +} + +/*******************************************************************************/ +void rfalNfcWorker(void) { + ReturnCode err; + + rfalWorker(); /* Execute RFAL process */ + + switch(gNfcDev.state) { + /*******************************************************************************/ + case RFAL_NFC_STATE_NOTINIT: + case RFAL_NFC_STATE_IDLE: + break; + + /*******************************************************************************/ + case RFAL_NFC_STATE_START_DISCOVERY: + + /* Initialize context for discovery cycle */ + gNfcDev.devCnt = 0; + gNfcDev.selDevIdx = 0; + gNfcDev.techsFound = RFAL_NFC_TECH_NONE; + gNfcDev.techs2do = gNfcDev.disc.techs2Find; + gNfcDev.state = RFAL_NFC_STATE_POLL_TECHDETECT; + +#if RFAL_FEATURE_WAKEUP_MODE + /* Check if Low power Wake-Up is to be performed */ + if(gNfcDev.disc.wakeupEnabled) { + /* Initialize Low power Wake-up mode and wait */ + err = rfalWakeUpModeStart( + (gNfcDev.disc.wakeupConfigDefault ? NULL : &gNfcDev.disc.wakeupConfig)); + if(err == ERR_NONE) { + gNfcDev.state = RFAL_NFC_STATE_WAKEUP_MODE; + rfalNfcNfcNotify(gNfcDev.state); /* Notify caller that WU was started */ + } + } +#endif /* RFAL_FEATURE_WAKEUP_MODE */ + break; + + /*******************************************************************************/ + case RFAL_NFC_STATE_WAKEUP_MODE: + +#if RFAL_FEATURE_WAKEUP_MODE + /* Check if the Wake-up mode has woke */ + if(rfalWakeUpModeHasWoke()) { + rfalWakeUpModeStop(); /* Disable Wake-up mode */ + gNfcDev.state = RFAL_NFC_STATE_POLL_TECHDETECT; /* Go to Technology detection */ + + rfalNfcNfcNotify(gNfcDev.state); /* Notify caller that WU has woke */ + } +#endif /* RFAL_FEATURE_WAKEUP_MODE */ + + break; + + /*******************************************************************************/ + case RFAL_NFC_STATE_POLL_TECHDETECT: + + /* Start total duration timer */ + platformTimerDestroy(gNfcDev.discTmr); + gNfcDev.discTmr = (uint32_t)platformTimerCreate(gNfcDev.disc.totalDuration); + + err = + rfalNfcPollTechDetetection(); /* Perform Technology Detection */ + if(err != ERR_BUSY) /* Wait until all technologies are performed */ + { + if((err != ERR_NONE) || + (gNfcDev.techsFound == + RFAL_NFC_TECH_NONE)) /* Check if any error occurred or no techs were found */ + { + rfalFieldOff(); + gNfcDev.state = + RFAL_NFC_STATE_LISTEN_TECHDETECT; /* Nothing found as poller, go to listener */ + break; + } + + gNfcDev.techs2do = + gNfcDev.techsFound; /* Store the found technologies for collision resolution */ + gNfcDev.state = + RFAL_NFC_STATE_POLL_COLAVOIDANCE; /* One or more devices found, go to Collision Avoidance */ + } + break; + + /*******************************************************************************/ + case RFAL_NFC_STATE_POLL_COLAVOIDANCE: + + err = + rfalNfcPollCollResolution(); /* Resolve any eventual collision */ + if(err != ERR_BUSY) /* Wait until all technologies are performed */ + { + if((err != ERR_NONE) || + (gNfcDev.devCnt == 0U)) /* Check if any error occurred or no devices were found */ + { + gNfcDev.state = RFAL_NFC_STATE_DEACTIVATION; + break; /* Unable to retrieve any device, restart loop */ + } + + /* Check if more than one device has been found */ + if(gNfcDev.devCnt > 1U) { + /* If more than one device was found inform upper layer to choose which one to activate */ + if(gNfcDev.disc.notifyCb != NULL) { + gNfcDev.state = RFAL_NFC_STATE_POLL_SELECT; + gNfcDev.disc.notifyCb(gNfcDev.state); + break; + } + } + + /* If only one device or no callback has been set, activate the first device found */ + gNfcDev.selDevIdx = 0U; + gNfcDev.state = RFAL_NFC_STATE_POLL_ACTIVATION; + } + break; + + /*******************************************************************************/ + case RFAL_NFC_STATE_POLL_ACTIVATION: + + err = rfalNfcPollActivation(gNfcDev.selDevIdx); + if(err != ERR_BUSY) /* Wait until all Activation is complete */ + { + if(err != ERR_NONE) /* Activation failed selected device */ + { + gNfcDev.state = + RFAL_NFC_STATE_DEACTIVATION; /* If Activation failed, restart loop */ + break; + } + + gNfcDev.state = RFAL_NFC_STATE_ACTIVATED; /* Device has been properly activated */ + rfalNfcNfcNotify( + gNfcDev.state); /* Inform upper layer that a device has been activated */ + } + break; + + /*******************************************************************************/ + case RFAL_NFC_STATE_DATAEXCHANGE: + + rfalNfcDataExchangeGetStatus(); /* Run the internal state machine */ + + if(gNfcDev.dataExErr != ERR_BUSY) /* If Dataexchange has terminated */ + { + gNfcDev.state = RFAL_NFC_STATE_DATAEXCHANGE_DONE; /* Go to done state */ + rfalNfcNfcNotify(gNfcDev.state); /* And notify caller */ + } + if(gNfcDev.dataExErr == ERR_SLEEP_REQ) /* Check if Listen mode has to go to Sleep */ + { + gNfcDev.state = RFAL_NFC_STATE_LISTEN_SLEEP; /* Go to Listen Sleep state */ + rfalNfcNfcNotify(gNfcDev.state); /* And notify caller */ + } + break; + + /*******************************************************************************/ + case RFAL_NFC_STATE_DEACTIVATION: + + rfalNfcDeactivation(); /* Deactivate current device */ + + gNfcDev.state = + ((gNfcDev.discRestart) ? RFAL_NFC_STATE_START_DISCOVERY : RFAL_NFC_STATE_IDLE); + rfalNfcNfcNotify(gNfcDev.state); /* Notify caller */ + break; + + /*******************************************************************************/ + case RFAL_NFC_STATE_LISTEN_TECHDETECT: + + if(platformTimerIsExpired(gNfcDev.discTmr)) { +#if RFAL_FEATURE_LISTEN_MODE + rfalListenStop(); +#else + rfalFieldOff(); +#endif /* RFAL_FEATURE_LISTEN_MODE */ + + gNfcDev.state = RFAL_NFC_STATE_START_DISCOVERY; /* Restart the discovery loop */ + rfalNfcNfcNotify(gNfcDev.state); /* Notify caller */ + break; + } + +#if RFAL_FEATURE_LISTEN_MODE + + if(gNfcDev.lmMask != 0U) /* Check if configured to perform Listen mode */ + { + err = rfalListenStart( + gNfcDev.lmMask, + &gNfcDev.disc.lmConfigPA, + NULL, + &gNfcDev.disc.lmConfigPF, + (uint8_t*)&gNfcDev.rxBuf.rfBuf, + (uint16_t)rfalConvBytesToBits(sizeof(gNfcDev.rxBuf.rfBuf)), + &gNfcDev.rxLen); + if(err == ERR_NONE) { + gNfcDev.state = + RFAL_NFC_STATE_LISTEN_COLAVOIDANCE; /* Wait for listen mode to be activated */ + } + } + break; + + /*******************************************************************************/ + case RFAL_NFC_STATE_LISTEN_COLAVOIDANCE: + + if(platformTimerIsExpired( + gNfcDev.discTmr)) /* Check if the total duration has been reached */ + { + rfalListenStop(); + gNfcDev.state = RFAL_NFC_STATE_START_DISCOVERY; /* Restart the discovery loop */ + rfalNfcNfcNotify(gNfcDev.state); /* Notify caller */ + break; + } + + /* Check for external field */ + if(rfalListenGetState(NULL, NULL) >= RFAL_LM_STATE_IDLE) { + gNfcDev.state = + RFAL_NFC_STATE_LISTEN_ACTIVATION; /* Wait for listen mode to be activated */ + } + break; + + /*******************************************************************************/ + case RFAL_NFC_STATE_LISTEN_ACTIVATION: + case RFAL_NFC_STATE_LISTEN_SLEEP: + + err = rfalNfcListenActivation(); + if(err != ERR_BUSY) { + if(err == ERR_NONE) { + gNfcDev.activeDev = + gNfcDev.devList; /* Assign the active device to be used further on */ + gNfcDev.devCnt++; + + gNfcDev.state = RFAL_NFC_STATE_ACTIVATED; /* Device has been properly activated */ + rfalNfcNfcNotify( + gNfcDev.state); /* Inform upper layer that a device has been activated */ + } else { + rfalListenStop(); + gNfcDev.state = RFAL_NFC_STATE_START_DISCOVERY; /* Restart the discovery loop */ + rfalNfcNfcNotify(gNfcDev.state); /* Notify caller */ + } + } +#endif /* RFAL_FEATURE_LISTEN_MODE */ + break; + + /*******************************************************************************/ + case RFAL_NFC_STATE_ACTIVATED: + case RFAL_NFC_STATE_POLL_SELECT: + case RFAL_NFC_STATE_DATAEXCHANGE_DONE: + default: + return; + } +} + +/*******************************************************************************/ +ReturnCode rfalNfcDataExchangeStart( + uint8_t* txData, + uint16_t txDataLen, + uint8_t** rxData, + uint16_t** rvdLen, + uint32_t fwt, + uint32_t flags) { + ReturnCode err; + rfalTransceiveContext ctx; + + /*******************************************************************************/ + /* The Data Exchange is divided in two different moments, the trigger/Start of * + * the transfer followed by the check until its completion */ + if((gNfcDev.state >= RFAL_NFC_STATE_ACTIVATED) && (gNfcDev.activeDev != NULL)) { + /*******************************************************************************/ + /* In Listen mode is the Poller that initiates the communicatation */ + /* Assign output parameters and rfalNfcDataExchangeGetStatus will return */ + /* incoming data from Poller/Initiator */ + if((gNfcDev.state == RFAL_NFC_STATE_ACTIVATED) && + rfalNfcIsRemDevPoller(gNfcDev.activeDev->type)) { + if(txDataLen > 0U) { + return ERR_WRONG_STATE; + } + + *rvdLen = (uint16_t*)&gNfcDev.rxLen; + *rxData = + (uint8_t*)((gNfcDev.activeDev->rfInterface == RFAL_NFC_INTERFACE_ISODEP) ? + gNfcDev.rxBuf.isoDepBuf.apdu : + ((gNfcDev.activeDev->rfInterface == RFAL_NFC_INTERFACE_NFCDEP) ? + gNfcDev.rxBuf.nfcDepBuf.pdu : + gNfcDev.rxBuf.rfBuf)); + if(gNfcDev.disc.activate_after_sak) { + gNfcDev.state = RFAL_NFC_STATE_DATAEXCHANGE_DONE; + } + return ERR_NONE; + } + + /*******************************************************************************/ + switch(gNfcDev.activeDev + ->rfInterface) /* Check which RF interface shall be used/has been activated */ + { + /*******************************************************************************/ + case RFAL_NFC_INTERFACE_RF: + + rfalCreateByteFlagsTxRxContext( + ctx, + (uint8_t*)txData, + txDataLen, + gNfcDev.rxBuf.rfBuf, + sizeof(gNfcDev.rxBuf.rfBuf), + &gNfcDev.rxLen, + flags, + fwt); + if(flags == RFAL_TXRX_FLAGS_RAW) { + ctx.txBufLen = txDataLen; + } + *rxData = (uint8_t*)gNfcDev.rxBuf.rfBuf; + *rvdLen = (uint16_t*)&gNfcDev.rxLen; + err = rfalStartTransceive(&ctx); + break; + +#if RFAL_FEATURE_ISO_DEP + /*******************************************************************************/ + case RFAL_NFC_INTERFACE_ISODEP: { + rfalIsoDepApduTxRxParam isoDepTxRx; + + if(txDataLen > sizeof(gNfcDev.txBuf.isoDepBuf.apdu)) { + return ERR_NOMEM; + } + + if(txDataLen > 0U) { + ST_MEMCPY((uint8_t*)gNfcDev.txBuf.isoDepBuf.apdu, txData, txDataLen); + } + + isoDepTxRx.DID = RFAL_ISODEP_NO_DID; + isoDepTxRx.ourFSx = RFAL_ISODEP_FSX_KEEP; + isoDepTxRx.FSx = gNfcDev.activeDev->proto.isoDep.info.FSx; + isoDepTxRx.dFWT = gNfcDev.activeDev->proto.isoDep.info.dFWT; + isoDepTxRx.FWT = gNfcDev.activeDev->proto.isoDep.info.FWT; + isoDepTxRx.txBuf = &gNfcDev.txBuf.isoDepBuf; + isoDepTxRx.txBufLen = txDataLen; + isoDepTxRx.rxBuf = &gNfcDev.rxBuf.isoDepBuf; + isoDepTxRx.rxLen = &gNfcDev.rxLen; + isoDepTxRx.tmpBuf = &gNfcDev.tmpBuf.isoDepBuf; + *rxData = (uint8_t*)gNfcDev.rxBuf.isoDepBuf.apdu; + *rvdLen = (uint16_t*)&gNfcDev.rxLen; + + /*******************************************************************************/ + /* Trigger a RFAL ISO-DEP Transceive */ + err = rfalIsoDepStartApduTransceive(isoDepTxRx); + break; + } +#endif /* RFAL_FEATURE_ISO_DEP */ + +#if RFAL_FEATURE_NFC_DEP + /*******************************************************************************/ + case RFAL_NFC_INTERFACE_NFCDEP: { + rfalNfcDepPduTxRxParam nfcDepTxRx; + + if(txDataLen > sizeof(gNfcDev.txBuf.nfcDepBuf.pdu)) { + return ERR_NOMEM; + } + + if(txDataLen > 0U) { + ST_MEMCPY((uint8_t*)gNfcDev.txBuf.nfcDepBuf.pdu, txData, txDataLen); + } + + nfcDepTxRx.DID = RFAL_NFCDEP_DID_KEEP; + nfcDepTxRx.FSx = + rfalNfcIsRemDevListener(gNfcDev.activeDev->type) ? + rfalNfcDepLR2FS((uint8_t)rfalNfcDepPP2LR( + gNfcDev.activeDev->proto.nfcDep.activation.Target.ATR_RES.PPt)) : + rfalNfcDepLR2FS((uint8_t)rfalNfcDepPP2LR( + gNfcDev.activeDev->proto.nfcDep.activation.Initiator.ATR_REQ.PPi)); + nfcDepTxRx.dFWT = gNfcDev.activeDev->proto.nfcDep.info.dFWT; + nfcDepTxRx.FWT = gNfcDev.activeDev->proto.nfcDep.info.FWT; + nfcDepTxRx.txBuf = &gNfcDev.txBuf.nfcDepBuf; + nfcDepTxRx.txBufLen = txDataLen; + nfcDepTxRx.rxBuf = &gNfcDev.rxBuf.nfcDepBuf; + nfcDepTxRx.rxLen = &gNfcDev.rxLen; + nfcDepTxRx.tmpBuf = &gNfcDev.tmpBuf.nfcDepBuf; + *rxData = (uint8_t*)gNfcDev.rxBuf.nfcDepBuf.pdu; + *rvdLen = (uint16_t*)&gNfcDev.rxLen; + + /*******************************************************************************/ + /* Trigger a RFAL NFC-DEP Transceive */ + err = rfalNfcDepStartPduTransceive(nfcDepTxRx); + break; + } +#endif /* RFAL_FEATURE_NFC_DEP */ + + /*******************************************************************************/ + default: + err = ERR_PARAM; + break; + } + + /* If a transceive has successfuly started flag Data Exchange as ongoing */ + if(err == ERR_NONE) { + gNfcDev.dataExErr = ERR_BUSY; + gNfcDev.state = RFAL_NFC_STATE_DATAEXCHANGE; + } + + return err; + } + + return ERR_WRONG_STATE; +} + +ReturnCode rfalNfcDataExchangeCustomStart( + uint8_t* txData, + uint16_t txDataLen, + uint8_t** rxData, + uint16_t** rvdLen, + uint32_t fwt, + uint32_t flags) { + ReturnCode err; + rfalTransceiveContext ctx; + + /*******************************************************************************/ + /* The Data Exchange is divided in two different moments, the trigger/Start of * + * the transfer followed by the check until its completion */ + if((gNfcDev.state >= RFAL_NFC_STATE_ACTIVATED) && (gNfcDev.activeDev != NULL)) { + /*******************************************************************************/ + /* In Listen mode is the Poller that initiates the communicatation */ + /* Assign output parameters and rfalNfcDataExchangeGetStatus will return */ + /* incoming data from Poller/Initiator */ + if((gNfcDev.state == RFAL_NFC_STATE_ACTIVATED) && + rfalNfcIsRemDevPoller(gNfcDev.activeDev->type)) { + if(txDataLen > 0U) { + return ERR_WRONG_STATE; + } + + *rvdLen = (uint16_t*)&gNfcDev.rxLen; + *rxData = + (uint8_t*)((gNfcDev.activeDev->rfInterface == RFAL_NFC_INTERFACE_ISODEP) ? + gNfcDev.rxBuf.isoDepBuf.apdu : + ((gNfcDev.activeDev->rfInterface == RFAL_NFC_INTERFACE_NFCDEP) ? + gNfcDev.rxBuf.nfcDepBuf.pdu : + gNfcDev.rxBuf.rfBuf)); + if(gNfcDev.disc.activate_after_sak) { + gNfcDev.state = RFAL_NFC_STATE_DATAEXCHANGE_DONE; + } + return ERR_NONE; + } + + /*******************************************************************************/ + switch(gNfcDev.activeDev + ->rfInterface) /* Check which RF interface shall be used/has been activated */ + { + /*******************************************************************************/ + case RFAL_NFC_INTERFACE_RF: + ctx.rxBuf = gNfcDev.rxBuf.rfBuf; + ctx.rxBufLen = 8 * sizeof(gNfcDev.rxBuf.rfBuf); + ctx.rxRcvdLen = &gNfcDev.rxLen; + ctx.txBuf = txData; + ctx.txBufLen = txDataLen; + ctx.flags = flags; + ctx.fwt = fwt; + *rxData = (uint8_t*)gNfcDev.rxBuf.rfBuf; + *rvdLen = (uint16_t*)&gNfcDev.rxLen; + err = rfalStartTransceive(&ctx); + break; + +#if RFAL_FEATURE_ISO_DEP + /*******************************************************************************/ + case RFAL_NFC_INTERFACE_ISODEP: { + rfalIsoDepApduTxRxParam isoDepTxRx; + uint16_t tx_bytes = txDataLen / 8; + + if(tx_bytes > sizeof(gNfcDev.txBuf.isoDepBuf.apdu)) { + return ERR_NOMEM; + } + + if(tx_bytes > 0U) { + ST_MEMCPY((uint8_t*)gNfcDev.txBuf.isoDepBuf.apdu, txData, tx_bytes); + } + + isoDepTxRx.DID = RFAL_ISODEP_NO_DID; + isoDepTxRx.ourFSx = RFAL_ISODEP_FSX_KEEP; + isoDepTxRx.FSx = gNfcDev.activeDev->proto.isoDep.info.FSx; + isoDepTxRx.dFWT = gNfcDev.activeDev->proto.isoDep.info.dFWT; + isoDepTxRx.FWT = gNfcDev.activeDev->proto.isoDep.info.FWT; + isoDepTxRx.txBuf = &gNfcDev.txBuf.isoDepBuf; + isoDepTxRx.txBufLen = tx_bytes; + isoDepTxRx.rxBuf = &gNfcDev.rxBuf.isoDepBuf; + isoDepTxRx.rxLen = &gNfcDev.rxLen; + isoDepTxRx.tmpBuf = &gNfcDev.tmpBuf.isoDepBuf; + *rxData = (uint8_t*)gNfcDev.rxBuf.isoDepBuf.apdu; + *rvdLen = (uint16_t*)&gNfcDev.rxLen; + + /*******************************************************************************/ + /* Trigger a RFAL ISO-DEP Transceive */ + err = rfalIsoDepStartApduTransceive(isoDepTxRx); + break; + } +#endif /* RFAL_FEATURE_ISO_DEP */ + +#if RFAL_FEATURE_NFC_DEP + /*******************************************************************************/ + case RFAL_NFC_INTERFACE_NFCDEP: { + rfalNfcDepPduTxRxParam nfcDepTxRx; + + if(txDataLen > sizeof(gNfcDev.txBuf.nfcDepBuf.pdu)) { + return ERR_NOMEM; + } + + if(txDataLen > 0U) { + ST_MEMCPY((uint8_t*)gNfcDev.txBuf.nfcDepBuf.pdu, txData, txDataLen); + } + + nfcDepTxRx.DID = RFAL_NFCDEP_DID_KEEP; + nfcDepTxRx.FSx = + rfalNfcIsRemDevListener(gNfcDev.activeDev->type) ? + rfalNfcDepLR2FS((uint8_t)rfalNfcDepPP2LR( + gNfcDev.activeDev->proto.nfcDep.activation.Target.ATR_RES.PPt)) : + rfalNfcDepLR2FS((uint8_t)rfalNfcDepPP2LR( + gNfcDev.activeDev->proto.nfcDep.activation.Initiator.ATR_REQ.PPi)); + nfcDepTxRx.dFWT = gNfcDev.activeDev->proto.nfcDep.info.dFWT; + nfcDepTxRx.FWT = gNfcDev.activeDev->proto.nfcDep.info.FWT; + nfcDepTxRx.txBuf = &gNfcDev.txBuf.nfcDepBuf; + nfcDepTxRx.txBufLen = txDataLen; + nfcDepTxRx.rxBuf = &gNfcDev.rxBuf.nfcDepBuf; + nfcDepTxRx.rxLen = &gNfcDev.rxLen; + nfcDepTxRx.tmpBuf = &gNfcDev.tmpBuf.nfcDepBuf; + *rxData = (uint8_t*)gNfcDev.rxBuf.nfcDepBuf.pdu; + *rvdLen = (uint16_t*)&gNfcDev.rxLen; + + /*******************************************************************************/ + /* Trigger a RFAL NFC-DEP Transceive */ + err = rfalNfcDepStartPduTransceive(nfcDepTxRx); + break; + } +#endif /* RFAL_FEATURE_NFC_DEP */ + + /*******************************************************************************/ + default: + err = ERR_PARAM; + break; + } + + /* If a transceive has successfuly started flag Data Exchange as ongoing */ + if(err == ERR_NONE) { + gNfcDev.dataExErr = ERR_BUSY; + gNfcDev.state = RFAL_NFC_STATE_DATAEXCHANGE; + } + + return err; + } + + return ERR_WRONG_STATE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcDataExchangeGetStatus(void) { + /*******************************************************************************/ + /* Check if it's the first frame received in Listen mode */ + if(gNfcDev.state == RFAL_NFC_STATE_ACTIVATED) { + /* Continue data exchange as normal */ + gNfcDev.dataExErr = ERR_BUSY; + gNfcDev.state = RFAL_NFC_STATE_DATAEXCHANGE; + + /* Check if we performing in T3T CE */ + if((gNfcDev.activeDev->type == RFAL_NFC_POLL_TYPE_NFCF) && + (gNfcDev.activeDev->rfInterface == RFAL_NFC_INTERFACE_RF)) { + /* The first frame has been retrieved by rfalListenMode, flag data immediately */ + /* Can only call rfalGetTransceiveStatus() after starting a transceive with rfalStartTransceive */ + gNfcDev.dataExErr = ERR_NONE; + } + } + + /*******************************************************************************/ + /* Check if we are in we have been placed to sleep, and return last error */ + if(gNfcDev.state == RFAL_NFC_STATE_LISTEN_SLEEP) { + return gNfcDev.dataExErr; /* ERR_SLEEP_REQ */ + } + + /*******************************************************************************/ + /* Check if Data exchange has been started */ + if((gNfcDev.state != RFAL_NFC_STATE_DATAEXCHANGE) && + (gNfcDev.state != RFAL_NFC_STATE_DATAEXCHANGE_DONE)) { + return ERR_WRONG_STATE; + } + + /* Check if Data exchange is still ongoing */ + if(gNfcDev.dataExErr == ERR_BUSY) { + switch(gNfcDev.activeDev->rfInterface) { + /*******************************************************************************/ + case RFAL_NFC_INTERFACE_RF: + gNfcDev.dataExErr = rfalGetTransceiveStatus(); + break; + +#if RFAL_FEATURE_ISO_DEP + /*******************************************************************************/ + case RFAL_NFC_INTERFACE_ISODEP: + gNfcDev.dataExErr = rfalIsoDepGetApduTransceiveStatus(); + break; +#endif /* RFAL_FEATURE_ISO_DEP */ + + /*******************************************************************************/ +#if RFAL_FEATURE_NFC_DEP + case RFAL_NFC_INTERFACE_NFCDEP: + gNfcDev.dataExErr = rfalNfcDepGetPduTransceiveStatus(); + break; +#endif /* RFAL_FEATURE_NFC_DEP */ + + /*******************************************************************************/ + default: + gNfcDev.dataExErr = ERR_PARAM; + break; + } + +#if RFAL_FEATURE_LISTEN_MODE + /*******************************************************************************/ + /* If a Sleep request has been received (Listen Mode) go to sleep immediately */ + if(gNfcDev.dataExErr == ERR_SLEEP_REQ) { + EXIT_ON_ERR( + gNfcDev.dataExErr, + rfalListenSleepStart( + RFAL_LM_STATE_SLEEP_A, + gNfcDev.rxBuf.rfBuf, + sizeof(gNfcDev.rxBuf.rfBuf), + &gNfcDev.rxLen)); + + /* If set Sleep was successful keep restore the Sleep request signal */ + gNfcDev.dataExErr = ERR_SLEEP_REQ; + } +#endif /* RFAL_FEATURE_LISTEN_MODE */ + } + + return gNfcDev.dataExErr; +} + +/*! + ****************************************************************************** + * \brief Poller Technology Detection + * + * This method implements the Technology Detection / Poll for different + * device technologies. + * + * \return ERR_NONE : Operation completed with no error + * \return ERR_BUSY : Operation ongoing + * \return ERR_XXXX : Error occurred + * + ****************************************************************************** + */ +static ReturnCode rfalNfcPollTechDetetection(void) { + ReturnCode err; + + err = ERR_NONE; + + /* Suppress warning when specific RFAL features have been disabled */ + NO_WARNING(err); + + /*******************************************************************************/ + /* AP2P Technology Detection */ + /*******************************************************************************/ + if(((gNfcDev.disc.techs2Find & RFAL_NFC_POLL_TECH_AP2P) != 0U) && + ((gNfcDev.techs2do & RFAL_NFC_POLL_TECH_AP2P) != 0U)) { +#if RFAL_FEATURE_NFC_DEP + + if(!gNfcDev.isTechInit) { + EXIT_ON_ERR( + err, + rfalSetMode(RFAL_MODE_POLL_ACTIVE_P2P, gNfcDev.disc.ap2pBR, gNfcDev.disc.ap2pBR)); + rfalSetErrorHandling(RFAL_ERRORHANDLING_NFC); + rfalSetFDTListen(RFAL_FDT_LISTEN_AP2P_POLLER); + rfalSetFDTPoll(RFAL_TIMING_NONE); + rfalSetGT(RFAL_GT_AP2P_ADJUSTED); + EXIT_ON_ERR(err, rfalFieldOnAndStartGT()); /* Turns the Field On and starts GT timer */ + gNfcDev.isTechInit = true; + } + + if(rfalIsGTExpired()) /* Wait until Guard Time is fulfilled */ + { + gNfcDev.techs2do &= ~RFAL_NFC_POLL_TECH_AP2P; + + err = rfalNfcNfcDepActivate( + gNfcDev.devList, RFAL_NFCDEP_COMM_ACTIVE, NULL, 0); /* Poll for NFC-A devices */ + if(err == ERR_NONE) { + gNfcDev.techsFound |= RFAL_NFC_POLL_TECH_AP2P; + + gNfcDev.devList->type = RFAL_NFC_LISTEN_TYPE_AP2P; + gNfcDev.devList->rfInterface = RFAL_NFC_INTERFACE_NFCDEP; + gNfcDev.devCnt++; + + return ERR_NONE; + } + + gNfcDev.isTechInit = false; + rfalFieldOff(); + } + return ERR_BUSY; + +#endif /* RFAL_FEATURE_NFC_DEP */ + } + + /*******************************************************************************/ + /* Passive NFC-A Technology Detection */ + /*******************************************************************************/ + if(((gNfcDev.disc.techs2Find & RFAL_NFC_POLL_TECH_A) != 0U) && + ((gNfcDev.techs2do & RFAL_NFC_POLL_TECH_A) != 0U)) { +#if RFAL_FEATURE_NFCA + + rfalNfcaSensRes sensRes; + + if(!gNfcDev.isTechInit) { + EXIT_ON_ERR(err, rfalNfcaPollerInitialize()); /* Initialize RFAL for NFC-A */ + EXIT_ON_ERR(err, rfalFieldOnAndStartGT()); /* Turns the Field On and starts GT timer */ + gNfcDev.isTechInit = true; + } + + if(rfalIsGTExpired()) /* Wait until Guard Time is fulfilled */ + { + err = rfalNfcaPollerTechnologyDetection( + gNfcDev.disc.compMode, &sensRes); /* Poll for NFC-A devices */ + if(err == ERR_NONE) { + gNfcDev.techsFound |= RFAL_NFC_POLL_TECH_A; + } + + gNfcDev.isTechInit = false; + gNfcDev.techs2do &= ~RFAL_NFC_POLL_TECH_A; + } + + return ERR_BUSY; + +#endif /* RFAL_FEATURE_NFCA */ + } + + /*******************************************************************************/ + /* Passive NFC-B Technology Detection */ + /*******************************************************************************/ + if(((gNfcDev.disc.techs2Find & RFAL_NFC_POLL_TECH_B) != 0U) && + ((gNfcDev.techs2do & RFAL_NFC_POLL_TECH_B) != 0U)) { +#if RFAL_FEATURE_NFCB + + rfalNfcbSensbRes sensbRes; + uint8_t sensbResLen; + + if(!gNfcDev.isTechInit) { + EXIT_ON_ERR(err, rfalNfcbPollerInitialize()); /* Initialize RFAL for NFC-B */ + EXIT_ON_ERR( + err, rfalFieldOnAndStartGT()); /* As field is already On only starts GT timer */ + gNfcDev.isTechInit = true; + } + + if(rfalIsGTExpired()) /* Wait until Guard Time is fulfilled */ + { + err = rfalNfcbPollerTechnologyDetection( + gNfcDev.disc.compMode, &sensbRes, &sensbResLen); /* Poll for NFC-B devices */ + if(err == ERR_NONE) { + gNfcDev.techsFound |= RFAL_NFC_POLL_TECH_B; + } + + gNfcDev.isTechInit = false; + gNfcDev.techs2do &= ~RFAL_NFC_POLL_TECH_B; + } + + return ERR_BUSY; + +#endif /* RFAL_FEATURE_NFCB */ + } + + /*******************************************************************************/ + /* Passive NFC-F Technology Detection */ + /*******************************************************************************/ + if(((gNfcDev.disc.techs2Find & RFAL_NFC_POLL_TECH_F) != 0U) && + ((gNfcDev.techs2do & RFAL_NFC_POLL_TECH_F) != 0U)) { +#if RFAL_FEATURE_NFCF + + if(!gNfcDev.isTechInit) { + EXIT_ON_ERR( + err, + rfalNfcfPollerInitialize(gNfcDev.disc.nfcfBR)); /* Initialize RFAL for NFC-F */ + EXIT_ON_ERR( + err, rfalFieldOnAndStartGT()); /* As field is already On only starts GT timer */ + gNfcDev.isTechInit = true; + } + + if(rfalIsGTExpired()) /* Wait until Guard Time is fulfilled */ + { + err = rfalNfcfPollerCheckPresence(); /* Poll for NFC-F devices */ + if(err == ERR_NONE) { + gNfcDev.techsFound |= RFAL_NFC_POLL_TECH_F; + } + + gNfcDev.isTechInit = false; + gNfcDev.techs2do &= ~RFAL_NFC_POLL_TECH_F; + } + + return ERR_BUSY; + +#endif /* RFAL_FEATURE_NFCF */ + } + + /*******************************************************************************/ + /* Passive NFC-V Technology Detection */ + /*******************************************************************************/ + if(((gNfcDev.disc.techs2Find & RFAL_NFC_POLL_TECH_V) != 0U) && + ((gNfcDev.techs2do & RFAL_NFC_POLL_TECH_V) != 0U)) { +#if RFAL_FEATURE_NFCV + + rfalNfcvInventoryRes invRes; + + if(!gNfcDev.isTechInit) { + EXIT_ON_ERR(err, rfalNfcvPollerInitialize()); /* Initialize RFAL for NFC-V */ + EXIT_ON_ERR( + err, rfalFieldOnAndStartGT()); /* As field is already On only starts GT timer */ + gNfcDev.isTechInit = true; + } + + if(rfalIsGTExpired()) /* Wait until Guard Time is fulfilled */ + { + err = rfalNfcvPollerCheckPresence(&invRes); /* Poll for NFC-V devices */ + if(err == ERR_NONE) { + gNfcDev.techsFound |= RFAL_NFC_POLL_TECH_V; + } + + gNfcDev.isTechInit = false; + gNfcDev.techs2do &= ~RFAL_NFC_POLL_TECH_V; + } + + return ERR_BUSY; + +#endif /* RFAL_FEATURE_NFCV */ + } + + /*******************************************************************************/ + /* Passive Proprietary Technology ST25TB */ + /*******************************************************************************/ + if(((gNfcDev.disc.techs2Find & RFAL_NFC_POLL_TECH_ST25TB) != 0U) && + ((gNfcDev.techs2do & RFAL_NFC_POLL_TECH_ST25TB) != 0U)) { +#if RFAL_FEATURE_ST25TB + + if(!gNfcDev.isTechInit) { + EXIT_ON_ERR(err, rfalSt25tbPollerInitialize()); /* Initialize RFAL for NFC-V */ + EXIT_ON_ERR( + err, rfalFieldOnAndStartGT()); /* As field is already On only starts GT timer */ + gNfcDev.isTechInit = true; + } + + if(rfalIsGTExpired()) /* Wait until Guard Time is fulfilled */ + { + err = rfalSt25tbPollerCheckPresence(NULL); /* Poll for ST25TB devices */ + if(err == ERR_NONE) { + gNfcDev.techsFound |= RFAL_NFC_POLL_TECH_ST25TB; + } + + gNfcDev.isTechInit = false; + gNfcDev.techs2do &= ~RFAL_NFC_POLL_TECH_ST25TB; + } + + return ERR_BUSY; + +#endif /* RFAL_FEATURE_ST25TB */ + } + + return ERR_NONE; +} + +/*! + ****************************************************************************** + * \brief Poller Collision Resolution + * + * This method implements the Collision Resolution on all technologies that + * have been detected before. + * + * \return ERR_NONE : Operation completed with no error + * \return ERR_BUSY : Operation ongoing + * \return ERR_XXXX : Error occurred + * + ****************************************************************************** + */ +static ReturnCode rfalNfcPollCollResolution(void) { + uint8_t i; + static uint8_t devCnt; + ReturnCode err; + + err = ERR_NONE; + i = 0; + + /* Suppress warning when specific RFAL features have been disabled */ + NO_WARNING(err); + NO_WARNING(devCnt); + NO_WARNING(i); + + /* Check if device limit has been reached */ + if(gNfcDev.devCnt >= gNfcDev.disc.devLimit) { + return ERR_NONE; + } + + /*******************************************************************************/ + /* NFC-A Collision Resolution */ + /*******************************************************************************/ +#if RFAL_FEATURE_NFCA + if(((gNfcDev.techsFound & RFAL_NFC_POLL_TECH_A) != 0U) && + ((gNfcDev.techs2do & RFAL_NFC_POLL_TECH_A) != + 0U)) /* If a NFC-A device was found/detected, perform Collision Resolution */ + { + static rfalNfcaListenDevice nfcaDevList[RFAL_NFC_MAX_DEVICES]; + + if(!gNfcDev.isTechInit) { + EXIT_ON_ERR(err, rfalNfcaPollerInitialize()); /* Initialize RFAL for NFC-A */ + EXIT_ON_ERR(err, rfalFieldOnAndStartGT()); /* Turns the Field On and starts GT timer */ + + gNfcDev.isTechInit = true; /* Technology has been initialized */ + gNfcDev.isOperOngoing = false; /* No operation currently ongoing */ + } + + if(!rfalIsGTExpired()) { + return ERR_BUSY; + } + + if(!gNfcDev.isOperOngoing) { + EXIT_ON_ERR( + err, + rfalNfcaPollerStartFullCollisionResolution( + gNfcDev.disc.compMode, + (gNfcDev.disc.devLimit - gNfcDev.devCnt), + nfcaDevList, + &devCnt)); + + gNfcDev.isOperOngoing = true; + return ERR_BUSY; + } + + err = rfalNfcaPollerGetFullCollisionResolutionStatus(); + if(err != ERR_BUSY) { + gNfcDev.isTechInit = false; + gNfcDev.techs2do &= ~RFAL_NFC_POLL_TECH_A; + + if((err == ERR_NONE) && (devCnt != 0U)) { + for(i = 0; i < devCnt; + i++) /* Copy devices found form local Nfca list into global device list */ + { + gNfcDev.devList[gNfcDev.devCnt].type = RFAL_NFC_LISTEN_TYPE_NFCA; + gNfcDev.devList[gNfcDev.devCnt].dev.nfca = nfcaDevList[i]; + gNfcDev.devCnt++; + } + } + } + + return ERR_BUSY; + } +#endif /* RFAL_FEATURE_NFCA */ + + /*******************************************************************************/ + /* NFC-B Collision Resolution */ + /*******************************************************************************/ +#if RFAL_FEATURE_NFCB + if(((gNfcDev.techsFound & RFAL_NFC_POLL_TECH_B) != 0U) && + ((gNfcDev.techs2do & RFAL_NFC_POLL_TECH_B) != + 0U)) /* If a NFC-B device was found/detected, perform Collision Resolution */ + { + rfalNfcbListenDevice nfcbDevList[RFAL_NFC_MAX_DEVICES]; + + if(!gNfcDev.isTechInit) { + EXIT_ON_ERR(err, rfalNfcbPollerInitialize()); /* Initialize RFAL for NFC-B */ + EXIT_ON_ERR( + err, + rfalFieldOnAndStartGT()); /* Ensure GT again as other technologies have also been polled */ + gNfcDev.isTechInit = true; + } + + if(!rfalIsGTExpired()) { + return ERR_BUSY; + } + + devCnt = 0; + gNfcDev.isTechInit = false; + gNfcDev.techs2do &= ~RFAL_NFC_POLL_TECH_B; + + err = rfalNfcbPollerCollisionResolution( + gNfcDev.disc.compMode, (gNfcDev.disc.devLimit - gNfcDev.devCnt), nfcbDevList, &devCnt); + if((err == ERR_NONE) && (devCnt != 0U)) { + for(i = 0; i < devCnt; + i++) /* Copy devices found form local Nfcb list into global device list */ + { + gNfcDev.devList[gNfcDev.devCnt].type = RFAL_NFC_LISTEN_TYPE_NFCB; + gNfcDev.devList[gNfcDev.devCnt].dev.nfcb = nfcbDevList[i]; + gNfcDev.devCnt++; + } + } + + return ERR_BUSY; + } +#endif /* RFAL_FEATURE_NFCB*/ + + /*******************************************************************************/ + /* NFC-F Collision Resolution */ + /*******************************************************************************/ +#if RFAL_FEATURE_NFCF + if(((gNfcDev.techsFound & RFAL_NFC_POLL_TECH_F) != 0U) && + ((gNfcDev.techs2do & RFAL_NFC_POLL_TECH_F) != + 0U)) /* If a NFC-F device was found/detected, perform Collision Resolution */ + { + rfalNfcfListenDevice nfcfDevList[RFAL_NFC_MAX_DEVICES]; + + if(!gNfcDev.isTechInit) { + EXIT_ON_ERR( + err, + rfalNfcfPollerInitialize(gNfcDev.disc.nfcfBR)); /* Initialize RFAL for NFC-F */ + EXIT_ON_ERR( + err, + rfalFieldOnAndStartGT()); /* Ensure GT again as other technologies have also been polled */ + gNfcDev.isTechInit = true; + } + + if(!rfalIsGTExpired()) { + return ERR_BUSY; + } + + devCnt = 0; + gNfcDev.isTechInit = false; + gNfcDev.techs2do &= ~RFAL_NFC_POLL_TECH_F; + + err = rfalNfcfPollerCollisionResolution( + gNfcDev.disc.compMode, (gNfcDev.disc.devLimit - gNfcDev.devCnt), nfcfDevList, &devCnt); + if((err == ERR_NONE) && (devCnt != 0U)) { + for(i = 0; i < devCnt; + i++) /* Copy devices found form local Nfcf list into global device list */ + { + gNfcDev.devList[gNfcDev.devCnt].type = RFAL_NFC_LISTEN_TYPE_NFCF; + gNfcDev.devList[gNfcDev.devCnt].dev.nfcf = nfcfDevList[i]; + gNfcDev.devCnt++; + } + } + + return ERR_BUSY; + } +#endif /* RFAL_FEATURE_NFCF */ + + /*******************************************************************************/ + /* NFC-V Collision Resolution */ + /*******************************************************************************/ +#if RFAL_FEATURE_NFCV + if(((gNfcDev.techsFound & RFAL_NFC_POLL_TECH_V) != 0U) && + ((gNfcDev.techs2do & RFAL_NFC_POLL_TECH_V) != + 0U)) /* If a NFC-V device was found/detected, perform Collision Resolution */ + { + rfalNfcvListenDevice nfcvDevList[RFAL_NFC_MAX_DEVICES]; + + if(!gNfcDev.isTechInit) { + EXIT_ON_ERR(err, rfalNfcvPollerInitialize()); /* Initialize RFAL for NFC-V */ + EXIT_ON_ERR( + err, + rfalFieldOnAndStartGT()); /* Ensure GT again as other technologies have also been polled */ + gNfcDev.isTechInit = true; + } + + if(!rfalIsGTExpired()) { + return ERR_BUSY; + } + + devCnt = 0; + gNfcDev.isTechInit = false; + gNfcDev.techs2do &= ~RFAL_NFC_POLL_TECH_V; + + err = rfalNfcvPollerCollisionResolution( + RFAL_COMPLIANCE_MODE_NFC, + (gNfcDev.disc.devLimit - gNfcDev.devCnt), + nfcvDevList, + &devCnt); + if((err == ERR_NONE) && (devCnt != 0U)) { + for(i = 0; i < devCnt; + i++) /* Copy devices found form local Nfcf list into global device list */ + { + gNfcDev.devList[gNfcDev.devCnt].type = RFAL_NFC_LISTEN_TYPE_NFCV; + gNfcDev.devList[gNfcDev.devCnt].dev.nfcv = nfcvDevList[i]; + gNfcDev.devCnt++; + } + } + + return ERR_BUSY; + } +#endif /* RFAL_FEATURE_NFCV */ + + /*******************************************************************************/ + /* ST25TB Collision Resolution */ + /*******************************************************************************/ +#if RFAL_FEATURE_ST25TB + if(((gNfcDev.techsFound & RFAL_NFC_POLL_TECH_ST25TB) != 0U) && + ((gNfcDev.techs2do & RFAL_NFC_POLL_TECH_ST25TB) != + 0U)) /* If a ST25TB device was found/detected, perform Collision Resolution */ + { + rfalSt25tbListenDevice st25tbDevList[RFAL_NFC_MAX_DEVICES]; + + if(!gNfcDev.isTechInit) { + EXIT_ON_ERR(err, rfalSt25tbPollerInitialize()); /* Initialize RFAL for ST25TB */ + EXIT_ON_ERR( + err, + rfalFieldOnAndStartGT()); /* Ensure GT again as other technologies have also been polled */ + gNfcDev.isTechInit = true; + } + + if(!rfalIsGTExpired()) { + return ERR_BUSY; + } + + devCnt = 0; + gNfcDev.isTechInit = false; + gNfcDev.techs2do &= ~RFAL_NFC_POLL_TECH_ST25TB; + + err = rfalSt25tbPollerCollisionResolution( + (gNfcDev.disc.devLimit - gNfcDev.devCnt), st25tbDevList, &devCnt); + if((err == ERR_NONE) && (devCnt != 0U)) { + for(i = 0; i < devCnt; + i++) /* Copy devices found form local Nfcf list into global device list */ + { + gNfcDev.devList[gNfcDev.devCnt].type = RFAL_NFC_LISTEN_TYPE_ST25TB; + gNfcDev.devList[gNfcDev.devCnt].dev.st25tb = st25tbDevList[i]; + gNfcDev.devCnt++; + } + } + + return ERR_BUSY; + } +#endif /* RFAL_FEATURE_ST25TB */ + + return ERR_NONE; /* All technologies have been performed */ +} + +/*! + ****************************************************************************** + * \brief Poller Activation + * + * This method Activates a given device according to it's type and + * protocols supported + * + * \param[in] devIt : device's position on the list to be activated + * + * \return ERR_NONE : Operation completed with no error + * \return ERR_BUSY : Operation ongoing + * \return ERR_XXXX : Error occurred + * + ****************************************************************************** + */ +static ReturnCode rfalNfcPollActivation(uint8_t devIt) { + ReturnCode err; + + err = ERR_NONE; + + /* Suppress warning when specific RFAL features have been disabled */ + NO_WARNING(err); + + if(devIt > gNfcDev.devCnt) { + return ERR_WRONG_STATE; + } + + switch(gNfcDev.devList[devIt].type) { + /*******************************************************************************/ + /* AP2P Activation */ + /*******************************************************************************/ +#if RFAL_FEATURE_NFC_DEP + case RFAL_NFC_LISTEN_TYPE_AP2P: + /* Activation has already been performed (ATR_REQ) */ + + gNfcDev.devList[devIt].nfcid = + gNfcDev.devList[devIt].proto.nfcDep.activation.Target.ATR_RES.NFCID3; + gNfcDev.devList[devIt].nfcidLen = RFAL_NFCDEP_NFCID3_LEN; + break; +#endif /* RFAL_FEATURE_NFC_DEP */ + + /*******************************************************************************/ + /* Passive NFC-A Activation */ + /*******************************************************************************/ +#if RFAL_FEATURE_NFCA + case RFAL_NFC_LISTEN_TYPE_NFCA: + + if(!gNfcDev.isTechInit) { + rfalNfcaPollerInitialize(); + gNfcDev.isTechInit = true; + gNfcDev.isOperOngoing = false; + return ERR_BUSY; + } + + if(gNfcDev.devList[devIt].dev.nfca.isSleep) /* Check if desired device is in Sleep */ + { + rfalNfcaSensRes sensRes; + rfalNfcaSelRes selRes; + + if(!gNfcDev.isOperOngoing) { + /* Wake up all cards */ + EXIT_ON_ERR( + err, rfalNfcaPollerCheckPresence(RFAL_14443A_SHORTFRAME_CMD_WUPA, &sensRes)); + gNfcDev.isOperOngoing = true; + } else { + /* Select specific device */ + EXIT_ON_ERR( + err, + rfalNfcaPollerSelect( + gNfcDev.devList[devIt].dev.nfca.nfcId1, + gNfcDev.devList[devIt].dev.nfca.nfcId1Len, + &selRes)); + gNfcDev.devList[devIt].dev.nfca.isSleep = false; + gNfcDev.isOperOngoing = false; + } + return ERR_BUSY; + } + + /* Set NFCID */ + gNfcDev.devList[devIt].nfcid = gNfcDev.devList[devIt].dev.nfca.nfcId1; + gNfcDev.devList[devIt].nfcidLen = gNfcDev.devList[devIt].dev.nfca.nfcId1Len; + + /*******************************************************************************/ + /* Perform protocol specific activation */ + switch(gNfcDev.devList[devIt].dev.nfca.type) { + /*******************************************************************************/ + case RFAL_NFCA_T1T: + + /* No further activation needed for T1T (RID already performed) */ + + gNfcDev.devList[devIt].nfcid = gNfcDev.devList[devIt].dev.nfca.ridRes.uid; + gNfcDev.devList[devIt].nfcidLen = RFAL_T1T_UID_LEN; + + gNfcDev.devList[devIt].rfInterface = RFAL_NFC_INTERFACE_RF; + break; + + case RFAL_NFCA_T2T: + + /* No further activation needed for a T2T */ + + gNfcDev.devList[devIt].rfInterface = RFAL_NFC_INTERFACE_RF; + break; + + /*******************************************************************************/ + case RFAL_NFCA_T4T: /* Device supports ISO-DEP */ + +#if RFAL_FEATURE_ISO_DEP && RFAL_FEATURE_ISO_DEP_POLL + if(!gNfcDev.isOperOngoing) { + /* Perform ISO-DEP (ISO14443-4) activation: RATS and PPS if supported */ + rfalIsoDepInitialize(); + EXIT_ON_ERR( + err, + rfalIsoDepPollAStartActivation( + (rfalIsoDepFSxI)RFAL_ISODEP_FSDI_DEFAULT, + RFAL_ISODEP_NO_DID, + gNfcDev.disc.maxBR, + &gNfcDev.devList[devIt].proto.isoDep)); + + gNfcDev.isOperOngoing = true; + return ERR_BUSY; + } + + err = rfalIsoDepPollAGetActivationStatus(); + if(err != ERR_NONE) { + return err; + } + + gNfcDev.devList[devIt].rfInterface = + RFAL_NFC_INTERFACE_ISODEP; /* NFC-A T4T device activated */ +#else + gNfcDev.devList[devIt].rfInterface = + RFAL_NFC_INTERFACE_RF; /* No ISO-DEP supported activate using RF interface */ +#endif /* RFAL_FEATURE_ISO_DEP_POLL */ + break; + + /*******************************************************************************/ + case RFAL_NFCA_T4T_NFCDEP: /* Device supports both T4T and NFC-DEP */ + case RFAL_NFCA_NFCDEP: /* Device supports NFC-DEP */ + +#if RFAL_FEATURE_NFC_DEP + /* Perform NFC-DEP (P2P) activation: ATR and PSL if supported */ + EXIT_ON_ERR( + err, + rfalNfcNfcDepActivate(&gNfcDev.devList[devIt], RFAL_NFCDEP_COMM_PASSIVE, NULL, 0)); + + gNfcDev.devList[devIt].nfcid = + gNfcDev.devList[devIt].proto.nfcDep.activation.Target.ATR_RES.NFCID3; + gNfcDev.devList[devIt].nfcidLen = RFAL_NFCDEP_NFCID3_LEN; + + gNfcDev.devList[devIt].rfInterface = + RFAL_NFC_INTERFACE_NFCDEP; /* NFC-A P2P device activated */ +#else + gNfcDev.devList[devIt].rfInterface = + RFAL_NFC_INTERFACE_RF; /* No NFC-DEP supported activate using RF interface */ +#endif /* RFAL_FEATURE_NFC_DEP */ + break; + + /*******************************************************************************/ + default: + return ERR_WRONG_STATE; + } + break; +#endif /* RFAL_FEATURE_NFCA */ + + /*******************************************************************************/ + /* Passive NFC-B Activation */ + /*******************************************************************************/ +#if RFAL_FEATURE_NFCB + case RFAL_NFC_LISTEN_TYPE_NFCB: + + if(!gNfcDev.isTechInit) { + rfalNfcbPollerInitialize(); + gNfcDev.isTechInit = true; + gNfcDev.isOperOngoing = false; + return ERR_BUSY; + } + + if(gNfcDev.devList[devIt].dev.nfcb.isSleep) /* Check if desired device is in Sleep */ + { + rfalNfcbSensbRes sensbRes; + uint8_t sensbResLen; + + /* Wake up all cards. SENSB_RES may return collision but the NFCID0 is available to explicitly select NFC-B card via ATTRIB; so error will be ignored here */ + rfalNfcbPollerCheckPresence( + RFAL_NFCB_SENS_CMD_ALLB_REQ, RFAL_NFCB_SLOT_NUM_1, &sensbRes, &sensbResLen); + } + + /* Set NFCID */ + gNfcDev.devList[devIt].nfcid = gNfcDev.devList[devIt].dev.nfcb.sensbRes.nfcid0; + gNfcDev.devList[devIt].nfcidLen = RFAL_NFCB_NFCID0_LEN; + +#if RFAL_FEATURE_ISO_DEP && RFAL_FEATURE_ISO_DEP_POLL + /* Check if device supports ISO-DEP (ISO14443-4) */ + if((gNfcDev.devList[devIt].dev.nfcb.sensbRes.protInfo.FsciProType & + RFAL_NFCB_SENSB_RES_PROTO_ISO_MASK) != 0U) { + if(!gNfcDev.isOperOngoing) { + rfalIsoDepInitialize(); + /* Perform ISO-DEP (ISO14443-4) activation: ATTRIB */ + EXIT_ON_ERR( + err, + rfalIsoDepPollBStartActivation( + (rfalIsoDepFSxI)RFAL_ISODEP_FSDI_DEFAULT, + RFAL_ISODEP_NO_DID, + gNfcDev.disc.maxBR, + 0x00, + &gNfcDev.devList[devIt].dev.nfcb, + NULL, + 0, + &gNfcDev.devList[devIt].proto.isoDep)); + + gNfcDev.isOperOngoing = true; + return ERR_BUSY; + } + + err = rfalIsoDepPollBGetActivationStatus(); + if(err != ERR_NONE) { + return err; + } + + gNfcDev.devList[devIt].rfInterface = + RFAL_NFC_INTERFACE_ISODEP; /* NFC-B T4T device activated */ + break; + } + +#endif /* RFAL_FEATURE_ISO_DEP_POLL */ + + gNfcDev.devList[devIt].rfInterface = + RFAL_NFC_INTERFACE_RF; /* NFC-B device activated */ + break; + +#endif /* RFAL_FEATURE_NFCB */ + + /*******************************************************************************/ + /* Passive NFC-F Activation */ + /*******************************************************************************/ +#if RFAL_FEATURE_NFCF + case RFAL_NFC_LISTEN_TYPE_NFCF: + + rfalNfcfPollerInitialize(gNfcDev.disc.nfcfBR); + +#if RFAL_FEATURE_NFC_DEP + if(rfalNfcfIsNfcDepSupported(&gNfcDev.devList[devIt].dev.nfcf)) { + /* Perform NFC-DEP (P2P) activation: ATR and PSL if supported */ + EXIT_ON_ERR( + err, + rfalNfcNfcDepActivate(&gNfcDev.devList[devIt], RFAL_NFCDEP_COMM_PASSIVE, NULL, 0)); + + /* Set NFCID */ + gNfcDev.devList[devIt].nfcid = + gNfcDev.devList[devIt].proto.nfcDep.activation.Target.ATR_RES.NFCID3; + gNfcDev.devList[devIt].nfcidLen = RFAL_NFCDEP_NFCID3_LEN; + + gNfcDev.devList[devIt].rfInterface = + RFAL_NFC_INTERFACE_NFCDEP; /* NFC-F P2P device activated */ + break; + } +#endif /* RFAL_FEATURE_NFC_DEP */ + + /* Set NFCID */ + gNfcDev.devList[devIt].nfcid = gNfcDev.devList[devIt].dev.nfcf.sensfRes.NFCID2; + gNfcDev.devList[devIt].nfcidLen = RFAL_NFCF_NFCID2_LEN; + + gNfcDev.devList[devIt].rfInterface = + RFAL_NFC_INTERFACE_RF; /* NFC-F T3T device activated */ + break; +#endif /* RFAL_FEATURE_NFCF */ + + /*******************************************************************************/ + /* Passive NFC-V Activation */ + /*******************************************************************************/ +#if RFAL_FEATURE_NFCV + case RFAL_NFC_LISTEN_TYPE_NFCV: + + rfalNfcvPollerInitialize(); + + /* No specific activation needed for a T5T */ + + /* Set NFCID */ + gNfcDev.devList[devIt].nfcid = gNfcDev.devList[devIt].dev.nfcv.InvRes.UID; + gNfcDev.devList[devIt].nfcidLen = RFAL_NFCV_UID_LEN; + + gNfcDev.devList[devIt].rfInterface = + RFAL_NFC_INTERFACE_RF; /* NFC-V T5T device activated */ + break; +#endif /* RFAL_FEATURE_NFCV */ + + /*******************************************************************************/ + /* Passive ST25TB Activation */ + /*******************************************************************************/ +#if RFAL_FEATURE_ST25TB + case RFAL_NFC_LISTEN_TYPE_ST25TB: + + rfalSt25tbPollerInitialize(); + + /* No specific activation needed for a ST25TB */ + + /* Set NFCID */ + gNfcDev.devList[devIt].nfcid = gNfcDev.devList[devIt].dev.st25tb.UID; + gNfcDev.devList[devIt].nfcidLen = RFAL_ST25TB_UID_LEN; + + gNfcDev.devList[devIt].rfInterface = RFAL_NFC_INTERFACE_RF; /* ST25TB device activated */ + break; +#endif /* RFAL_FEATURE_ST25TB */ + + /*******************************************************************************/ + default: + return ERR_WRONG_STATE; + } + + gNfcDev.activeDev = &gNfcDev.devList[devIt]; /* Assign active device to be used further on */ + return ERR_NONE; +} + +/*! + ****************************************************************************** + * \brief Listener Activation + * + * This method handles the listen mode Activation according to the different + * protocols the Reader/Initiator performs + * + * \return ERR_NONE : Operation completed with no error + * \return ERR_BUSY : Operation ongoing + * \return ERR_PROTO : Unexpected frame received + * \return ERR_XXXX : Error occurred + * + ****************************************************************************** + */ +#if RFAL_FEATURE_LISTEN_MODE +static ReturnCode rfalNfcListenActivation(void) { + bool isDataRcvd; + ReturnCode ret; + rfalLmState lmSt; + rfalBitRate bitRate; +#if RFAL_FEATURE_NFC_DEP + uint8_t hdrLen; + + /* Set the header length in NFC-A */ + hdrLen = (RFAL_NFCDEP_SB_LEN + RFAL_NFCDEP_LEN_LEN); +#endif /* RFAL_FEATURE_NFC_DEP */ + + lmSt = rfalListenGetState(&isDataRcvd, &bitRate); + + switch(lmSt) { +#if RFAL_FEATURE_NFCA + /*******************************************************************************/ + case RFAL_LM_STATE_ACTIVE_A: /* NFC-A CE activation */ + case RFAL_LM_STATE_ACTIVE_Ax: + + if(isDataRcvd) /* Check if Reader/Initator has sent some data */ + { + /* Check if received data is a Sleep request */ + if(rfalNfcaListenerIsSleepReq( + gNfcDev.rxBuf.rfBuf, + rfalConvBitsToBytes(gNfcDev.rxLen))) /* Check if received data is a SLP_REQ */ + { + /* Set the Listen Mode in Sleep state */ + EXIT_ON_ERR( + ret, + rfalListenSleepStart( + RFAL_LM_STATE_SLEEP_A, + gNfcDev.rxBuf.rfBuf, + sizeof(gNfcDev.rxBuf.rfBuf), + &gNfcDev.rxLen)); + } + + else if(gNfcDev.disc.activate_after_sak) { + gNfcDev.devList->type = RFAL_NFC_POLL_TYPE_NFCA; + rfalListenSetState(RFAL_LM_STATE_ACTIVE_A); + return ERR_NONE; + } +#if RFAL_FEATURE_ISO_DEP && RFAL_FEATURE_ISO_DEP_LISTEN + /* Check if received data is a valid RATS */ + else if(rfalIsoDepIsRats( + gNfcDev.rxBuf.rfBuf, (uint8_t)rfalConvBitsToBytes(gNfcDev.rxLen))) { + rfalIsoDepAtsParam atsParam; + rfalIsoDepListenActvParam rxParam; + + /* Set ATS parameters */ + atsParam.fsci = (uint8_t)RFAL_ISODEP_DEFAULT_FSCI; + atsParam.fwi = RFAL_ISODEP_DEFAULT_FWI; + atsParam.sfgi = RFAL_ISODEP_DEFAULT_SFGI; + atsParam.didSupport = false; + atsParam.ta = RFAL_ISODEP_ATS_TA_SAME_D; + atsParam.hb = NULL; + atsParam.hbLen = 0; + + /* Set Rx parameters */ + rxParam.rxBuf = + (rfalIsoDepBufFormat*)&gNfcDev.rxBuf + .isoDepBuf; /* PRQA S 0310 # MISRA 11.3 - Intentional safe cast to avoiding large buffer duplication */ + rxParam.rxLen = &gNfcDev.rxLen; + rxParam.isoDepDev = &gNfcDev.devList->proto.isoDep; + rxParam.isRxChaining = &gNfcDev.isRxChaining; + + rfalListenSetState(RFAL_LM_STATE_CARDEMU_4A); /* Set next state CE T4T */ + rfalIsoDepInitialize(); /* Initialize ISO-DEP layer to handle ISO14443-a activation / RATS */ + + /* Set ISO-DEP layer to digest RATS and handle activation */ + EXIT_ON_ERR( + ret, + rfalIsoDepListenStartActivation( + &atsParam, NULL, gNfcDev.rxBuf.rfBuf, gNfcDev.rxLen, rxParam)); + } +#endif /* RFAL_FEATURE_ISO_DEP_LISTEN */ + +#if RFAL_FEATURE_NFC_DEP + + /* Check if received data is a valid ATR_REQ */ + else if(rfalNfcDepIsAtrReq( + &gNfcDev.rxBuf.rfBuf[hdrLen], + (rfalConvBitsToBytes(gNfcDev.rxLen) - hdrLen), + gNfcDev.devList->nfcid)) { + gNfcDev.devList->type = RFAL_NFC_POLL_TYPE_NFCA; + EXIT_ON_ERR( + ret, + rfalNfcNfcDepActivate( + gNfcDev.devList, + RFAL_NFCDEP_COMM_PASSIVE, + &gNfcDev.rxBuf.rfBuf[hdrLen], + (rfalConvBitsToBytes(gNfcDev.rxLen) - hdrLen))); + } +#endif /* RFAL_FEATURE_NFC_DEP */ + + else { + return ERR_PROTO; + } + } + return ERR_BUSY; + +#endif /* RFAL_FEATURE_NFCA */ + +#if RFAL_FEATURE_ISO_DEP && RFAL_FEATURE_ISO_DEP_LISTEN + /*******************************************************************************/ + case RFAL_LM_STATE_CARDEMU_4A: /* T4T ISO-DEP activation */ + + ret = rfalIsoDepListenGetActivationStatus(); + if(ret == ERR_NONE) { + gNfcDev.devList->type = RFAL_NFC_POLL_TYPE_NFCA; + gNfcDev.devList->rfInterface = RFAL_NFC_INTERFACE_ISODEP; + gNfcDev.devList->nfcid = NULL; + gNfcDev.devList->nfcidLen = 0; + } + return ret; +#endif /* RFAL_FEATURE_ISO_DEP_LISTEN */ + + /*******************************************************************************/ + case RFAL_LM_STATE_READY_F: /* NFC-F CE activation */ + + if(isDataRcvd) /* Wait for the first received data */ + { +#if RFAL_FEATURE_NFC_DEP + /* Set the header length in NFC-F */ + hdrLen = RFAL_NFCDEP_LEN_LEN; + + if(rfalNfcDepIsAtrReq( + &gNfcDev.rxBuf.rfBuf[hdrLen], + (rfalConvBitsToBytes(gNfcDev.rxLen) - hdrLen), + gNfcDev.devList->nfcid)) { + gNfcDev.devList->type = RFAL_NFC_POLL_TYPE_NFCF; + EXIT_ON_ERR( + ret, + rfalNfcNfcDepActivate( + gNfcDev.devList, + RFAL_NFCDEP_COMM_PASSIVE, + &gNfcDev.rxBuf.rfBuf[hdrLen], + (rfalConvBitsToBytes(gNfcDev.rxLen) - hdrLen))); + } else +#endif /* RFAL_FEATURE_NFC_DEP */ + { + rfalListenSetState( + RFAL_LM_STATE_CARDEMU_3); /* First data already received - set T3T CE */ + } + } + return ERR_BUSY; + + /*******************************************************************************/ + case RFAL_LM_STATE_CARDEMU_3: /* T3T activated */ + + gNfcDev.devList->type = RFAL_NFC_POLL_TYPE_NFCF; + gNfcDev.devList->rfInterface = RFAL_NFC_INTERFACE_RF; + gNfcDev.devList->nfcid = NULL; + gNfcDev.devList->nfcidLen = 0; + + return ERR_NONE; + +#if RFAL_FEATURE_NFC_DEP + /*******************************************************************************/ + case RFAL_LM_STATE_TARGET_A: /* NFC-DEP activation */ + case RFAL_LM_STATE_TARGET_F: + + ret = rfalNfcDepListenGetActivationStatus(); + if(ret == ERR_NONE) { + gNfcDev.devList->rfInterface = RFAL_NFC_INTERFACE_NFCDEP; + gNfcDev.devList->nfcidLen = RFAL_NFCDEP_NFCID3_LEN; + } + return ret; +#endif /* RFAL_FEATURE_NFC_DEP */ + + /*******************************************************************************/ + case RFAL_LM_STATE_IDLE: /* AP2P activation */ + if(isDataRcvd) /* Check if Reader/Initator has sent some data */ + { + if((gNfcDev.lmMask & RFAL_LM_MASK_ACTIVE_P2P) != 0U) /* Check if AP2P is enabled */ + { +#if RFAL_FEATURE_NFC_DEP + /* Calculate the header length in NFC-A or NFC-F mode*/ + hdrLen = + ((bitRate == RFAL_BR_106) ? (RFAL_NFCDEP_SB_LEN + RFAL_NFCDEP_LEN_LEN) : + RFAL_NFCDEP_LEN_LEN); + + if(rfalNfcDepIsAtrReq( + &gNfcDev.rxBuf.rfBuf[hdrLen], + (rfalConvBitsToBytes(gNfcDev.rxLen) - hdrLen), + NULL)) { + gNfcDev.devList->type = RFAL_NFC_POLL_TYPE_AP2P; + rfalSetMode((RFAL_MODE_LISTEN_ACTIVE_P2P), bitRate, bitRate); + EXIT_ON_ERR( + ret, + rfalNfcNfcDepActivate( + gNfcDev.devList, + RFAL_NFCDEP_COMM_ACTIVE, + &gNfcDev.rxBuf.rfBuf[hdrLen], + (rfalConvBitsToBytes(gNfcDev.rxLen) - hdrLen))); + } else +#endif /* RFAL_FEATURE_NFC_DEP */ + { + return ERR_PROTO; + } + } + } + return ERR_BUSY; + + /*******************************************************************************/ + case RFAL_LM_STATE_READY_A: + case RFAL_LM_STATE_READY_Ax: + case RFAL_LM_STATE_SLEEP_A: + case RFAL_LM_STATE_SLEEP_AF: + return ERR_BUSY; + + /*******************************************************************************/ + case RFAL_LM_STATE_POWER_OFF: + return ERR_LINK_LOSS; + + default: /* Wait for activation */ + break; + } + + return ERR_INTERNAL; +} +#endif /* RFAL_FEATURE_LISTEN_MODE */ + +/*! + ****************************************************************************** + * \brief Poller NFC DEP Activate + * + * This method performs NFC-DEP Activation + * + * \param[in] device : device info + * \param[in] commMode : communication mode (Passive/Active) + * \param[in] atrReq : received ATR_REQ + * \param[in] atrReqLen : received ATR_REQ size + * + * \return ERR_NONE : Operation completed with no error + * \return ERR_BUSY : Operation ongoing + * \return ERR_XXXX : Error occurred + * + ****************************************************************************** + */ +#if RFAL_FEATURE_NFC_DEP +static ReturnCode rfalNfcNfcDepActivate( + rfalNfcDevice* device, + rfalNfcDepCommMode commMode, + const uint8_t* atrReq, + uint16_t atrReqLen) { + rfalNfcDepAtrParam initParam; + + /* Suppress warnings if Listen mode is disabled */ + NO_WARNING(atrReq); + NO_WARNING(atrReqLen); + + /* If we are in Poll mode */ + if(rfalNfcIsRemDevListener(device->type)) { + /*******************************************************************************/ + /* If Passive F use the NFCID2 retrieved from SENSF */ + if(device->type == RFAL_NFC_LISTEN_TYPE_NFCF) { + initParam.nfcid = device->dev.nfcf.sensfRes.NFCID2; + initParam.nfcidLen = RFAL_NFCF_NFCID2_LEN; + } else { + initParam.nfcid = gNfcDev.disc.nfcid3; + initParam.nfcidLen = RFAL_NFCDEP_NFCID3_LEN; + } + + initParam.BS = RFAL_NFCDEP_Bx_NO_HIGH_BR; + initParam.BR = RFAL_NFCDEP_Bx_NO_HIGH_BR; + initParam.DID = RFAL_NFCDEP_DID_NO; + initParam.NAD = RFAL_NFCDEP_NAD_NO; + initParam.LR = RFAL_NFCDEP_LR_254; + initParam.GB = gNfcDev.disc.GB; + initParam.GBLen = gNfcDev.disc.GBLen; + initParam.commMode = commMode; + initParam.operParam = + (RFAL_NFCDEP_OPER_FULL_MI_EN | RFAL_NFCDEP_OPER_EMPTY_DEP_DIS | + RFAL_NFCDEP_OPER_ATN_EN | RFAL_NFCDEP_OPER_RTOX_REQ_EN); + + rfalNfcDepInitialize(); + /* Perform NFC-DEP (P2P) activation: ATR and PSL if supported */ + return rfalNfcDepInitiatorHandleActivation( + &initParam, gNfcDev.disc.maxBR, &device->proto.nfcDep); + } + /* If we are in Listen mode */ +#if RFAL_FEATURE_LISTEN_MODE + else if(rfalNfcIsRemDevPoller(device->type)) { + rfalNfcDepListenActvParam actvParams; + rfalNfcDepTargetParam targetParam; + + ST_MEMCPY(targetParam.nfcid3, (uint8_t*)gNfcDev.disc.nfcid3, RFAL_NFCDEP_NFCID3_LEN); + targetParam.bst = RFAL_NFCDEP_Bx_NO_HIGH_BR; + targetParam.brt = RFAL_NFCDEP_Bx_NO_HIGH_BR; + targetParam.to = RFAL_NFCDEP_WT_TRG_MAX_L13; /* [LLCP] 1.3 6.2.1 */ + targetParam.ppt = rfalNfcDepLR2PP(RFAL_NFCDEP_LR_254); + if(gNfcDev.disc.GBLen >= RFAL_NFCDEP_GB_MAX_LEN) { + return ERR_PARAM; + } + targetParam.GBtLen = gNfcDev.disc.GBLen; + if(gNfcDev.disc.GBLen > 0U) { + ST_MEMCPY(targetParam.GBt, gNfcDev.disc.GB, gNfcDev.disc.GBLen); + } + targetParam.operParam = + (RFAL_NFCDEP_OPER_FULL_MI_EN | RFAL_NFCDEP_OPER_EMPTY_DEP_DIS | + RFAL_NFCDEP_OPER_ATN_EN | RFAL_NFCDEP_OPER_RTOX_REQ_EN); + targetParam.commMode = commMode; + + /* Set activation buffer (including header) for NFC-DEP */ + actvParams.rxBuf = + (rfalNfcDepBufFormat*)&gNfcDev.rxBuf + .nfcDepBuf; /* PRQA S 0310 # MISRA 11.3 - Intentional safe cast to avoiding large buffer duplication */ + actvParams.rxLen = &gNfcDev.rxLen; + actvParams.isRxChaining = &gNfcDev.isRxChaining; + actvParams.nfcDepDev = &gNfcDev.devList->proto.nfcDep; + + rfalListenSetState( + ((device->type == RFAL_NFC_POLL_TYPE_NFCA) ? RFAL_LM_STATE_TARGET_A : + RFAL_LM_STATE_TARGET_F)); + + rfalNfcDepInitialize(); + /* Perform NFC-DEP (P2P) activation: send ATR_RES and handle activation */ + return rfalNfcDepListenStartActivation(&targetParam, atrReq, atrReqLen, actvParams); + } +#endif /* RFAL_FEATURE_LISTEN_MODE */ + + else { + return ERR_INTERNAL; + } +} +#endif /* RFAL_FEATURE_NFC_DEP */ + +/*! + ****************************************************************************** + * \brief Poller NFC Deactivate + * + * This method Deactivates the device if a deactivation procedure exists + * + * \return ERR_NONE : Operation completed with no error + * \return ERR_BUSY : Operation ongoing + * \return ERR_XXXX : Error occurred + * + ****************************************************************************** + */ +static ReturnCode rfalNfcDeactivation(void) { + /* Check if a device has been activated */ + if(gNfcDev.activeDev != NULL) { + if(rfalNfcIsRemDevListener( + gNfcDev.activeDev->type)) /* Listen mode no additional deactivation to be performed*/ + { +#ifndef RFAL_NFC_SKIP_DEACT + switch(gNfcDev.activeDev->rfInterface) { + /*******************************************************************************/ + case RFAL_NFC_INTERFACE_RF: + break; /* No specific deactivation to be performed */ + + /*******************************************************************************/ +#if RFAL_FEATURE_ISO_DEP && RFAL_FEATURE_ISO_DEP_POLL + case RFAL_NFC_INTERFACE_ISODEP: + rfalIsoDepDeselect(); /* Send a Deselect to device */ + break; +#endif /* RFAL_FEATURE_ISO_DEP_POLL */ + + /*******************************************************************************/ +#if RFAL_FEATURE_NFC_DEP + case RFAL_NFC_INTERFACE_NFCDEP: + switch(gNfcDev.activeDev->type) { + case RFAL_NFC_LISTEN_TYPE_AP2P: + rfalNfcDepRLS(); /* Send a Release to device */ + break; + default: + rfalNfcDepDSL(); /* Send a Deselect to device */ + break; + } + break; +#endif /* RFAL_FEATURE_NFC_DEP */ + + default: + return ERR_REQUEST; + } +#endif /* RFAL_NFC_SKIP_DEACT */ + } + } + +#if RFAL_FEATURE_WAKEUP_MODE + rfalWakeUpModeStop(); +#endif /* RFAL_FEATURE_WAKEUP_MODE */ + +#if RFAL_FEATURE_LISTEN_MODE + rfalListenStop(); +#else + rfalFieldOff(); +#endif + + gNfcDev.activeDev = NULL; + return ERR_NONE; +} diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_nfcDep.c b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_nfcDep.c new file mode 100644 index 00000000000..b1fad78b81c --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_nfcDep.c @@ -0,0 +1,2741 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: NFCC firmware + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_nfcDep.c + * + * \author Gustavo Patricio + * + * \brief Implementation of NFC-DEP protocol + * + * NFC-DEP is also known as NFCIP - Near Field Communication + * Interface and Protocol + * + * This implementation was based on the following specs: + * - NFC Forum Digital 1.1 + * - ECMA 340 3rd Edition 2013 + * + */ + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "../include/rfal_nfcDep.h" +#include "../include/rfal_nfcf.h" +#include "../utils.h" + +/* + ****************************************************************************** + * ENABLE SWITCH + ****************************************************************************** + */ + +#if RFAL_FEATURE_NFC_DEP + +/* Check for valid Block/Payload length Digital 2.0 Table 90*/ +#if((RFAL_FEATURE_NFC_DEP_BLOCK_MAX_LEN != 64) && (RFAL_FEATURE_NFC_DEP_BLOCK_MAX_LEN != 128) && \ + (RFAL_FEATURE_NFC_DEP_BLOCK_MAX_LEN != 192) && (RFAL_FEATURE_NFC_DEP_BLOCK_MAX_LEN != 254)) +#error \ + " RFAL: Invalid NFC-DEP Block Max length. Please change RFAL_FEATURE_NFC_DEP_BLOCK_MAX_LEN. " +#endif + +/* Check for valid PDU length */ +#if((RFAL_FEATURE_NFC_DEP_PDU_MAX_LEN < RFAL_FEATURE_NFC_DEP_BLOCK_MAX_LEN)) +#error " RFAL: Invalid NFC-DEP PDU Max length. Please change RFAL_FEATURE_NFC_DEP_PDU_MAX_LEN. " +#endif + +/* + ****************************************************************************** + * DEFINES + ****************************************************************************** + */ +#define NFCIP_ATR_RETRY_MAX 2U /*!< Max consecutive retrys of an ATR REQ with transm error*/ + +#define NFCIP_PSLPAY_LEN (2U) /*!< PSL Payload length (BRS + FSL) */ +#define NFCIP_PSLREQ_LEN \ + (3U + RFAL_NFCDEP_LEN_LEN) /*!< PSL REQ length (incl LEN) */ +#define NFCIP_PSLRES_LEN \ + (3U + RFAL_NFCDEP_LEN_LEN) /*!< PSL RES length (incl LEN) */ + +#define NFCIP_ATRREQ_BUF_LEN \ + (RFAL_NFCDEP_ATRREQ_MAX_LEN + RFAL_NFCDEP_LEN_LEN) /*!< ATR REQ max length (incl LEN) */ +#define NFCIP_ATRRES_BUF_LEN \ + (RFAL_NFCDEP_ATRRES_MAX_LEN + RFAL_NFCDEP_LEN_LEN) /*!< ATR RES max length (incl LEN) */ + +#define NFCIP_RLSREQ_LEN \ + (3U + RFAL_NFCDEP_LEN_LEN) /*!< RLS REQ length (incl LEN) */ +#define NFCIP_RLSRES_LEN \ + (3U + RFAL_NFCDEP_LEN_LEN) /*!< RSL RES length (incl LEN) */ +#define NFCIP_RLSRES_MIN \ + (2U + RFAL_NFCDEP_LEN_LEN) /*!< Minimum length for a RLS RES (incl LEN) */ + +#define NFCIP_DSLREQ_LEN \ + (3U + RFAL_NFCDEP_LEN_LEN) /*!< DSL REQ length (incl LEN) */ +#define NFCIP_DSLRES_LEN \ + (3U + RFAL_NFCDEP_LEN_LEN) /*!< DSL RES length (incl LEN) */ +#define NFCIP_DSLRES_MIN \ + (2U + RFAL_NFCDEP_LEN_LEN) /*!< Minimum length for a DSL RES (incl LEN) */ + +#define NFCIP_DSLRES_MAX_LEN \ + (3U + RFAL_NFCDEP_LEN_LEN) /*!< Maximum length for a DSL RES (incl LEN) */ +#define NFCIP_RLSRES_MAX_LEN \ + (3U + RFAL_NFCDEP_LEN_LEN) /*!< Minimum length for a RLS RES (incl LEN) */ +#define NFCIP_TARGET_RES_MAX \ + (MAX(NFCIP_RLSRES_MAX_LEN, NFCIP_DSLRES_MAX_LEN)) /*!< Max target control res length */ + +#define NFCIP_NO_FWT RFAL_FWT_NONE /*!< No FWT value - Target Mode */ +#define NFCIP_INIT_MIN_RTOX 1U /*!< Minimum RTOX value Digital 1.0 14.8.4.1 */ +#define NFCIP_INIT_MAX_RTOX 59U /*!< Maximum RTOX value Digital 1.0 14.8.4.1 */ + +#define NFCIP_TARG_MIN_RTOX 1U /*!< Minimum target RTOX value Digital 1.0 14.8.4.1 */ +#define NFCIP_TARG_MAX_RTOX 59U /*!< Maximum target RTOX value Digital 1.0 14.8.4.1 */ + +#define NFCIP_TRECOV 1280U /*!< Digital 1.0 A.10 Trecov */ + +#define NFCIP_TIMEOUT_ADJUSTMENT \ + 3072U /*!< Timeout Adjustment to compensate timing from end of Tx to end of frame */ +#define NFCIP_RWT_ACTIVATION \ + (0x1000001U + \ + NFCIP_TIMEOUT_ADJUSTMENT) /*!< Digital 2.2 B.11 RWT ACTIVATION 2^24 + RWT Delta + Adjustment*/ +#define NFCIP_RWT_ACM_ACTIVATION \ + (0x200001U + \ + NFCIP_TIMEOUT_ADJUSTMENT) /*!< Digital 2.2 B.11 RWT ACTIVATION 2^21 + RWT Delta + Adjustment*/ + +#define RFAL_NFCDEP_HEADER_PAD \ + (RFAL_NFCDEP_DEPREQ_HEADER_LEN - \ + RFAL_NFCDEP_LEN_MIN) /*!< Difference between expected rcvd header len and max foreseen */ + +#ifndef RFAL_NFCDEP_MAX_TX_RETRYS +#define RFAL_NFCDEP_MAX_TX_RETRYS \ + (uint8_t)3U /*!< Number of retransmit retyrs */ +#endif /* RFAL_NFCDEP_MAX_TX_RETRYS */ + +#ifndef RFAL_NFCDEP_TO_RETRYS +#define RFAL_NFCDEP_TO_RETRYS \ + (uint8_t)3U /*!< Number of retrys for Timeout */ +#endif /* RFAL_NFCDEP_TO_RETRYS */ + +#ifndef RFAL_NFCDEP_MAX_RTOX_RETRYS +#define RFAL_NFCDEP_MAX_RTOX_RETRYS \ + (uint8_t)10U /*!< Number of retrys for RTOX Digital 2.0 17.12.4.3 */ +#endif /* RFAL_NFCDEP_MAX_RTOX_RETRYS */ + +#ifndef RFAL_NFCDEP_MAX_NACK_RETRYS +#define RFAL_NFCDEP_MAX_NACK_RETRYS \ + (uint8_t)3U /*!< Number of retrys for NACK */ +#endif /* RFAL_NFCDEP_MAX_NACK_RETRYS */ + +#ifndef RFAL_NFCDEP_MAX_ATN_RETRYS +#define RFAL_NFCDEP_MAX_ATN_RETRYS \ + (uint8_t)3U /*!< Number of retrys for ATN */ +#endif /* RFAL_NFCDEP_MAX_ATN_RETRYS */ + +#define NFCIP_MIN_TXERROR_LEN \ + 4U /*!< Minimum frame length with error to be ignored Digital 1.0 14.12.5.4 */ + +#define NFCIP_REQ (uint8_t)0xD4U /*!= NFCIP_ST_INIT_IDLE) && \ + ((st) <= \ + NFCIP_ST_INIT_RLS)) /*!< Checks if module is set as Initiator */ +#define nfcipIsTarget(st) \ + (!nfcipIsInitiator( \ + st)) /*!< Checks if module is set as Target */ + +#define nfcipIsBRAllowed(br, mBR) \ + (((1U << (br)) & (mBR)) != \ + 0U) /*!< Checks bit rate is allowed by given mask */ + +#define nfcipIsEmptyDEPEnabled(op) \ + (!nfcipIsEmptyDEPDisabled( \ + op)) /*!< Checks if empty payload is allowed by operation config NCI 1.0 Table 81 */ +#define nfcipIsEmptyDEPDisabled(op) \ + (((op) & RFAL_NFCDEP_OPER_EMPTY_DEP_DIS) != \ + 0U) /*!< Checks if empty payload is not allowed by operation config NCI 1.0 Table 81 */ + +#define nfcipIsRTOXReqEnabled(op) \ + (!nfcipIsRTOXReqDisabled( \ + op)) /*!< Checks if send a RTOX_REQ is allowed by operation config NCI 1.0 Table 81 */ +#define nfcipIsRTOXReqDisabled(op) \ + (((op) & RFAL_NFCDEP_OPER_RTOX_REQ_DIS) != \ + 0U) /*!< Checks if send a RTOX_REQ is not allowed by operation config NCI 1.0 Table 81 */ + +/*! Checks if isDeactivating callback is set and calls it, otherwise returns false */ +#define nfcipIsDeactivationPending() \ + ((gNfcip.isDeactivating == NULL) ? false : gNfcip.isDeactivating()) + +/*! Returns the RWT Activation according to the current communication mode */ +#define nfcipRWTActivation() \ + ((gNfcip.cfg.commMode == RFAL_NFCDEP_COMM_ACTIVE) ? NFCIP_RWT_ACM_ACTIVATION : \ + NFCIP_RWT_ACTIVATION) + +#define nfcipRTOXAdjust(v) \ + ((v) - ((v) >> 3)) /*!< Adjust RTOX timer value to a percentage of the total, current 88% */ + +/*******************************************************************************/ + +// timerPollTimeoutValue is necessary after timerCalculateTimeout so that system will wake up upon timer timeout. +#define nfcipTimerStart(timer, time_ms) \ + do { \ + platformTimerDestroy(timer); \ + (timer) = platformTimerCreate((uint16_t)(time_ms)); \ + } while(0) /*!< Configures and starts the RTOX timer */ +#define nfcipTimerisExpired(timer) \ + platformTimerIsExpired(timer) /*!< Checks RTOX timer has expired */ +#define nfcipTimerDestroy(timer) \ + platformTimerDestroy(timer) /*!< Destroys RTOX timer */ + +#define nfcipLogE(...) /*!< Macro for the error log method */ +#define nfcipLogW(...) /*!< Macro for the warning log method */ +#define nfcipLogI(...) /*!< Macro for the info log method */ +#define nfcipLogD(...) /*!< Macro for the debug log method */ + +/*! Digital 1.1 - 16.12.5.2 The Target SHALL NOT attempt any error recovery and remains in Rx mode upon Transmission or a Protocol Error */ +#define nfcDepReEnableRx(rxB, rxBL, rxL) \ + rfalTransceiveBlockingTx( \ + NULL, \ + 0, \ + (rxB), \ + (rxBL), \ + (rxL), \ + (RFAL_TXRX_FLAGS_DEFAULT | (uint32_t)RFAL_TXRX_FLAGS_NFCIP1_ON), \ + RFAL_FWT_NONE) + +/* + ****************************************************************************** + * LOCAL DATA TYPES + ****************************************************************************** + */ + +/*! Struct that holds all DEP parameters/configs for the following communications */ +typedef struct { + uint8_t did; /*!< Device ID (DID) to be used */ + + uint8_t* txBuf; /*!< Pointer to the Tx buffer to be sent */ + uint16_t txBufLen; /*!< Length of the data in the txBuf */ + uint8_t txBufPaylPos; /*!< Position inside txBuf where data starts */ + bool txChaining; /*!< Flag indicating chaining on transmission */ + + uint8_t* rxBuf; /*!< Pointer to the Rx buffer for incoming data */ + uint16_t rxBufLen; /*!< Length of the data in the rxBuf */ + uint8_t rxBufPaylPos; /*!< Position inside rxBuf where data is to be placed*/ + + uint32_t fwt; /*!< Frame Waiting Time (FWT) to be used */ + uint32_t dFwt; /*!< Delta Frame Waiting Time (dFWT) to be used */ + uint16_t fsc; /*!< Frame Size (FSC) to be used */ + +} rfalNfcDepDEPParams; + +/*! NFCIP module states */ +typedef enum { + NFCIP_ST_IDLE, + NFCIP_ST_INIT_IDLE, + NFCIP_ST_INIT_ATR, + NFCIP_ST_INIT_PSL, + NFCIP_ST_INIT_DEP_IDLE, + NFCIP_ST_INIT_DEP_TX, + NFCIP_ST_INIT_DEP_RX, + NFCIP_ST_INIT_DEP_ATN, + NFCIP_ST_INIT_DSL, + NFCIP_ST_INIT_RLS, + + NFCIP_ST_TARG_WAIT_ATR, + NFCIP_ST_TARG_WAIT_ACTV, + NFCIP_ST_TARG_DEP_IDLE, + NFCIP_ST_TARG_DEP_RX, + NFCIP_ST_TARG_DEP_RTOX, + NFCIP_ST_TARG_DEP_TX, + NFCIP_ST_TARG_DEP_SLEEP +} rfalNfcDepState; + +/*! NFCIP commands (Request, Response) */ +typedef enum { + NFCIP_CMD_ATR_REQ = 0x00, + NFCIP_CMD_ATR_RES = 0x01, + NFCIP_CMD_WUP_REQ = 0x02, + NFCIP_CMD_WUP_RES = 0x03, + NFCIP_CMD_PSL_REQ = 0x04, + NFCIP_CMD_PSL_RES = 0x05, + NFCIP_CMD_DEP_REQ = 0x06, + NFCIP_CMD_DEP_RES = 0x07, + NFCIP_CMD_DSL_REQ = 0x08, + NFCIP_CMD_DSL_RES = 0x09, + NFCIP_CMD_RLS_REQ = 0x0A, + NFCIP_CMD_RLS_RES = 0x0B +} rfalNfcDepCmd; + +/*! Struct that holds all NFCIP data */ +typedef struct { + rfalNfcDepConfigs cfg; /*!< Holds the current configuration to be used */ + + rfalNfcDepState state; /*!< Current state of the NFCIP module */ + uint8_t pni; /*!< Packet Number Information (PNI) counter */ + + uint8_t lastCmd; /*!< Last command sent */ + uint8_t lastPFB; /*!< Last PFB sent */ + uint8_t lastPFBnATN; /*!< Last PFB sent (excluding ATN) */ + uint8_t lastRTOX; /*!< Last RTOX value sent */ + + uint8_t cntTxRetrys; /*!< Retransmissions counter */ + uint8_t cntTORetrys; /*!< Timeouts counter */ + uint8_t cntRTOXRetrys; /*!< RTOX counter */ + uint8_t cntNACKRetrys; /*!< NACK counter */ + uint8_t cntATNRetrys; /*!< Attention (ATN) counter */ + + uint16_t fsc; /*!< Current Frame Size (FSC) to be used */ + bool isTxChaining; /*!< Flag for chaining on Transmission */ + bool isRxChaining; /*!< Flag for chaining on Reception */ + uint8_t* txBuf; /*!< Pointer to the Tx buffer to be sent */ + uint8_t* rxBuf; /*!< Pointer to the Rx buffer for incoming data */ + uint16_t txBufLen; /*!< Length of the data in the txBuf */ + uint16_t rxBufLen; /*!< Length of rxBuf buffer */ + uint16_t* rxRcvdLen; /*!< Length of the data in the rxBuf */ + uint8_t txBufPaylPos; /*!< Position in txBuf where data starts */ + uint8_t rxBufPaylPos; /*!< Position in rxBuf where data is to be placed */ + bool* isChaining; /*!< Flag for chaining on Reception */ + + rfalNfcDepDevice* nfcDepDev; /*!< Pointer to NFC-DEP device info */ + + uint32_t RTOXTimer; /*!< Timer used for RTOX */ + rfalNfcDepDeactCallback isDeactivating; /*!< Deactivating flag check callback */ + + bool isReqPending; /*!< Flag pending REQ from Target activation */ + bool isTxPending; /*!< Flag pending DEP Block while waiting RTOX Ack */ + bool isWait4RTOX; /*!< Flag for waiting RTOX Ack */ + + rfalNfcDepPduTxRxParam PDUParam; /*!< PDU TxRx params */ + uint16_t PDUTxPos; /*!< PDU Tx position */ + uint16_t PDURxPos; /*!< PDU Rx position */ + bool isPDURxChaining; /*!< PDU Transceive chaining flag */ +} rfalNfcDep; + +/* + ****************************************************************************** + * LOCAL VARIABLES + ****************************************************************************** + */ + +static rfalNfcDep gNfcip; /*!< NFCIP module instance */ + +/* + ****************************************************************************** + * LOCAL FUNCTION PROTOTYPES + ****************************************************************************** + */ + +static ReturnCode nfcipTxRx( + rfalNfcDepCmd cmd, + uint8_t* txBuf, + uint32_t fwt, + uint8_t* paylBuf, + uint8_t paylBufLen, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rxActLen); +static ReturnCode nfcipTx( + rfalNfcDepCmd cmd, + uint8_t* txBuf, + uint8_t* paylBuf, + uint16_t paylLen, + uint8_t pfbData, + uint32_t fwt); +static ReturnCode nfcipDEPControlMsg(uint8_t pfb, uint8_t RTOX); +static ReturnCode nfcipInitiatorHandleDEP( + ReturnCode rxRes, + uint16_t rxLen, + uint16_t* outActRxLen, + bool* outIsChaining); +static ReturnCode + nfcipTargetHandleRX(ReturnCode rxRes, uint16_t* outActRxLen, bool* outIsChaining); +static ReturnCode nfcipTargetHandleActivation(rfalNfcDepDevice* nfcDepDev, uint8_t* outBRS); + +/*! + ****************************************************************************** + * \brief NFCIP Configure + * + * Configures the nfcip layer with the given configurations + * + * \param[in] cfg : nfcip configuration for following communication + ****************************************************************************** + */ +static void nfcipConfig(const rfalNfcDepConfigs* cfg); + +/*! + ****************************************************************************** + * \brief Set DEP parameters + * + * This method sets the parameters/configs for following Data Exchange + * Sets the nfcip module state according to the role it is configured + * + * + * \warning To be used only after proper Initiator/Target activation: + * nfcipTargetHandleActivation() or nfcipInitiatorActivate() has + * returned success + * + * This must be called before nfcipRun() in case of Target to pass + * rxBuffer + * + * Everytime some data needs to be transmitted call this to set it and + * call nfcipRun() until done or error + * + * \param[in] DEPParams : the parameters to be used during Data Exchange + ****************************************************************************** + */ +static void nfcipSetDEPParams(const rfalNfcDepDEPParams* DEPParams); + +/*! + ****************************************************************************** + * \brief NFCIP run protocol + * + * This method handles all the nfcip protocol during Data Exchange (DEP + * requests and responses). + * + * A data exchange cycle is considered a DEP REQ and a DEP RES. + * + * In case of Tx chaining(MI) must signal it with nfcipSetDEPParams() + * In case of Rx chaining(MI) outIsChaining will be set to true and the + * current data returned + * + * \param[out] outActRxLen : data received length + * \param[out] outIsChaining : true if other peer is performing chaining(MI) + * + * \return ERR_NONE : Data exchange cycle completed successfully + * \return ERR_TIMEOUT : Timeout occurred + * \return ERR_PROTO : Protocol error occurred + * \return ERR_AGAIN : Other peer is doing chaining(MI), current block + * was received successfully call again until complete + * + ****************************************************************************** + */ +static ReturnCode nfcipRun(uint16_t* outActRxLen, bool* outIsChaining); + +/*! + ****************************************************************************** + * \brief Transmission method + * + * This method checks if the current communication is Active or Passive + * and performs the necessary procedures for each communication type + * + * Transmits the data hold in txBuf + * + * \param[in] txBuf : buffer to transmit + * \param[in] txBufLen : txBuffer capacity + * \param[in] fwt : fwt for current Tx + * + * \return ERR_NONE : No error + ****************************************************************************** + */ +static ReturnCode nfcipDataTx(uint8_t* txBuf, uint16_t txBufLen, uint32_t fwt); + +/*! + ****************************************************************************** + * \brief Reception method + * + * This method checks if the current communication is Active or Passive + * and calls the appropriate reception method + * + * Copies incoming data to rxBuf + * + * \param[in] blocking : reception is to be done blocking or non-blocking + * + * \return ERR_BUSY : Busy + * \return ERR_NONE : No error + ****************************************************************************** + */ +static ReturnCode nfcipDataRx(bool blocking); + +/* + ****************************************************************************** + * LOCAL FUNCTIONS + ****************************************************************************** + */ + +/*******************************************************************************/ + +/*******************************************************************************/ +static bool nfcipDxIsSupported(uint8_t Dx, uint8_t BRx, uint8_t BSx) { + uint8_t Bx; + + /* Take the min of the possible bit rates, we'll use one for both directions */ + Bx = MIN(BRx, BSx); + + /* Lower bit rates must be supported for P2P */ + if((Dx <= (uint8_t)RFAL_NFCDEP_Dx_04_424)) { + return true; + } + + if((Dx == (uint8_t)RFAL_NFCDEP_Dx_08_848) && (Bx >= (uint8_t)RFAL_NFCDEP_Bx_08_848)) { + return true; + } + + return false; +} + +/*******************************************************************************/ +static ReturnCode nfcipTxRx( + rfalNfcDepCmd cmd, + uint8_t* txBuf, + uint32_t fwt, + uint8_t* paylBuf, + uint8_t paylBufLen, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rxActLen) { + ReturnCode ret; + + if((cmd == NFCIP_CMD_DEP_REQ) || + (cmd == NFCIP_CMD_DEP_RES)) /* this method cannot be used for DEPs */ + { + return ERR_PARAM; + } + + /* Assign the global params for this TxRx */ + gNfcip.rxBuf = rxBuf; + gNfcip.rxBufLen = rxBufLen; + gNfcip.rxRcvdLen = rxActLen; + + /*******************************************************************************/ + /* Transmission */ + /*******************************************************************************/ + if(txBuf != NULL) /* if nothing to Tx, just do Rx */ + { + EXIT_ON_ERR(ret, nfcipTx(cmd, txBuf, paylBuf, paylBufLen, 0, fwt)); + } + + /*******************************************************************************/ + /* Reception */ + /*******************************************************************************/ + ret = nfcipDataRx(true); + if(ret != ERR_NONE) { + return ret; + } + + /*******************************************************************************/ + *rxActLen = *rxBuf; /* Use LEN byte instead due to with/without CRC modes */ + return ERR_NONE; /* Tx and Rx completed successfully */ +} + +/*******************************************************************************/ +static ReturnCode nfcipDEPControlMsg(uint8_t pfb, uint8_t RTOX) { + uint8_t ctrlMsg[20]; + rfalNfcDepCmd depCmd; + uint32_t fwt; + + /*******************************************************************************/ + /* Calculate Cmd and fwt to be used */ + /*******************************************************************************/ + depCmd = + ((gNfcip.cfg.role == RFAL_NFCDEP_ROLE_TARGET) ? NFCIP_CMD_DEP_RES : NFCIP_CMD_DEP_REQ); + fwt = + ((gNfcip.cfg.role == RFAL_NFCDEP_ROLE_TARGET) ? + NFCIP_NO_FWT : + (nfcip_PFBisSTO(pfb) ? ((RTOX * gNfcip.cfg.fwt) + gNfcip.cfg.dFwt) : + (gNfcip.cfg.fwt + gNfcip.cfg.dFwt))); + + if(nfcip_PFBisSTO(pfb)) { + ctrlMsg[RFAL_NFCDEP_DEPREQ_HEADER_LEN] = RTOX; + return nfcipTx( + depCmd, ctrlMsg, &ctrlMsg[RFAL_NFCDEP_DEPREQ_HEADER_LEN], sizeof(uint8_t), pfb, fwt); + } else { + return nfcipTx(depCmd, ctrlMsg, NULL, 0, pfb, fwt); + } +} + +/*******************************************************************************/ +static void nfcipClearCounters(void) { + gNfcip.cntATNRetrys = 0; + gNfcip.cntNACKRetrys = 0; + gNfcip.cntTORetrys = 0; + gNfcip.cntTxRetrys = 0; + gNfcip.cntRTOXRetrys = 0; +} + +/*******************************************************************************/ +static ReturnCode nfcipInitiatorHandleDEP( + ReturnCode rxRes, + uint16_t rxLen, + uint16_t* outActRxLen, + bool* outIsChaining) { + ReturnCode ret; + uint8_t nfcDepLen; + uint8_t rxMsgIt; + uint8_t rxPFB; + uint8_t rxRTOX; + uint8_t optHdrLen; + + ret = ERR_INTERNAL; + rxMsgIt = 0; + optHdrLen = 0; + + *outActRxLen = 0; + *outIsChaining = false; + + /*******************************************************************************/ + /* Handle reception errors */ + /*******************************************************************************/ + switch(rxRes) { + /*******************************************************************************/ + /* Timeout -> Digital 1.0 14.15.5.6 */ + case ERR_TIMEOUT: + + nfcipLogI(" NFCIP(I) TIMEOUT TORetrys:%d \r\n", gNfcip.cntTORetrys); + + /* Digital 1.0 14.15.5.6 - If nTO >= Max raise protocol error */ + if(gNfcip.cntTORetrys++ >= RFAL_NFCDEP_TO_RETRYS) { + return ERR_PROTO; + } + + /*******************************************************************************/ + /* Upon Timeout error, if Deactivation is pending, no more error recovery + * will be done #54. + * This is used to address the issue some devices that havea big TO. + * Normally LLCP layer has timeout already, and NFCIP layer is still + * running error handling, retrying ATN/NACKs */ + /*******************************************************************************/ + if(nfcipIsDeactivationPending()) { + nfcipLogI(" skipping error recovery due deactivation pending \r\n"); + return ERR_TIMEOUT; + } + + /* Digital 1.0 14.15.5.6 1) If last PDU was NACK */ + if(nfcip_PFBisRNACK(gNfcip.lastPFB)) { + /* Digital 1.0 14.15.5.6 2) if NACKs failed raise protocol error */ + if(gNfcip.cntNACKRetrys++ >= RFAL_NFCDEP_MAX_NACK_RETRYS) { + return ERR_PROTO; + } + + /* Send NACK */ + nfcipLogI(" NFCIP(I) Sending NACK retry: %d \r\n", gNfcip.cntNACKRetrys); + EXIT_ON_ERR(ret, nfcipDEPControlMsg(nfcip_PFBRPDU_NACK(gNfcip.pni), 0)); + return ERR_BUSY; + } + + nfcipLogI(" NFCIP(I) Checking if to send ATN ATNRetrys: %d \r\n", gNfcip.cntATNRetrys); + + /* Digital 1.0 14.15.5.6 3) Otherwise send ATN */ + if(gNfcip.cntATNRetrys++ >= RFAL_NFCDEP_MAX_NACK_RETRYS) { + return ERR_PROTO; + } + + /* Send ATN */ + nfcipLogI(" NFCIP(I) Sending ATN \r\n"); + EXIT_ON_ERR(ret, nfcipDEPControlMsg(nfcip_PFBSPDU_ATN(), 0)); + return ERR_BUSY; + + /*******************************************************************************/ + /* Data rcvd with error -> Digital 1.0 14.12.5.4 */ + case ERR_CRC: + case ERR_PAR: + case ERR_FRAMING: + case ERR_RF_COLLISION: + + nfcipLogI(" NFCIP(I) rx Error: %d \r\n", rxRes); + + /* Digital 1.0 14.12.5.4 Tx Error with data, ignore */ + if(rxLen < NFCIP_MIN_TXERROR_LEN) { + nfcipLogI(" NFCIP(I) Transmission error w data \r\n"); +#if 0 + if(gNfcip.cfg.commMode == RFAL_NFCDEP_COMM_PASSIVE) + { + nfcipLogI( " NFCIP(I) Transmission error w data -> reEnabling Rx \r\n" ); + nfcipReEnableRxTout( NFCIP_TRECOV ); + return ERR_BUSY; + } +#endif /* 0 */ + } + + /* Digital 1.1 16.12.5.4 if NACKs failed raise Transmission error */ + if(gNfcip.cntNACKRetrys++ >= RFAL_NFCDEP_MAX_NACK_RETRYS) { + return ERR_FRAMING; + } + + /* Send NACK */ + nfcipLogI(" NFCIP(I) Sending NACK \r\n"); + EXIT_ON_ERR(ret, nfcipDEPControlMsg(nfcip_PFBRPDU_NACK(gNfcip.pni), 0)); + return ERR_BUSY; + + case ERR_NONE: + break; + + case ERR_BUSY: + return ERR_BUSY; /* Debug purposes */ + + default: + nfcipLogW(" NFCIP(I) Error: %d \r\n", rxRes); + return rxRes; + } + + /*******************************************************************************/ + /* Rx OK check if valid DEP PDU */ + /*******************************************************************************/ + + /* Due to different modes on ST25R391x (with/without CRC) use NFC-DEP LEN instead of bytes retrieved */ + nfcDepLen = gNfcip.rxBuf[rxMsgIt++]; + + nfcipLogD(" NFCIP(I) rx OK: %d bytes \r\n", nfcDepLen); + + /* Digital 1.0 14.15.5.5 Protocol Error */ + if(gNfcip.rxBuf[rxMsgIt++] != NFCIP_RES) { + nfcipLogW(" NFCIP(I) error %02X instead of %02X \r\n", gNfcip.rxBuf[--rxMsgIt], NFCIP_RES); + return ERR_PROTO; + } + + /* Digital 1.0 14.15.5.5 Protocol Error */ + if(gNfcip.rxBuf[rxMsgIt++] != (uint8_t)NFCIP_CMD_DEP_RES) { + nfcipLogW( + " NFCIP(I) error %02X instead of %02X \r\n", + gNfcip.rxBuf[--rxMsgIt], + NFCIP_CMD_DEP_RES); + return ERR_PROTO; + } + + rxPFB = gNfcip.rxBuf[rxMsgIt++]; + + /*******************************************************************************/ + /* Check for valid PFB type */ + if(!(nfcip_PFBisSPDU(rxPFB) || nfcip_PFBisRPDU(rxPFB) || nfcip_PFBisIPDU(rxPFB))) { + return ERR_PROTO; + } + + /*******************************************************************************/ + /* Digital 1.0 14.8.2.1 check if DID is expected and match -> Protocol Error */ + if(gNfcip.cfg.did != RFAL_NFCDEP_DID_NO) { + if((gNfcip.rxBuf[rxMsgIt++] != gNfcip.cfg.did) || !nfcip_PFBhasDID(rxPFB)) { + return ERR_PROTO; + } + optHdrLen++; /* Inc header optional field cnt*/ + } else if(nfcip_PFBhasDID(rxPFB)) /* DID not expected but rcv */ + { + return ERR_PROTO; + } else { + /* MISRA 15.7 - Empty else */ + } + + /*******************************************************************************/ + /* Digital 1.0 14.6.2.8 & 14.6.3.11 NAD must not be used */ + if(gNfcip.cfg.nad != RFAL_NFCDEP_NAD_NO) { + if((gNfcip.rxBuf[rxMsgIt++] != gNfcip.cfg.nad) || !nfcip_PFBhasNAD(rxPFB)) { + return ERR_PROTO; + } + optHdrLen++; /* Inc header optional field cnt*/ + } else if(nfcip_PFBhasNAD(rxPFB)) /* NAD not expected but rcv */ + { + return ERR_PROTO; + } else { + /* MISRA 15.7 - Empty else */ + } + + /*******************************************************************************/ + /* Process R-PDU */ + /*******************************************************************************/ + if(nfcip_PFBisRPDU(rxPFB)) { + /*******************************************************************************/ + /* R ACK */ + /*******************************************************************************/ + if(nfcip_PFBisRACK(rxPFB)) { + nfcipLogI(" NFCIP(I) Rcvd ACK \r\n"); + if(gNfcip.pni == nfcip_PBF_PNI(rxPFB)) { + /* 14.12.3.3 R-ACK with correct PNI -> Increment */ + gNfcip.pni = nfcip_PNIInc(gNfcip.pni); + + /* R-ACK while not performing chaining -> Protocol error*/ + if(!gNfcip.isTxChaining) { + return ERR_PROTO; + } + + nfcipClearCounters(); + gNfcip.state = NFCIP_ST_INIT_DEP_IDLE; + return ERR_NONE; /* This block has been transmitted */ + } else /* Digital 1.0 14.12.4.5 ACK with wrong PNI Initiator may retransmit */ + { + if(gNfcip.cntTxRetrys++ >= RFAL_NFCDEP_MAX_TX_RETRYS) { + return ERR_PROTO; + } + + /* Extended the MAY in Digital 1.0 14.12.4.5 to only reTransmit if the ACK + * is for the previous DEP, otherwise raise Protocol immediately + * If the PNI difference is more than 1 it is worthless to reTransmit 3x + * and after raise the error */ + + if(nfcip_PNIDec(gNfcip.pni) == nfcip_PBF_PNI(rxPFB)) { + /* ReTransmit */ + nfcipLogI(" NFCIP(I) Rcvd ACK prev PNI -> reTx \r\n"); + gNfcip.state = NFCIP_ST_INIT_DEP_TX; + return ERR_BUSY; + } + + nfcipLogI(" NFCIP(I) Rcvd ACK unexpected far PNI -> Error \r\n"); + return ERR_PROTO; + } + } else /* Digital 1.0 - 14.12.5.2 Target must never send NACK */ + { + return ERR_PROTO; + } + } + + /*******************************************************************************/ + /* Process S-PDU */ + /*******************************************************************************/ + if(nfcip_PFBisSPDU(rxPFB)) { + nfcipLogI(" NFCIP(I) Rcvd S-PDU \r\n"); + /*******************************************************************************/ + /* S ATN */ + /*******************************************************************************/ + if(nfcip_PFBisSATN(rxPFB)) /* If is a S-ATN */ + { + nfcipLogI(" NFCIP(I) Rcvd ATN \r\n"); + if(nfcip_PFBisSATN(gNfcip.lastPFB)) /* Check if is expected */ + { + gNfcip.cntATNRetrys = 0; /* Clear ATN counter */ + + /* Although spec is not clear NFC Forum Digital test is expecting to + * retransmit upon receiving ATN_RES */ + if(nfcip_PFBisSTO(gNfcip.lastPFBnATN)) { + nfcipLogI(" NFCIP(I) Rcvd ATN -> reTx RTOX_RES \r\n"); + EXIT_ON_ERR(ret, nfcipDEPControlMsg(nfcip_PFBSPDU_TO(), gNfcip.lastRTOX)); + } else { + /* ReTransmit ? */ + if(gNfcip.cntTxRetrys++ >= RFAL_NFCDEP_MAX_TX_RETRYS) { + return ERR_PROTO; + } + + nfcipLogI(" NFCIP(I) Rcvd ATN -> reTx PNI: %d \r\n", gNfcip.pni); + gNfcip.state = NFCIP_ST_INIT_DEP_TX; + } + + return ERR_BUSY; + } else /* Digital 1.0 14.12.4.4 & 14.12.4.8 */ + { + return ERR_PROTO; + } + } + /*******************************************************************************/ + /* S TO */ + /*******************************************************************************/ + else if(nfcip_PFBisSTO(rxPFB)) /* If is a S-TO (RTOX) */ + { + nfcipLogI(" NFCIP(I) Rcvd TO \r\n"); + + rxRTOX = gNfcip.rxBuf[rxMsgIt++]; + + /* Digital 1.1 16.12.4.3 - Initiator MAY stop accepting subsequent RTOX Req * + * - RTOX request to an ATN -> Protocol error */ + if((gNfcip.cntRTOXRetrys++ > RFAL_NFCDEP_MAX_RTOX_RETRYS) || + nfcip_PFBisSATN(gNfcip.lastPFB)) { + return ERR_PROTO; + } + + /* Digital 1.1 16.8.4.1 RTOX must be between [1,59] */ + if((rxRTOX < NFCIP_INIT_MIN_RTOX) || (rxRTOX > NFCIP_INIT_MAX_RTOX)) { + return ERR_PROTO; + } + + EXIT_ON_ERR(ret, nfcipDEPControlMsg(nfcip_PFBSPDU_TO(), rxRTOX)); + gNfcip.lastRTOX = rxRTOX; + + return ERR_BUSY; + } else { + /* Unexpected S-PDU */ + return ERR_PROTO; /* PRQA S 2880 # MISRA 2.1 - Guard code to prevent unexpected behavior */ + } + } + + /*******************************************************************************/ + /* Process I-PDU */ + /*******************************************************************************/ + if(nfcip_PFBisIPDU(rxPFB)) { + if(gNfcip.pni != nfcip_PBF_PNI(rxPFB)) { + nfcipLogI( + " NFCIP(I) Rcvd IPDU wrong PNI curPNI: %d rxPNI: %d \r\n", + gNfcip.pni, + nfcip_PBF_PNI(rxPFB)); + return ERR_PROTO; + } + + nfcipLogD(" NFCIP(I) Rcvd IPDU OK PNI: %d \r\n", gNfcip.pni); + + /* 14.12.3.3 I-PDU with correct PNI -> Increment */ + gNfcip.pni = nfcip_PNIInc(gNfcip.pni); + + /* Successful data Exchange */ + nfcipClearCounters(); + *outActRxLen = ((uint16_t)nfcDepLen - RFAL_NFCDEP_DEP_HEADER - (uint16_t)optHdrLen); + + if((&gNfcip.rxBuf[gNfcip.rxBufPaylPos] != + &gNfcip.rxBuf[RFAL_NFCDEP_DEP_HEADER + optHdrLen]) && + (*outActRxLen > 0U)) { + ST_MEMMOVE( + &gNfcip.rxBuf[gNfcip.rxBufPaylPos], + &gNfcip.rxBuf[RFAL_NFCDEP_DEP_HEADER + optHdrLen], + *outActRxLen); + } + + /*******************************************************************************/ + /* Check if target is indicating chaining MI */ + /*******************************************************************************/ + if(nfcip_PFBisIMI(rxPFB)) { + gNfcip.isRxChaining = true; + *outIsChaining = true; + + nfcipLogD(" NFCIP(I) Rcvd IPDU OK w MI -> ACK \r\n"); + EXIT_ON_ERR( + ret, nfcipDEPControlMsg(nfcip_PFBRPDU_ACK(gNfcip.pni), gNfcip.rxBuf[rxMsgIt++])); + + return ERR_AGAIN; /* Send Again signalling to run again, but some chaining data has arrived*/ + } else { + gNfcip.isRxChaining = false; + gNfcip.state = NFCIP_ST_INIT_DEP_IDLE; + + ret = ERR_NONE; /* Data exchange done */ + } + } + return ret; +} + +/*******************************************************************************/ +static ReturnCode + nfcipTargetHandleRX(ReturnCode rxRes, uint16_t* outActRxLen, bool* outIsChaining) { + ReturnCode ret; + uint8_t nfcDepLen; + uint8_t rxMsgIt; + uint8_t rxPFB; + uint8_t optHdrLen; + uint8_t resBuf[RFAL_NFCDEP_HEADER_PAD + NFCIP_TARGET_RES_MAX]; + + ret = ERR_INTERNAL; + rxMsgIt = 0; + optHdrLen = 0; + + *outActRxLen = 0; + *outIsChaining = false; + + /*******************************************************************************/ + /* Handle reception errors */ + /*******************************************************************************/ + switch(rxRes) { + /*******************************************************************************/ + case ERR_NONE: + break; + + case ERR_LINK_LOSS: + nfcipLogW(" NFCIP(T) Error: %d \r\n", rxRes); + return rxRes; + + case ERR_BUSY: + return ERR_BUSY; /* Debug purposes */ + + case ERR_TIMEOUT: + case ERR_CRC: + case ERR_PAR: + case ERR_FRAMING: + case ERR_PROTO: + default: + /* Digital 1.1 16.12.5.2 The Target MUST NOT attempt any error recovery. * + * The Target MUST always stay in receive mode when a * + * Transmission Error or a Protocol Error occurs. * + * * + * Do not push Transmission/Protocol Errors to upper layer in Listen Mode #766 */ + + nfcDepReEnableRx(gNfcip.rxBuf, gNfcip.rxBufLen, gNfcip.rxRcvdLen); + return ERR_BUSY; + } + + /*******************************************************************************/ + /* Rx OK check if valid DEP PDU */ + /*******************************************************************************/ + + /* Due to different modes on ST25R391x (with/without CRC) use NFC-DEP LEN instead of bytes retrieved */ + nfcDepLen = gNfcip.rxBuf[rxMsgIt++]; + + nfcipLogD(" NFCIP(T) rx OK: %d bytes \r\n", nfcDepLen); + + if(gNfcip.rxBuf[rxMsgIt++] != NFCIP_REQ) { + nfcDepReEnableRx(gNfcip.rxBuf, gNfcip.rxBufLen, gNfcip.rxRcvdLen); + return ERR_BUSY; /* ERR_PROTO - Ignore bad request */ + } + + /*******************************************************************************/ + /* Check whether target rcvd a normal DEP or deactivation request */ + /*******************************************************************************/ + switch(gNfcip.rxBuf[rxMsgIt++]) { + /*******************************************************************************/ + case(uint8_t)NFCIP_CMD_DEP_REQ: + break; /* Continue to normal DEP processing */ + + /*******************************************************************************/ + case(uint8_t)NFCIP_CMD_DSL_REQ: + + nfcipLogI(" NFCIP(T) rx DSL \r\n"); + + /* Digital 1.0 14.9.1.2 If DID is used and incorrect ignore it */ + /* [Digital 1.0, 16.9.1.2]: If DID == 0, Target SHALL ignore DSL_REQ with DID */ + if((((gNfcip.rxBuf[rxMsgIt++] != gNfcip.cfg.did) || + (nfcDepLen != RFAL_NFCDEP_DSL_RLS_LEN_DID)) && + (gNfcip.cfg.did != RFAL_NFCDEP_DID_NO)) || + ((gNfcip.cfg.did == RFAL_NFCDEP_DID_NO) && + (nfcDepLen != RFAL_NFCDEP_DSL_RLS_LEN_NO_DID))) { + nfcipLogI(" NFCIP(T) DSL wrong DID, ignoring \r\n"); + return ERR_BUSY; + } + + nfcipTx(NFCIP_CMD_DSL_RES, resBuf, NULL, 0, 0, NFCIP_NO_FWT); + + gNfcip.state = NFCIP_ST_TARG_DEP_SLEEP; + return ERR_SLEEP_REQ; + + /*******************************************************************************/ + case(uint8_t)NFCIP_CMD_RLS_REQ: + + nfcipLogI(" NFCIP(T) rx RLS \r\n"); + + /* Digital 1.0 14.10.1.2 If DID is used and incorrect ignore it */ + /* [Digital 1.0, 16.10.2.2]: If DID == 0, Target SHALL ignore DSL_REQ with DID */ + if((((gNfcip.rxBuf[rxMsgIt++] != gNfcip.cfg.did) || + (nfcDepLen != RFAL_NFCDEP_DSL_RLS_LEN_DID)) && + (gNfcip.cfg.did != RFAL_NFCDEP_DID_NO)) || + ((gNfcip.cfg.did == RFAL_NFCDEP_DID_NO) && + (nfcDepLen > RFAL_NFCDEP_DSL_RLS_LEN_NO_DID))) { + nfcipLogI(" NFCIP(T) RLS wrong DID, ignoring \r\n"); + return ERR_BUSY; + } + + nfcipTx(NFCIP_CMD_RLS_RES, resBuf, NULL, 0, 0, NFCIP_NO_FWT); + + gNfcip.state = NFCIP_ST_TARG_DEP_IDLE; + return ERR_RELEASE_REQ; + + /*******************************************************************************/ + /*case NFCIP_CMD_PSL_REQ: PSL must be handled in Activation only */ + /*case NFCIP_CMD_WUP_REQ: WUP not in NFC Forum Digital 1.0 */ + default: + + /* Don't go to NFCIP_ST_TARG_DEP_IDLE state as it needs to ignore this * + * invalid frame, and keep waiting for more frames */ + + nfcDepReEnableRx(gNfcip.rxBuf, gNfcip.rxBufLen, gNfcip.rxRcvdLen); + return ERR_BUSY; /* ERR_PROTO - Ignore bad frame */ + } + + /*******************************************************************************/ + + rxPFB = gNfcip.rxBuf[rxMsgIt++]; /* Store rcvd PFB */ + + /*******************************************************************************/ + /* Check for valid PFB type */ + if(!(nfcip_PFBisSPDU(rxPFB) || nfcip_PFBisRPDU(rxPFB) || nfcip_PFBisIPDU(rxPFB))) { + nfcDepReEnableRx(gNfcip.rxBuf, gNfcip.rxBufLen, gNfcip.rxRcvdLen); + return ERR_BUSY; /* ERR_PROTO - Ignore invalid PFB */ + } + + /*******************************************************************************/ + if(gNfcip.cfg.did != RFAL_NFCDEP_DID_NO) { + if(!nfcip_PFBhasDID(rxPFB)) { + nfcDepReEnableRx(gNfcip.rxBuf, gNfcip.rxBufLen, gNfcip.rxRcvdLen); + return ERR_BUSY; /* ERR_PROTO - Ignore bad/missing DID */ + } + if(gNfcip.rxBuf[rxMsgIt++] != gNfcip.cfg.did) /* MISRA 13.5 */ + { + nfcDepReEnableRx(gNfcip.rxBuf, gNfcip.rxBufLen, gNfcip.rxRcvdLen); + return ERR_BUSY; /* ERR_PROTO - Ignore bad/missing DID */ + } + optHdrLen++; /* Inc header optional field cnt*/ + } else if(nfcip_PFBhasDID(rxPFB)) /* DID not expected but rcv */ + { + nfcDepReEnableRx(gNfcip.rxBuf, gNfcip.rxBufLen, gNfcip.rxRcvdLen); + return ERR_BUSY; /* ERR_PROTO - Ignore unexpected DID */ + } else { + /* MISRA 15.7 - Empty else */ + } + + /*******************************************************************************/ + if(gNfcip.cfg.nad != RFAL_NFCDEP_NAD_NO) { + if((gNfcip.rxBuf[rxMsgIt++] != gNfcip.cfg.did) || !nfcip_PFBhasDID(rxPFB)) { + nfcDepReEnableRx(gNfcip.rxBuf, gNfcip.rxBufLen, gNfcip.rxRcvdLen); + return ERR_BUSY; /* ERR_PROTO - Ignore bad/missing DID */ + } + optHdrLen++; /* Inc header optional field cnt*/ + } else if(nfcip_PFBhasNAD(rxPFB)) /* NAD not expected but rcv */ + { + nfcDepReEnableRx(gNfcip.rxBuf, gNfcip.rxBufLen, gNfcip.rxRcvdLen); + return ERR_BUSY; /* ERR_PROTO - Ignore unexpected NAD */ + } else { + /* MISRA 15.7 - Empty else */ + } + + /*******************************************************************************/ + /* Process R-PDU */ + /*******************************************************************************/ + if(nfcip_PFBisRPDU(rxPFB)) { + nfcipLogD(" NFCIP(T) Rcvd R-PDU \r\n"); + /*******************************************************************************/ + /* R ACK */ + /*******************************************************************************/ + if(nfcip_PFBisRACK(rxPFB)) { + nfcipLogI(" NFCIP(T) Rcvd ACK \r\n"); + if(gNfcip.pni == nfcip_PBF_PNI(rxPFB)) { + /* R-ACK while not performing chaining -> Protocol error */ + if(!gNfcip.isTxChaining) { + nfcDepReEnableRx(gNfcip.rxBuf, gNfcip.rxBufLen, gNfcip.rxRcvdLen); + return ERR_BUSY; /* ERR_PROTO - Ignore unexpected ACK */ + } + + /* This block has been transmitted and acknowledged, perform RTOX until next data is provided */ + + /* Digital 1.1 16.12.4.7 - If ACK rcvd continue with chaining or an RTOX */ + nfcipTimerStart( + gNfcip.RTOXTimer, + nfcipRTOXAdjust(nfcipConv1FcToMs(rfalNfcDepWT2RWT(gNfcip.cfg.to)))); + gNfcip.state = NFCIP_ST_TARG_DEP_RTOX; + + return ERR_NONE; /* This block has been transmitted */ + } + + /* Digital 1.0 14.12.3.4 - If last send was ATN and rx PNI is minus 1 */ + else if( + nfcip_PFBisSATN(gNfcip.lastPFB) && + (nfcip_PNIDec(gNfcip.pni) == nfcip_PBF_PNI(rxPFB))) { + nfcipLogI(" NFCIP(T) wrong PNI, last was ATN reTx \r\n"); + /* Spec says to leave current PNI as is, but will be Inc after Tx, remaining the same */ + gNfcip.pni = nfcip_PNIDec(gNfcip.pni); + + gNfcip.state = NFCIP_ST_TARG_DEP_TX; + return ERR_BUSY; + } else { + /* MISRA 15.7 - Empty else */ + } + } + /*******************************************************************************/ + /* R NACK */ + /*******************************************************************************/ + /* ISO 18092 12.6.1.3.3 When rcv NACK if PNI = prev PNI sent -> reTx */ + else if(nfcip_PFBisRNACK(rxPFB) && (nfcip_PNIDec(gNfcip.pni) == nfcip_PBF_PNI(rxPFB))) { + nfcipLogI(" NFCIP(T) Rcvd NACK \r\n"); + + gNfcip.pni = nfcip_PNIDec(gNfcip.pni); /* Dec so that has the prev PNI */ + + gNfcip.state = NFCIP_ST_TARG_DEP_TX; + return ERR_BUSY; + } else { + nfcipLogI(" NFCIP(T) Unexpected R-PDU \r\n"); + + nfcDepReEnableRx(gNfcip.rxBuf, gNfcip.rxBufLen, gNfcip.rxRcvdLen); + return ERR_BUSY; /* ERR_PROTO - Ignore unexpected R-PDU */ + } + } + + /*******************************************************************************/ + /* Process S-PDU */ + /*******************************************************************************/ + if(nfcip_PFBisSPDU(rxPFB)) { + nfcipLogD(" NFCIP(T) Rcvd S-PDU \r\n"); + + /*******************************************************************************/ + /* S ATN */ + /*******************************************************************************/ + /* ISO 18092 12.6.3 Attention */ + if(nfcip_PFBisSATN(rxPFB)) /* If is a S-ATN */ + { + nfcipLogI(" NFCIP(T) Rcvd ATN curPNI: %d \r\n", gNfcip.pni); + EXIT_ON_ERR(ret, nfcipDEPControlMsg(nfcip_PFBSPDU_ATN(), 0)); + return ERR_BUSY; + } + + /*******************************************************************************/ + /* S TO */ + /*******************************************************************************/ + else if(nfcip_PFBisSTO(rxPFB)) /* If is a S-TO (RTOX) */ + { + if(nfcip_PFBisSTO(gNfcip.lastPFBnATN)) { + nfcipLogI(" NFCIP(T) Rcvd TO \r\n"); + + /* Digital 1.1 16.8.4.6 RTOX value in RES different that in REQ -> Protocol Error */ + if(gNfcip.lastRTOX != gNfcip.rxBuf[rxMsgIt++]) { + nfcipLogI(" NFCIP(T) Mismatched RTOX value \r\n"); + + nfcDepReEnableRx(gNfcip.rxBuf, gNfcip.rxBufLen, gNfcip.rxRcvdLen); + return ERR_BUSY; /* ERR_PROTO - Ignore unexpected RTOX value */ + } + + /* Clear waiting for RTOX Ack Flag */ + gNfcip.isWait4RTOX = false; + + /* Check if a Tx is already pending */ + if(gNfcip.isTxPending) { + nfcipLogW(" NFCIP(T) Tx pending, go immediately to TX \r\n"); + + gNfcip.state = NFCIP_ST_TARG_DEP_TX; + return ERR_BUSY; + } + + /* Start RTOX timer and change to check state */ + nfcipTimerStart( + gNfcip.RTOXTimer, + nfcipRTOXAdjust( + nfcipConv1FcToMs(gNfcip.lastRTOX * rfalNfcDepWT2RWT(gNfcip.cfg.to)))); + gNfcip.state = NFCIP_ST_TARG_DEP_RTOX; + + return ERR_BUSY; + } + } else { + /* Unexpected S-PDU */ + nfcipLogI( + " NFCIP(T) Unexpected S-PDU \r\n"); /* PRQA S 2880 # MISRA 2.1 - Guard code to prevent unexpected behavior */ + + nfcDepReEnableRx(gNfcip.rxBuf, gNfcip.rxBufLen, gNfcip.rxRcvdLen); + return ERR_BUSY; /* ERR_PROTO - Ignore unexpected S-PDU */ + } + } + + /*******************************************************************************/ + /* Process I-PDU */ + /*******************************************************************************/ + if(nfcip_PFBisIPDU(rxPFB)) { + if(gNfcip.pni != nfcip_PBF_PNI(rxPFB)) { + nfcipLogI( + " NFCIP(T) Rcvd IPDU wrong PNI curPNI: %d rxPNI: %d \r\n", + gNfcip.pni, + nfcip_PBF_PNI(rxPFB)); + + /* Digital 1.1 16.12.3.4 - If last send was ATN and rx PNI is minus 1 */ + if(nfcip_PFBisSATN(gNfcip.lastPFB) && + (nfcip_PNIDec(gNfcip.pni) == nfcip_PBF_PNI(rxPFB))) { + /* Spec says to leave current PNI as is, but will be Inc after Data Tx, remaining the same */ + gNfcip.pni = nfcip_PNIDec(gNfcip.pni); + + if(nfcip_PFBisIMI(rxPFB)) { + nfcipLogI( + " NFCIP(T) PNI = prevPNI && ATN before && chaining -> send ACK \r\n"); + EXIT_ON_ERR( + ret, + nfcipDEPControlMsg(nfcip_PFBRPDU_ACK(gNfcip.pni), gNfcip.rxBuf[rxMsgIt++])); + + /* Digital 1.1 16.12.3.4 (...) leave the current PNI unchanged afterwards */ + gNfcip.pni = nfcip_PNIInc(gNfcip.pni); + } else { + nfcipLogI(" NFCIP(T) PNI = prevPNI && ATN before -> reTx last I-PDU \r\n"); + gNfcip.state = NFCIP_ST_TARG_DEP_TX; + } + + return ERR_BUSY; + } + + nfcDepReEnableRx(gNfcip.rxBuf, gNfcip.rxBufLen, gNfcip.rxRcvdLen); + return ERR_BUSY; /* ERR_PROTO - Ignore bad PNI value */ + } + + nfcipLogD(" NFCIP(T) Rcvd IPDU OK PNI: %d \r\n", gNfcip.pni); + + /*******************************************************************************/ + /* Successful data exchange */ + /*******************************************************************************/ + *outActRxLen = ((uint16_t)nfcDepLen - RFAL_NFCDEP_DEP_HEADER - (uint16_t)optHdrLen); + + nfcipClearCounters(); + + if((&gNfcip.rxBuf[gNfcip.rxBufPaylPos] != + &gNfcip.rxBuf[RFAL_NFCDEP_DEP_HEADER + optHdrLen]) && + (*outActRxLen > 0U)) { + ST_MEMMOVE( + &gNfcip.rxBuf[gNfcip.rxBufPaylPos], + &gNfcip.rxBuf[RFAL_NFCDEP_DEP_HEADER + optHdrLen], + *outActRxLen); + } + + /*******************************************************************************/ + /* Check if Initiator is indicating chaining MI */ + /*******************************************************************************/ + if(nfcip_PFBisIMI(rxPFB)) { + gNfcip.isRxChaining = true; + *outIsChaining = true; + + nfcipLogD(" NFCIP(T) Rcvd IPDU OK w MI -> ACK \r\n"); + EXIT_ON_ERR( + ret, nfcipDEPControlMsg(nfcip_PFBRPDU_ACK(gNfcip.pni), gNfcip.rxBuf[rxMsgIt++])); + + gNfcip.pni = nfcip_PNIInc(gNfcip.pni); + + return ERR_AGAIN; /* Send Again signalling to run again, but some chaining data has arrived*/ + } else { + if(gNfcip.isRxChaining) { + nfcipLogI(" NFCIP(T) Rcvd last IPDU chaining finished \r\n"); + } + + /*******************************************************************************/ + /* Reception done, send to DH and start RTOX timer */ + /*******************************************************************************/ + nfcipTimerStart( + gNfcip.RTOXTimer, + nfcipRTOXAdjust(nfcipConv1FcToMs(rfalNfcDepWT2RWT(gNfcip.cfg.to)))); + gNfcip.state = NFCIP_ST_TARG_DEP_RTOX; + + gNfcip.isRxChaining = false; + ret = ERR_NONE; /* Data exchange done */ + } + } + return ret; +} + +/*******************************************************************************/ +static ReturnCode nfcipTx( + rfalNfcDepCmd cmd, + uint8_t* txBuf, + uint8_t* paylBuf, + uint16_t paylLen, + uint8_t pfbData, + uint32_t fwt) { + uint16_t txBufIt; + uint8_t* txBlock; + uint8_t* payloadBuf; + uint8_t pfb; + + if(txBuf == NULL) { + return ERR_PARAM; + } + + payloadBuf = paylBuf; /* MISRA 17.8: Use intermediate variable */ + + if((paylLen == 0U) || (payloadBuf == NULL)) { + payloadBuf = (uint8_t*)&txBuf + [RFAL_NFCDEP_DEPREQ_HEADER_LEN]; /* If not a DEP (no Data) ensure enough space for header */ + } + + txBufIt = 0; + pfb = pfbData; /* MISRA 17.8: Use intermediate variable */ + + txBlock = payloadBuf; /* Point to beginning of the Data, and go backwards */ + + gNfcip.lastCmd = (uint8_t)cmd; /* Store last cmd sent */ + gNfcip.lastPFB = NFCIP_PFB_INVALID; /* Reset last pfb sent */ + + /*******************************************************************************/ + /* Compute outgoing NFCIP message */ + /*******************************************************************************/ + switch(cmd) { + /*******************************************************************************/ + case NFCIP_CMD_ATR_RES: + case NFCIP_CMD_ATR_REQ: + + rfalNfcDepSetNFCID(payloadBuf, gNfcip.cfg.nfcid, gNfcip.cfg.nfcidLen); /* NFCID */ + txBufIt += RFAL_NFCDEP_NFCID3_LEN; + + payloadBuf[txBufIt++] = gNfcip.cfg.did; /* DID */ + payloadBuf[txBufIt++] = gNfcip.cfg.bs; /* BS */ + payloadBuf[txBufIt++] = gNfcip.cfg.br; /* BR */ + + if(cmd == NFCIP_CMD_ATR_RES) { + payloadBuf[txBufIt++] = gNfcip.cfg.to; /* ATR_RES[ TO ] */ + } + + if(gNfcip.cfg.gbLen > 0U) { + payloadBuf[txBufIt++] = nfcip_PPwGB(gNfcip.cfg.lr); /* PP signalling GB */ + ST_MEMCPY( + &payloadBuf[txBufIt], gNfcip.cfg.gb, gNfcip.cfg.gbLen); /* set General Bytes */ + txBufIt += gNfcip.cfg.gbLen; + } else { + payloadBuf[txBufIt++] = rfalNfcDepLR2PP(gNfcip.cfg.lr); /* PP without GB */ + } + + if((txBufIt + RFAL_NFCDEP_CMDTYPE_LEN + RFAL_NFCDEP_CMD_LEN) > + RFAL_NFCDEP_ATRREQ_MAX_LEN) /* Check max ATR length (ATR_REQ = ATR_RES)*/ + { + return ERR_PARAM; + } + break; + + /*******************************************************************************/ + case NFCIP_CMD_WUP_REQ: /* ISO 18092 - 12.5.2.1 */ + + rfalNfcDepSetNFCID((payloadBuf), gNfcip.cfg.nfcid, gNfcip.cfg.nfcidLen); /* NFCID */ + txBufIt += RFAL_NFCDEP_NFCID3_LEN; + + *(--txBlock) = gNfcip.cfg.did; /* DID */ + break; + + /*******************************************************************************/ + case NFCIP_CMD_WUP_RES: /* ISO 18092 - 12.5.2.2 */ + case NFCIP_CMD_PSL_REQ: + case NFCIP_CMD_PSL_RES: + + *(--txBlock) = gNfcip.cfg.did; /* DID */ + break; + + /*******************************************************************************/ + case NFCIP_CMD_RLS_REQ: + case NFCIP_CMD_RLS_RES: + case NFCIP_CMD_DSL_REQ: + case NFCIP_CMD_DSL_RES: + + /* Digital 1.0 - 14.8.1.1 & 14.9.1.1 & 14.10.1.1 Only add DID if not 0 */ + if(gNfcip.cfg.did != RFAL_NFCDEP_DID_NO) { + *(--txBlock) = gNfcip.cfg.did; /* DID */ + } + break; + + /*******************************************************************************/ + case NFCIP_CMD_DEP_REQ: + case NFCIP_CMD_DEP_RES: + + /* Compute optional PFB bits */ + if(gNfcip.cfg.did != RFAL_NFCDEP_DID_NO) { + pfb |= NFCIP_PFB_DID_BIT; + } + if(gNfcip.cfg.nad != RFAL_NFCDEP_NAD_NO) { + pfb |= NFCIP_PFB_NAD_BIT; + } + if((gNfcip.isTxChaining) && (nfcip_PFBisIPDU(pfb))) { + pfb |= NFCIP_PFB_MI_BIT; + } + + /* Store PFB for future handling */ + gNfcip.lastPFB = pfb; /* store PFB sent */ + + if(!nfcip_PFBisSATN(pfb)) { + gNfcip.lastPFBnATN = pfb; /* store last PFB different then ATN */ + } + + /* Add NAD if it is to be supported */ + if(gNfcip.cfg.nad != RFAL_NFCDEP_NAD_NO) { + *(--txBlock) = gNfcip.cfg.nad; /* NAD */ + } + + /* Digital 1.0 - 14.8.1.1 & 14.8.1.1 Only add DID if not 0 */ + if(gNfcip.cfg.did != RFAL_NFCDEP_DID_NO) { + *(--txBlock) = gNfcip.cfg.did; /* DID */ + } + + *(--txBlock) = pfb; /* PFB */ + + /* NCI 1.0 - Check if Empty frames are allowed */ + if((paylLen == 0U) && nfcipIsEmptyDEPDisabled(gNfcip.cfg.oper) && nfcip_PFBisIPDU(pfb)) { + return ERR_PARAM; + } + break; + + /*******************************************************************************/ + default: + return ERR_PARAM; + } + + /*******************************************************************************/ + /* Prepend Header */ + /*******************************************************************************/ + *(--txBlock) = (uint8_t)cmd; /* CMD */ + *(--txBlock) = (uint8_t)(nfcipCmdIsReq(cmd) ? NFCIP_REQ : NFCIP_RES); /* CMDType */ + + txBufIt += paylLen + (uint16_t)((uint32_t)payloadBuf - + (uint32_t)txBlock); /* Calculate overall buffer size */ + + if(txBufIt > gNfcip.fsc) /* Check if msg length violates the maximum payload size FSC */ + { + return ERR_NOTSUPP; + } + + /*******************************************************************************/ + return nfcipDataTx(txBlock, txBufIt, fwt); +} + +/* + ****************************************************************************** + * GLOBAL FUNCTIONS + ****************************************************************************** + */ + +/*******************************************************************************/ +static void nfcipConfig(const rfalNfcDepConfigs* cfg) { + if(cfg == NULL) { + return; + } + + ST_MEMCPY(&gNfcip.cfg, cfg, sizeof(rfalNfcDepConfigs)); /* Copy given config to local */ + + gNfcip.cfg.to = + MIN(RFAL_NFCDEP_WT_TRG_MAX, gNfcip.cfg.to); /* Ensure proper WT value */ + gNfcip.cfg.did = nfcip_DIDMax(gNfcip.cfg.did); /* Ensure proper DID value */ + gNfcip.fsc = rfalNfcDepLR2FS(gNfcip.cfg.lr); /* Calculate FSC based on given LR */ + + gNfcip.state = + ((gNfcip.cfg.role == RFAL_NFCDEP_ROLE_TARGET) ? NFCIP_ST_TARG_WAIT_ATR : + NFCIP_ST_INIT_IDLE); +} + +/*******************************************************************************/ +static ReturnCode nfcipRun(uint16_t* outActRxLen, bool* outIsChaining) { + ReturnCode ret; + + ret = ERR_SYNTAX; + + nfcipLogD(" NFCIP Run() state: %d \r\n", gNfcip.state); + + switch(gNfcip.state) { + /*******************************************************************************/ + case NFCIP_ST_IDLE: + case NFCIP_ST_INIT_DEP_IDLE: + case NFCIP_ST_TARG_DEP_IDLE: + case NFCIP_ST_TARG_DEP_SLEEP: + return ERR_NONE; + + /*******************************************************************************/ + case NFCIP_ST_INIT_DEP_TX: + + nfcipLogD(" NFCIP(I) Tx PNI: %d txLen: %d \r\n", gNfcip.pni, gNfcip.txBufLen); + ret = nfcipTx( + NFCIP_CMD_DEP_REQ, + gNfcip.txBuf, + &gNfcip.txBuf[gNfcip.txBufPaylPos], + gNfcip.txBufLen, + nfcip_PFBIPDU(gNfcip.pni), + (gNfcip.cfg.fwt + gNfcip.cfg.dFwt)); + + switch(ret) { + case ERR_NONE: + gNfcip.state = NFCIP_ST_INIT_DEP_RX; + break; + + case ERR_PARAM: + default: + gNfcip.state = NFCIP_ST_INIT_DEP_IDLE; + return ret; + } + /* fall through */ + + /*******************************************************************************/ + case NFCIP_ST_INIT_DEP_RX: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + + ret = nfcipDataRx(false); + + if(ret != ERR_BUSY) { + ret = nfcipInitiatorHandleDEP(ret, *gNfcip.rxRcvdLen, outActRxLen, outIsChaining); + } + + break; + + /*******************************************************************************/ + case NFCIP_ST_TARG_DEP_RTOX: + + if(!nfcipTimerisExpired(gNfcip.RTOXTimer)) /* Do nothing until RTOX timer has expired */ + { + return ERR_BUSY; + } + + /* If we cannot send a RTOX raise a Timeout error so that we do not + * hold the field On forever in AP2P */ + if(nfcipIsRTOXReqDisabled(gNfcip.cfg.oper)) { + /* We should reEnable Rx, and measure time between our field Off to + * either report link loss or recover #287 */ + nfcipLogI(" NFCIP(T) RTOX not sent due to config, NOT reenabling Rx \r\n"); + return ERR_TIMEOUT; + } + + if(gNfcip.cntRTOXRetrys++ > + RFAL_NFCDEP_MAX_RTOX_RETRYS) /* Check maximum consecutive RTOX requests */ + { + return ERR_PROTO; + } + + nfcipLogI(" NFCIP(T) RTOX sent \r\n"); + + gNfcip.lastRTOX = + nfcip_RTOXTargMax(gNfcip.cfg.to); /* Calculate requested RTOX value, and send it */ + EXIT_ON_ERR(ret, nfcipDEPControlMsg(nfcip_PFBSPDU_TO(), gNfcip.lastRTOX)); + + /* Set waiting for RTOX Ack Flag */ + gNfcip.isWait4RTOX = true; + + gNfcip.state = NFCIP_ST_TARG_DEP_RX; /* Go back to Rx to process RTOX ack */ + return ERR_BUSY; + + /*******************************************************************************/ + case NFCIP_ST_TARG_DEP_TX: + + nfcipLogD(" NFCIP(T) Tx PNI: %d txLen: %d \r\n", gNfcip.pni, gNfcip.txBufLen); + ret = nfcipTx( + NFCIP_CMD_DEP_RES, + gNfcip.txBuf, + &gNfcip.txBuf[gNfcip.txBufPaylPos], + gNfcip.txBufLen, + nfcip_PFBIPDU(gNfcip.pni), + NFCIP_NO_FWT); + + /* Clear flags */ + gNfcip.isTxPending = false; + gNfcip.isWait4RTOX = false; + + /* Digital 1.0 14.12.3.4 Increment the current PNI after Tx */ + gNfcip.pni = nfcip_PNIInc(gNfcip.pni); + + switch(ret) { + case ERR_NONE: + gNfcip.state = NFCIP_ST_TARG_DEP_RX; /* All OK, goto Rx state */ + break; + + case ERR_PARAM: + default: + gNfcip.state = NFCIP_ST_TARG_DEP_IDLE; /* Upon Tx error, goto IDLE state */ + return ret; + } + /* fall through */ + + /*******************************************************************************/ + case NFCIP_ST_TARG_DEP_RX: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + + if(gNfcip.isReqPending) /* if already has Data should be from a DEP from nfcipTargetHandleActivation() */ + { + nfcipLogD(" NFCIP(T) Skipping Rx Using DEP from Activation \r\n"); + + gNfcip.isReqPending = false; + ret = ERR_NONE; + } else { + ret = nfcipDataRx(false); + } + + if(ret != ERR_BUSY) { + ret = nfcipTargetHandleRX(ret, outActRxLen, outIsChaining); + } + + break; + + /*******************************************************************************/ + default: + /* MISRA 16.4: no empty default statement (a comment being enough) */ + break; + } + return ret; +} + +/*******************************************************************************/ +void rfalNfcDepSetDeactivatingCallback(rfalNfcDepDeactCallback pFunc) { + gNfcip.isDeactivating = pFunc; +} + +/*******************************************************************************/ +void rfalNfcDepInitialize(void) { + nfcipLogD(" NFCIP Ini() \r\n"); + + gNfcip.state = NFCIP_ST_IDLE; + gNfcip.isDeactivating = NULL; + + gNfcip.isTxPending = false; + gNfcip.isWait4RTOX = false; + gNfcip.isReqPending = false; + + gNfcip.cfg.oper = + (RFAL_NFCDEP_OPER_FULL_MI_DIS | RFAL_NFCDEP_OPER_EMPTY_DEP_EN | RFAL_NFCDEP_OPER_ATN_EN | + RFAL_NFCDEP_OPER_RTOX_REQ_EN); + + gNfcip.cfg.did = RFAL_NFCDEP_DID_NO; + gNfcip.cfg.nad = RFAL_NFCDEP_NAD_NO; + + gNfcip.cfg.br = RFAL_NFCDEP_Bx_NO_HIGH_BR; + gNfcip.cfg.bs = RFAL_NFCDEP_Bx_NO_HIGH_BR; + + gNfcip.cfg.lr = RFAL_NFCDEP_LR_254; + gNfcip.fsc = rfalNfcDepLR2FS(gNfcip.cfg.lr); + + gNfcip.cfg.gbLen = 0; + + gNfcip.cfg.fwt = RFAL_NFCDEP_MAX_FWT; + gNfcip.cfg.dFwt = RFAL_NFCDEP_MAX_FWT; + + gNfcip.pni = 0; + + /* Destroy any ongoing RTOX timer*/ + nfcipTimerDestroy(gNfcip.RTOXTimer); + gNfcip.RTOXTimer = 0U; + + gNfcip.PDUTxPos = 0; + gNfcip.PDURxPos = 0; + gNfcip.PDUParam.rxLen = NULL; + gNfcip.PDUParam.rxBuf = NULL; + gNfcip.PDUParam.txBuf = NULL; + + nfcipClearCounters(); +} + +/*******************************************************************************/ +static void nfcipSetDEPParams(const rfalNfcDepDEPParams* DEPParams) { + nfcipLogD(" NFCIP SetDEP() txLen: %d \r\n", DEPParams->txBufLen); + + gNfcip.isTxChaining = DEPParams->txChaining; + gNfcip.txBuf = DEPParams->txBuf; + gNfcip.rxBuf = DEPParams->rxBuf; + gNfcip.txBufLen = DEPParams->txBufLen; + gNfcip.rxBufLen = DEPParams->rxBufLen; + gNfcip.txBufPaylPos = DEPParams->txBufPaylPos; + gNfcip.rxBufPaylPos = DEPParams->rxBufPaylPos; + + if(DEPParams->did != RFAL_NFCDEP_DID_KEEP) { + gNfcip.cfg.did = nfcip_DIDMax(DEPParams->did); + } + + gNfcip.cfg.fwt = DEPParams->fwt; + gNfcip.cfg.dFwt = DEPParams->dFwt; + gNfcip.fsc = DEPParams->fsc; + + if(gNfcip.cfg.role == RFAL_NFCDEP_ROLE_TARGET) { + /* If there's any data to be sent go for Tx */ + if(DEPParams->txBufLen > 0U) { + /* Ensure that an RTOX Ack is not being expected at moment */ + if(!gNfcip.isWait4RTOX) { + gNfcip.state = NFCIP_ST_TARG_DEP_TX; + return; + } else { + /* If RTOX Ack is expected, signal a pending Tx to be transmitted right after */ + gNfcip.isTxPending = true; + nfcipLogW(" NFCIP(T) Waiting RTOX, queueing outgoing DEP Block \r\n"); + } + } + + /*Digital 1.0 14.12.4.1 In target mode the first PDU MUST be sent by the Initiator */ + gNfcip.state = NFCIP_ST_TARG_DEP_RX; + return; + } + + /* New data TxRx request clear previous error counters for consecutive TxRx without reseting communication/protocol layer*/ + nfcipClearCounters(); + + gNfcip.state = NFCIP_ST_INIT_DEP_TX; +} + +/*******************************************************************************/ +bool rfalNfcDepTargetRcvdATR(void) { + return ( + (gNfcip.cfg.role == RFAL_NFCDEP_ROLE_TARGET) && nfcipIsTarget(gNfcip.state) && + (gNfcip.state > NFCIP_ST_TARG_WAIT_ATR)); +} + +/*******************************************************************************/ +bool rfalNfcDepIsAtrReq(const uint8_t* buf, uint16_t bufLen, uint8_t* nfcid3) { + uint8_t msgIt; + + msgIt = 0; + + if((bufLen < RFAL_NFCDEP_ATRREQ_MIN_LEN) || (bufLen > RFAL_NFCDEP_ATRREQ_MAX_LEN)) { + return false; + } + + if(buf[msgIt++] != NFCIP_REQ) { + return false; + } + + if(buf[msgIt++] != (uint8_t)NFCIP_CMD_ATR_REQ) { + return false; + } + + /* Output NFID3 if requested */ + if(nfcid3 != NULL) { + ST_MEMCPY(nfcid3, &buf[RFAL_NFCDEP_ATR_REQ_NFCID3_POS], RFAL_NFCDEP_NFCID3_LEN); + } + + return true; +} + +/*******************************************************************************/ +static ReturnCode nfcipTargetHandleActivation(rfalNfcDepDevice* nfcDepDev, uint8_t* outBRS) { + ReturnCode ret; + uint8_t msgIt; + uint8_t txBuf[RFAL_NFCDEP_HEADER_PAD + NFCIP_PSLRES_LEN]; + + /*******************************************************************************/ + /* Check if we are in correct state */ + /*******************************************************************************/ + if(gNfcip.state != NFCIP_ST_TARG_WAIT_ACTV) { + return ERR_WRONG_STATE; + } + + /*******************************************************************************/ + /* Check required parameters */ + /*******************************************************************************/ + if(outBRS == NULL) { + return ERR_PARAM; + } + + /*******************************************************************************/ + /* Wait and process incoming cmd (PSL / DEP) */ + /*******************************************************************************/ + ret = nfcipDataRx(false); + + if(ret != ERR_NONE) { + return ret; + } + + msgIt = 0; + *outBRS = RFAL_NFCDEP_BRS_MAINTAIN; /* set out BRS to be maintained */ + + msgIt++; /* Skip LEN byte */ + + if(gNfcip.rxBuf[msgIt++] != NFCIP_REQ) { + return ERR_PROTO; + } + + if(gNfcip.rxBuf[msgIt] == (uint8_t)NFCIP_CMD_PSL_REQ) { + msgIt++; + + if(gNfcip.rxBuf[msgIt++] != gNfcip.cfg.did) /* Checking DID */ + { + return ERR_PROTO; + } + + nfcipLogI(" NFCIP(T) PSL REQ rcvd \r\n"); + + *outBRS = gNfcip.rxBuf[msgIt++]; /* assign output BRS value */ + + /* Store FSL(LR) and update current config */ + gNfcip.cfg.lr = (gNfcip.rxBuf[msgIt++] & RFAL_NFCDEP_LR_VAL_MASK); + gNfcip.fsc = rfalNfcDepLR2FS(gNfcip.cfg.lr); + + /*******************************************************************************/ + /* Update NFC-DDE Device info */ + if(nfcDepDev != NULL) { + /* Update Bitrate info */ + /* PRQA S 4342 2 # MISRA 10.5 - Layout of enum rfalBitRate and definition of rfalNfcDepBRS2DSI guarantee no invalid enum values to be created */ + nfcDepDev->info.DSI = (rfalBitRate)rfalNfcDepBRS2DSI( + *outBRS); /* DSI codes the bit rate from Initiator to Target */ + nfcDepDev->info.DRI = (rfalBitRate)rfalNfcDepBRS2DRI( + *outBRS); /* DRI codes the bit rate from Target to Initiator */ + + /* Update Length Reduction and Frame Size */ + nfcDepDev->info.LR = gNfcip.cfg.lr; + nfcDepDev->info.FS = gNfcip.fsc; + + /* Update PPi byte */ + nfcDepDev->activation.Initiator.ATR_REQ.PPi &= ~RFAL_NFCDEP_PP_LR_MASK; + nfcDepDev->activation.Initiator.ATR_REQ.PPi |= rfalNfcDepLR2PP(gNfcip.cfg.lr); + } + + rfalSetBitRate(RFAL_BR_KEEP, gNfcip.nfcDepDev->info.DSI); + + EXIT_ON_ERR(ret, nfcipTx(NFCIP_CMD_PSL_RES, txBuf, NULL, 0, 0, NFCIP_NO_FWT)); + } else { + if(gNfcip.rxBuf[msgIt] == (uint8_t)NFCIP_CMD_DEP_REQ) { + msgIt++; + + /*******************************************************************************/ + /* Digital 1.0 14.12.3.1 PNI must be initialized to 0 */ + if(nfcip_PBF_PNI(gNfcip.rxBuf[msgIt]) != 0U) { + return ERR_PROTO; + } + + /*******************************************************************************/ + /* Digital 1.0 14.8.2.1 check if DID is expected and match -> Protocol Error */ + if(nfcip_PFBhasDID(gNfcip.rxBuf[msgIt])) { + if(gNfcip.rxBuf[++msgIt] != gNfcip.cfg.did) { + return ERR_PROTO; + } + } else if(gNfcip.cfg.did != RFAL_NFCDEP_DID_NO) /* DID expected but not rcv */ + { + return ERR_PROTO; + } else { + /* MISRA 15.7 - Empty else */ + } + } + + /* Signal Request pending to be digested on normal Handling (DEP_REQ, DSL_REQ, RLS_REQ) */ + gNfcip.isReqPending = true; + } + + gNfcip.state = NFCIP_ST_TARG_DEP_RX; + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode + rfalNfcDepATR(const rfalNfcDepAtrParam* param, rfalNfcDepAtrRes* atrRes, uint8_t* atrResLen) { + ReturnCode ret; + rfalNfcDepConfigs cfg; + uint16_t rxLen; + uint8_t msgIt; + uint8_t txBuf[RFAL_NFCDEP_ATRREQ_MAX_LEN]; + uint8_t rxBuf[NFCIP_ATRRES_BUF_LEN]; + + if((param == NULL) || (atrRes == NULL) || (atrResLen == NULL)) { + return ERR_PARAM; + } + + /*******************************************************************************/ + /* Configure NFC-DEP layer */ + /*******************************************************************************/ + + cfg.did = param->DID; + cfg.nad = param->NAD; + cfg.fwt = RFAL_NFCDEP_MAX_FWT; + cfg.dFwt = RFAL_NFCDEP_MAX_FWT; + cfg.br = param->BR; + cfg.bs = param->BS; + cfg.lr = param->LR; + cfg.to = RFAL_NFCDEP_WT_TRG_MAX; /* Not used in Initiator mode */ + + cfg.gbLen = param->GBLen; + if(cfg.gbLen > 0U) /* MISRA 21.18 */ + { + ST_MEMCPY(cfg.gb, param->GB, cfg.gbLen); + } + + cfg.nfcidLen = param->nfcidLen; + if(cfg.nfcidLen > 0U) /* MISRA 21.18 */ + { + ST_MEMCPY(cfg.nfcid, param->nfcid, cfg.nfcidLen); + } + + cfg.role = RFAL_NFCDEP_ROLE_INITIATOR; + cfg.oper = param->operParam; + cfg.commMode = param->commMode; + + rfalNfcDepInitialize(); + nfcipConfig(&cfg); + + /*******************************************************************************/ + /* Send ATR_REQ */ + /*******************************************************************************/ + + EXIT_ON_ERR( + ret, + nfcipTxRx( + NFCIP_CMD_ATR_REQ, + txBuf, + nfcipRWTActivation(), + NULL, + 0, + rxBuf, + NFCIP_ATRRES_BUF_LEN, + &rxLen)); + + /*******************************************************************************/ + /* ATR sent, check response */ + /*******************************************************************************/ + msgIt = 0; + rxLen = ((uint16_t)rxBuf[msgIt++] - RFAL_NFCDEP_LEN_LEN); /* use LEN byte */ + + if((rxLen < RFAL_NFCDEP_ATRRES_MIN_LEN) || + (rxLen > RFAL_NFCDEP_ATRRES_MAX_LEN)) /* Checking length: ATR_RES */ + { + return ERR_PROTO; + } + + if(rxBuf[msgIt++] != NFCIP_RES) /* Checking if is a response*/ + { + return ERR_PROTO; + } + + if(rxBuf[msgIt++] != (uint8_t)NFCIP_CMD_ATR_RES) /* Checking if is a ATR RES */ + { + return ERR_PROTO; + } + + ST_MEMCPY((uint8_t*)atrRes, (rxBuf + RFAL_NFCDEP_LEN_LEN), rxLen); + *atrResLen = (uint8_t)rxLen; + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcDepPSL(uint8_t BRS, uint8_t FSL) { + ReturnCode ret; + uint16_t rxLen; + uint8_t msgIt; + uint8_t txBuf[NFCIP_PSLREQ_LEN + NFCIP_PSLPAY_LEN]; + uint8_t rxBuf[NFCIP_PSLRES_LEN]; + + msgIt = NFCIP_PSLREQ_LEN; + + txBuf[msgIt++] = BRS; + txBuf[msgIt++] = FSL; + + /*******************************************************************************/ + /* Send PSL REQ and wait for response */ + /*******************************************************************************/ + EXIT_ON_ERR( + ret, + nfcipTxRx( + NFCIP_CMD_PSL_REQ, + txBuf, + nfcipRWTActivation(), + &txBuf[NFCIP_PSLREQ_LEN], + (msgIt - NFCIP_PSLREQ_LEN), + rxBuf, + NFCIP_PSLRES_LEN, + &rxLen)); + + /*******************************************************************************/ + /* PSL sent, check response */ + /*******************************************************************************/ + msgIt = 0; + rxLen = (uint16_t)(rxBuf[msgIt++]); /* use LEN byte */ + + if(rxLen < NFCIP_PSLRES_LEN) /* Checking length: LEN + RLS_RES */ + { + return ERR_PROTO; + } + + if(rxBuf[msgIt++] != NFCIP_RES) /* Checking if is a response */ + { + return ERR_PROTO; + } + + if(rxBuf[msgIt++] != (uint8_t)NFCIP_CMD_PSL_RES) /* Checking if is a PSL RES */ + { + return ERR_PROTO; + } + + if(rxBuf[msgIt++] != gNfcip.cfg.did) /* Checking DID */ + { + return ERR_PROTO; + } + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcDepDSL(void) { + ReturnCode ret; + uint8_t txBuf[RFAL_NFCDEP_HEADER_PAD + NFCIP_DSLREQ_LEN]; + uint8_t rxBuf[NFCIP_DSLRES_LEN]; + uint8_t rxMsgIt; + uint16_t rxLen = 0; + + if(gNfcip.cfg.role == RFAL_NFCDEP_ROLE_TARGET) { + return ERR_NONE; /* Target has no deselect procedure */ + } + + /* Repeating a DSL REQ is optional, not doing it */ + EXIT_ON_ERR( + ret, + nfcipTxRx( + NFCIP_CMD_DSL_REQ, + txBuf, + nfcipRWTActivation(), + NULL, + 0, + rxBuf, + (uint16_t)sizeof(rxBuf), + &rxLen)); + + /*******************************************************************************/ + rxMsgIt = 0; + + if(rxBuf[rxMsgIt++] < NFCIP_DSLRES_MIN) /* Checking length: LEN + DSL_RES */ + { + return ERR_PROTO; + } + + if(rxBuf[rxMsgIt++] != NFCIP_RES) /* Checking if is a response */ + { + return ERR_PROTO; + } + + if(rxBuf[rxMsgIt++] != (uint8_t)NFCIP_CMD_DSL_RES) /* Checking if is DSL RES */ + { + return ERR_PROTO; + } + + if(gNfcip.cfg.did != RFAL_NFCDEP_DID_NO) { + if(rxBuf[rxMsgIt++] != gNfcip.cfg.did) { + return ERR_PROTO; + } + } + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcDepRLS(void) { + ReturnCode ret; + uint8_t txBuf[RFAL_NFCDEP_HEADER_PAD + NFCIP_RLSREQ_LEN]; + uint8_t rxBuf[NFCIP_RLSRES_LEN]; + uint8_t rxMsgIt; + uint16_t rxLen = 0; + + if(gNfcip.cfg.role == RFAL_NFCDEP_ROLE_TARGET) /* Target has no release procedure */ + { + return ERR_NONE; + } + + /* Repeating a RLS REQ is optional, not doing it */ + EXIT_ON_ERR( + ret, + nfcipTxRx( + NFCIP_CMD_RLS_REQ, + txBuf, + nfcipRWTActivation(), + NULL, + 0, + rxBuf, + (uint16_t)sizeof(rxBuf), + &rxLen)); + + /*******************************************************************************/ + rxMsgIt = 0; + + if(rxBuf[rxMsgIt++] < NFCIP_RLSRES_MIN) /* Checking length: LEN + RLS_RES */ + { + return ERR_PROTO; + } + + if(rxBuf[rxMsgIt++] != NFCIP_RES) /* Checking if is a response */ + { + return ERR_PROTO; + } + + if(rxBuf[rxMsgIt++] != (uint8_t)NFCIP_CMD_RLS_RES) /* Checking if is RLS RES */ + { + return ERR_PROTO; + } + + if(gNfcip.cfg.did != RFAL_NFCDEP_DID_NO) { + if(rxBuf[rxMsgIt++] != gNfcip.cfg.did) { + return ERR_PROTO; + } + } + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcDepInitiatorHandleActivation( + rfalNfcDepAtrParam* param, + rfalBitRate desiredBR, + rfalNfcDepDevice* nfcDepDev) { + ReturnCode ret; + uint8_t maxRetyrs; + uint8_t PSL_BRS; + uint8_t PSL_FSL; + bool sendPSL; + + if((param == NULL) || (nfcDepDev == NULL)) { + return ERR_PARAM; + } + + param->NAD = RFAL_NFCDEP_NAD_NO; /* Digital 1.1 16.6.2.9 Initiator SHALL NOT use NAD */ + maxRetyrs = NFCIP_ATR_RETRY_MAX; + + /*******************************************************************************/ + /* Send ATR REQ and wait for response */ + /*******************************************************************************/ + do { /* Upon transmission error ATR REQ should be retried */ + + ret = rfalNfcDepATR( + param, + &nfcDepDev->activation.Target.ATR_RES, + &nfcDepDev->activation.Target.ATR_RESLen); + + if(nfcipIsTransmissionError(ret)) { + continue; + } + break; + } while((maxRetyrs--) != 0U); + + if(ret != ERR_NONE) { + return ret; + } + + /*******************************************************************************/ + /* Compute NFC-DEP device with ATR_RES */ + /*******************************************************************************/ + nfcDepDev->info.GBLen = (nfcDepDev->activation.Target.ATR_RESLen - RFAL_NFCDEP_ATRRES_MIN_LEN); + nfcDepDev->info.DID = nfcDepDev->activation.Target.ATR_RES.DID; + nfcDepDev->info.NAD = + RFAL_NFCDEP_NAD_NO; /* Digital 1.1 16.6.3.11 Initiator SHALL ignore b1 of PPt */ + nfcDepDev->info.LR = rfalNfcDepPP2LR(nfcDepDev->activation.Target.ATR_RES.PPt); + nfcDepDev->info.FS = rfalNfcDepLR2FS(nfcDepDev->info.LR); + nfcDepDev->info.WT = (nfcDepDev->activation.Target.ATR_RES.TO & RFAL_NFCDEP_WT_MASK); + nfcDepDev->info.FWT = rfalNfcDepCalculateRWT(nfcDepDev->info.WT); + nfcDepDev->info.dFWT = RFAL_NFCDEP_WT_DELTA; + + rfalGetBitRate(&nfcDepDev->info.DSI, &nfcDepDev->info.DRI); + + /*******************************************************************************/ + /* Check if a PSL needs to be sent */ + /*******************************************************************************/ + sendPSL = false; + PSL_BRS = rfalNfcDepDx2BRS( + nfcDepDev->info.DSI); /* Set current bit rate divisor on both directions */ + PSL_FSL = nfcDepDev->info.LR; /* Set current Frame Size */ + + /* Activity 1.0 9.4.4.15 & 9.4.6.3 NFC-DEP Activation PSL + * Activity 2.0 9.4.4.17 & 9.4.6.6 NFC-DEP Activation PSL + * + * PSL_REQ shall only be sent if desired bit rate is different from current (Activity 1.0) + * PSL_REQ shall be sent to update LR or bit rate (Activity 2.0) + * */ + +#if 0 /* PSL due to LR is disabled, can be enabled if desired*/ + /*******************************************************************************/ + /* Check Frame Size */ + /*******************************************************************************/ + if( gNfcip.cfg.lr < nfcDepDev->info.LR ) /* If our Length reduction is smaller */ + { + sendPSL = true; + + nfcDepDev->info.LR = MIN( nfcDepDev->info.LR, gNfcip.cfg.lr ); + + gNfcip.cfg.lr = nfcDepDev->info.LR; /* Update nfcip LR to be used */ + gNfcip.fsc = rfalNfcDepLR2FS( gNfcip.cfg.lr ); /* Update nfcip FSC to be used */ + + PSL_FSL = gNfcip.cfg.lr; /* Set LR to be sent */ + + nfcipLogI( " NFCIP(I) Frame Size differ, PSL new fsc: %d \r\n", gNfcip.fsc ); + } +#endif + + /*******************************************************************************/ + /* Check Baud rates */ + /*******************************************************************************/ + if((nfcDepDev->info.DSI != desiredBR) && + (desiredBR != RFAL_BR_KEEP)) /* if desired BR is different */ + { + if(nfcipDxIsSupported( + (uint8_t)desiredBR, + nfcDepDev->activation.Target.ATR_RES.BRt, + nfcDepDev->activation.Target.ATR_RES + .BSt)) /* if desired BR is supported */ /* MISRA 13.5 */ + { + sendPSL = true; + PSL_BRS = rfalNfcDepDx2BRS(desiredBR); + + nfcipLogI(" NFCIP(I) BR differ, PSL BR: 0x%02X \r\n", PSL_BRS); + } + } + + /*******************************************************************************/ + if(sendPSL) { + /*******************************************************************************/ + /* Send PSL REQ and wait for response */ + /*******************************************************************************/ + EXIT_ON_ERR(ret, rfalNfcDepPSL(PSL_BRS, PSL_FSL)); + + /* Check if bit rate has been changed */ + if(nfcDepDev->info.DSI != desiredBR) { + /* Check if device was in Passive NFC-A and went to higher bit rates, use NFC-F */ + if((nfcDepDev->info.DSI == RFAL_BR_106) && + (gNfcip.cfg.commMode == RFAL_NFCDEP_COMM_PASSIVE)) { +#if RFAL_FEATURE_NFCF + /* If Passive initialize NFC-F module */ + rfalNfcfPollerInitialize(desiredBR); +#else /* RFAL_FEATURE_NFCF */ + return ERR_NOTSUPP; +#endif /* RFAL_FEATURE_NFCF */ + } + + nfcDepDev->info.DRI = desiredBR; /* DSI Bit Rate coding from Initiator to Target */ + nfcDepDev->info.DSI = desiredBR; /* DRI Bit Rate coding from Target to Initiator */ + + rfalSetBitRate(nfcDepDev->info.DSI, nfcDepDev->info.DRI); + } + + return ERR_NONE; /* PSL has been sent */ + } + + return ERR_NONE; /* No PSL has been sent */ +} + +/*******************************************************************************/ +uint32_t rfalNfcDepCalculateRWT(uint8_t wt) { + /* Digital 1.0 14.6.3.8 & Digital 1.1 16.6.3.9 */ + /* Digital 1.1 16.6.3.9 treat all RFU values as WT=14 */ + uint8_t responseWaitTime = MIN(RFAL_NFCDEP_WT_INI_MAX, wt); + + return (uint32_t)rfalNfcDepWT2RWT(responseWaitTime); +} + +/*******************************************************************************/ +static ReturnCode nfcipDataTx(uint8_t* txBuf, uint16_t txBufLen, uint32_t fwt) { + return rfalTransceiveBlockingTx( + txBuf, + txBufLen, + gNfcip.rxBuf, + gNfcip.rxBufLen, + gNfcip.rxRcvdLen, + (RFAL_TXRX_FLAGS_DEFAULT | (uint32_t)RFAL_TXRX_FLAGS_NFCIP1_ON), + ((fwt == NFCIP_NO_FWT) ? RFAL_FWT_NONE : fwt)); +} + +/*******************************************************************************/ +static ReturnCode nfcipDataRx(bool blocking) { + ReturnCode ret; + + /* Perform Rx either blocking or non-blocking */ + if(blocking) { + ret = rfalTransceiveBlockingRx(); + } else { + ret = rfalGetTransceiveStatus(); + } + + if(ret != ERR_BUSY) { + if(gNfcip.rxRcvdLen != NULL) { + (*gNfcip.rxRcvdLen) = rfalConvBitsToBytes(*gNfcip.rxRcvdLen); + + if((ret == ERR_NONE) && (gNfcip.rxBuf != NULL)) { + /* Digital 1.1 16.4.1.3 - Length byte LEN SHALL have a value between 3 and 255 -> otherwise treat as Transmission Error * + * - Ensure that actual received and frame length do match, otherwise treat as Transmission error */ + if((*gNfcip.rxRcvdLen != (uint16_t)*gNfcip.rxBuf) || + (*gNfcip.rxRcvdLen < RFAL_NFCDEP_LEN_MIN) || + (*gNfcip.rxRcvdLen > RFAL_NFCDEP_LEN_MAX)) { + return ERR_FRAMING; + } + } + } + } + + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalNfcDepListenStartActivation( + const rfalNfcDepTargetParam* param, + const uint8_t* atrReq, + uint16_t atrReqLength, + rfalNfcDepListenActvParam rxParam) { + ReturnCode ret; + rfalNfcDepConfigs cfg; + + if((param == NULL) || (atrReq == NULL) || (rxParam.rxLen == NULL)) { + return ERR_PARAM; + } + + /*******************************************************************************/ + /* Check whether is a valid ATR_REQ Compute NFC-DEP device */ + if(!rfalNfcDepIsAtrReq(atrReq, atrReqLength, NULL)) { + return ERR_PARAM; + } + + rxParam.nfcDepDev->activation.Initiator.ATR_REQLen = + (uint8_t)atrReqLength; /* nfcipIsAtrReq() is already checking Min and Max buffer lengths */ + if(atrReqLength > 0U) /* MISRA 21.18 */ + { + ST_MEMCPY( + (uint8_t*)&rxParam.nfcDepDev->activation.Initiator.ATR_REQ, atrReq, atrReqLength); + } + + rxParam.nfcDepDev->info.GBLen = (uint8_t)(atrReqLength - RFAL_NFCDEP_ATRREQ_MIN_LEN); + rxParam.nfcDepDev->info.DID = rxParam.nfcDepDev->activation.Initiator.ATR_REQ.DID; + rxParam.nfcDepDev->info.NAD = + RFAL_NFCDEP_NAD_NO; /* Digital 1.1 16.6.2.9 Initiator SHALL NOT use NAD */ + rxParam.nfcDepDev->info.LR = + rfalNfcDepPP2LR(rxParam.nfcDepDev->activation.Initiator.ATR_REQ.PPi); + rxParam.nfcDepDev->info.FS = rfalNfcDepLR2FS(rxParam.nfcDepDev->info.LR); + rxParam.nfcDepDev->info.WT = 0; + rxParam.nfcDepDev->info.FWT = NFCIP_NO_FWT; + rxParam.nfcDepDev->info.dFWT = NFCIP_NO_FWT; + + rfalGetBitRate(&rxParam.nfcDepDev->info.DSI, &rxParam.nfcDepDev->info.DRI); + + /* Store Device Info location, updated upon a PSL */ + gNfcip.nfcDepDev = rxParam.nfcDepDev; + + /*******************************************************************************/ + cfg.did = rxParam.nfcDepDev->activation.Initiator.ATR_REQ.DID; + cfg.nad = RFAL_NFCDEP_NAD_NO; + + cfg.fwt = RFAL_NFCDEP_MAX_FWT; + cfg.dFwt = RFAL_NFCDEP_MAX_FWT; + + cfg.br = param->brt; + cfg.bs = param->bst; + + cfg.lr = rfalNfcDepPP2LR(param->ppt); + + cfg.gbLen = param->GBtLen; + if(cfg.gbLen > 0U) /* MISRA 21.18 */ + { + ST_MEMCPY(cfg.gb, param->GBt, cfg.gbLen); + } + + cfg.nfcidLen = RFAL_NFCDEP_NFCID3_LEN; + ST_MEMCPY(cfg.nfcid, param->nfcid3, RFAL_NFCDEP_NFCID3_LEN); + + cfg.to = param->to; + + cfg.role = RFAL_NFCDEP_ROLE_TARGET; + cfg.oper = param->operParam; + cfg.commMode = param->commMode; + + rfalNfcDepInitialize(); + nfcipConfig(&cfg); + + /*******************************************************************************/ + /* Reply with ATR RES to Initiator */ + /*******************************************************************************/ + gNfcip.rxBuf = (uint8_t*)rxParam.rxBuf; + gNfcip.rxBufLen = sizeof(rfalNfcDepBufFormat); + gNfcip.rxRcvdLen = rxParam.rxLen; + gNfcip.rxBufPaylPos = RFAL_NFCDEP_DEPREQ_HEADER_LEN; + gNfcip.isChaining = rxParam.isRxChaining; + gNfcip.txBufPaylPos = RFAL_NFCDEP_DEPREQ_HEADER_LEN; + + EXIT_ON_ERR(ret, nfcipTx(NFCIP_CMD_ATR_RES, (uint8_t*)gNfcip.rxBuf, NULL, 0, 0, NFCIP_NO_FWT)); + + gNfcip.state = NFCIP_ST_TARG_WAIT_ACTV; + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcDepListenGetActivationStatus(void) { + ReturnCode err; + uint8_t BRS; + + BRS = RFAL_NFCDEP_BRS_MAINTAIN; + + err = nfcipTargetHandleActivation(gNfcip.nfcDepDev, &BRS); + + switch(err) { + case ERR_NONE: + + if(BRS != RFAL_NFCDEP_BRS_MAINTAIN) { + /* DSI codes the bit rate from Initiator to Target */ + /* DRI codes the bit rate from Target to Initiator */ + + if(gNfcip.cfg.commMode == RFAL_NFCDEP_COMM_ACTIVE) { + EXIT_ON_ERR( + err, + rfalSetMode( + RFAL_MODE_LISTEN_ACTIVE_P2P, + gNfcip.nfcDepDev->info.DRI, + gNfcip.nfcDepDev->info.DSI)); + } else { + EXIT_ON_ERR( + err, + rfalSetMode( + ((RFAL_BR_106 == gNfcip.nfcDepDev->info.DRI) ? RFAL_MODE_LISTEN_NFCA : + RFAL_MODE_LISTEN_NFCF), + gNfcip.nfcDepDev->info.DRI, + gNfcip.nfcDepDev->info.DSI)); + } + } + break; + + case ERR_BUSY: + // do nothing + break; + + case ERR_PROTO: + default: + // re-enable receiving of data + nfcDepReEnableRx(gNfcip.rxBuf, gNfcip.rxBufLen, gNfcip.rxRcvdLen); + break; + } + + return err; +} + +/*******************************************************************************/ +ReturnCode rfalNfcDepStartTransceive(const rfalNfcDepTxRxParam* param) { + rfalNfcDepDEPParams nfcDepParams; + + nfcDepParams.txBuf = (uint8_t*)param->txBuf; + nfcDepParams.txBufLen = param->txBufLen; + nfcDepParams.txChaining = param->isTxChaining; + nfcDepParams.txBufPaylPos = + RFAL_NFCDEP_DEPREQ_HEADER_LEN; /* position in txBuf where actual outgoing data is located */ + nfcDepParams.did = RFAL_NFCDEP_DID_KEEP; + nfcDepParams.rxBufPaylPos = RFAL_NFCDEP_DEPREQ_HEADER_LEN; + nfcDepParams.rxBuf = (uint8_t*)param->rxBuf; + nfcDepParams.rxBufLen = sizeof(rfalNfcDepBufFormat); + nfcDepParams.fsc = param->FSx; + nfcDepParams.fwt = param->FWT; + nfcDepParams.dFwt = param->dFWT; + + gNfcip.rxRcvdLen = param->rxLen; + gNfcip.isChaining = param->isRxChaining; + + nfcipSetDEPParams(&nfcDepParams); + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcDepGetTransceiveStatus(void) { + return nfcipRun(gNfcip.rxRcvdLen, gNfcip.isChaining); +} + +/*******************************************************************************/ +static void rfalNfcDepPdu2BLockParam( + rfalNfcDepPduTxRxParam pduParam, + rfalNfcDepTxRxParam* blockParam, + uint16_t txPos, + uint16_t rxPos) { + uint16_t maxInfLen; + + NO_WARNING(rxPos); /* Keep this param for future use */ + + blockParam->DID = pduParam.DID; + blockParam->FSx = pduParam.FSx; + blockParam->FWT = pduParam.FWT; + blockParam->dFWT = pduParam.dFWT; + + /* Calculate max INF/Payload to be sent to other device */ + maxInfLen = (blockParam->FSx - (RFAL_NFCDEP_HEADER + RFAL_NFCDEP_DEP_PFB_LEN)); + maxInfLen += ((blockParam->DID != RFAL_NFCDEP_DID_NO) ? RFAL_NFCDEP_DID_LEN : 0U); + + if((pduParam.txBufLen - txPos) > maxInfLen) { + blockParam->isTxChaining = true; + blockParam->txBufLen = maxInfLen; + } else { + blockParam->isTxChaining = false; + blockParam->txBufLen = (pduParam.txBufLen - txPos); + } + + /* TxBuf is moved to the beginning for every Block */ + blockParam->txBuf = + (rfalNfcDepBufFormat*)pduParam + .txBuf; /* PRQA S 0310 # MISRA 11.3 - Intentional safe cast to avoiding large buffer duplication */ + blockParam->rxBuf = + pduParam + .tmpBuf; /* Simply using the pdu buffer is not possible because of current ACK handling */ + blockParam->isRxChaining = &gNfcip.isPDURxChaining; + blockParam->rxLen = pduParam.rxLen; +} + +/*******************************************************************************/ +ReturnCode rfalNfcDepStartPduTransceive(rfalNfcDepPduTxRxParam param) { + rfalNfcDepTxRxParam txRxParam; + + /* Initialize and store APDU context */ + gNfcip.PDUParam = param; + gNfcip.PDUTxPos = 0; + gNfcip.PDURxPos = 0; + + /* Convert PDU TxRxParams to Block TxRxParams */ + rfalNfcDepPdu2BLockParam(gNfcip.PDUParam, &txRxParam, gNfcip.PDUTxPos, gNfcip.PDURxPos); + + return rfalNfcDepStartTransceive(&txRxParam); +} + +/*******************************************************************************/ +ReturnCode rfalNfcDepGetPduTransceiveStatus(void) { + ReturnCode ret; + rfalNfcDepTxRxParam txRxParam; + + ret = rfalNfcDepGetTransceiveStatus(); + switch(ret) { + /*******************************************************************************/ + case ERR_NONE: + + /* Check if we are still doing chaining on Tx */ + if(gNfcip.isTxChaining) { + /* Add already Tx bytes */ + gNfcip.PDUTxPos += gNfcip.txBufLen; + + /* Convert APDU TxRxParams to I-Block TxRxParams */ + rfalNfcDepPdu2BLockParam( + gNfcip.PDUParam, &txRxParam, gNfcip.PDUTxPos, gNfcip.PDURxPos); + + if(txRxParam.txBufLen > 0U) /* MISRA 21.18 */ + { + /* Move next Block to beginning of APDU Tx buffer */ + ST_MEMCPY( + gNfcip.PDUParam.txBuf->pdu, + &gNfcip.PDUParam.txBuf->pdu[gNfcip.PDUTxPos], + txRxParam.txBufLen); + } + + EXIT_ON_ERR(ret, rfalNfcDepStartTransceive(&txRxParam)); + return ERR_BUSY; + } + + /* PDU TxRx is done */ + /* fall through */ + + /*******************************************************************************/ + case ERR_AGAIN: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + + /* Check if no PDU transceive has been started before (data from rfalNfcDepListenStartActivation) */ + if(gNfcip.PDUParam.rxLen == NULL) { + /* In Listen mode first chained packet cannot be retrieved via APDU interface */ + if(ret == ERR_AGAIN) { + return ERR_NOTSUPP; + } + + /* TxRx is complete and full data is already available */ + return ERR_NONE; + } + + if((*gNfcip.PDUParam.rxLen) > 0U) /* MISRA 21.18 */ + { + /* Ensure that data in tmpBuf still fits into PDU buffer */ + if((uint16_t)((uint16_t)gNfcip.PDURxPos + (*gNfcip.PDUParam.rxLen)) > + RFAL_FEATURE_NFC_DEP_PDU_MAX_LEN) { + return ERR_NOMEM; + } + + /* Copy chained packet from tmp buffer to PDU buffer */ + ST_MEMCPY( + &gNfcip.PDUParam.rxBuf->pdu[gNfcip.PDURxPos], + gNfcip.PDUParam.tmpBuf->inf, + *gNfcip.PDUParam.rxLen); + gNfcip.PDURxPos += *gNfcip.PDUParam.rxLen; + } + + /* Update output param rxLen */ + *gNfcip.PDUParam.rxLen = gNfcip.PDURxPos; + + /* Wait for following Block or PDU TxRx is done */ + return ((ret == ERR_AGAIN) ? ERR_BUSY : ERR_NONE); + + /*******************************************************************************/ + default: + /* MISRA 16.4: no empty default statement (a comment being enough) */ + break; + } + + return ret; +} + +#endif /* RFAL_FEATURE_NFC_DEP */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_nfca.c b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_nfca.c new file mode 100644 index 00000000000..856e9147d10 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_nfca.c @@ -0,0 +1,891 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_nfca.c + * + * \author Gustavo Patricio + * + * \brief Provides several NFC-A convenience methods and definitions + * + * It provides a Poller (ISO14443A PCD) interface and as well as + * some NFC-A Listener (ISO14443A PICC) helpers. + * + * The definitions and helpers methods provided by this module are only + * up to ISO14443-3 layer + * + */ + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "../include/rfal_nfca.h" +#include "../utils.h" + +/* + ****************************************************************************** + * ENABLE SWITCH + ****************************************************************************** + */ + +#ifndef RFAL_FEATURE_NFCA +#define RFAL_FEATURE_NFCA false /* NFC-A module configuration missing. Disabled by default */ +#endif + +#if RFAL_FEATURE_NFCA + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ + +#define RFAL_NFCA_SLP_FWT \ + rfalConvMsTo1fc(1) /*!< Check 1ms for any modulation ISO14443-3 6.4.3 */ +#define RFAL_NFCA_SLP_CMD 0x50U /*!< SLP cmd (byte1) Digital 1.1 6.9.1 & Table 20 */ +#define RFAL_NFCA_SLP_BYTE2 0x00U /*!< SLP byte2 Digital 1.1 6.9.1 & Table 20 */ +#define RFAL_NFCA_SLP_CMD_POS 0U /*!< SLP cmd position Digital 1.1 6.9.1 & Table 20 */ +#define RFAL_NFCA_SLP_BYTE2_POS 1U /*!< SLP byte2 position Digital 1.1 6.9.1 & Table 20 */ + +#define RFAL_NFCA_SDD_CT 0x88U /*!< Cascade Tag value Digital 1.1 6.7.2 */ +#define RFAL_NFCA_SDD_CT_LEN 1U /*!< Cascade Tag length */ + +#define RFAL_NFCA_SLP_REQ_LEN 2U /*!< SLP_REQ length */ + +#define RFAL_NFCA_SEL_CMD_LEN 1U /*!< SEL_CMD length */ +#define RFAL_NFCA_SEL_PAR_LEN 1U /*!< SEL_PAR length */ +#define RFAL_NFCA_SEL_SELPAR \ + rfalNfcaSelPar(7U, 0U) /*!< SEL_PAR on Select is always with 4 data/nfcid */ +#define RFAL_NFCA_BCC_LEN 1U /*!< BCC length */ + +#define RFAL_NFCA_SDD_REQ_LEN \ + (RFAL_NFCA_SEL_CMD_LEN + RFAL_NFCA_SEL_PAR_LEN) /*!< SDD_REQ length */ +#define RFAL_NFCA_SDD_RES_LEN \ + (RFAL_NFCA_CASCADE_1_UID_LEN + RFAL_NFCA_BCC_LEN) /*!< SDD_RES length */ + +#define RFAL_NFCA_T_RETRANS 5U /*!< t RETRANSMISSION [3, 33]ms EMVCo 2.6 A.5 */ +#define RFAL_NFCA_N_RETRANS 2U /*!< Number of retries EMVCo 2.6 9.6.1.3 */ + +/*! SDD_REQ (Select) Cascade Levels */ +enum { + RFAL_NFCA_SEL_CASCADE_L1 = 0, /*!< SDD_REQ Cascade Level 1 */ + RFAL_NFCA_SEL_CASCADE_L2 = 1, /*!< SDD_REQ Cascade Level 2 */ + RFAL_NFCA_SEL_CASCADE_L3 = 2 /*!< SDD_REQ Cascade Level 3 */ +}; + +/*! SDD_REQ (Select) request Cascade Level command Digital 1.1 Table 15 */ +enum { + RFAL_NFCA_CMD_SEL_CL1 = 0x93, /*!< SDD_REQ command Cascade Level 1 */ + RFAL_NFCA_CMD_SEL_CL2 = 0x95, /*!< SDD_REQ command Cascade Level 2 */ + RFAL_NFCA_CMD_SEL_CL3 = 0x97, /*!< SDD_REQ command Cascade Level 3 */ +}; + +/* +****************************************************************************** +* GLOBAL MACROS +****************************************************************************** +*/ +#define rfalNfcaSelPar(nBy, nbi) \ + (uint8_t)( \ + (((nBy) << 4U) & 0xF0U) | \ + ((nbi) & 0x0FU)) /*!< Calculates SEL_PAR with the bytes/bits to be sent */ +#define rfalNfcaCLn2SELCMD(cl) \ + (uint8_t)( \ + (uint8_t)(RFAL_NFCA_CMD_SEL_CL1) + \ + (2U * (cl))) /*!< Calculates SEL_CMD with the given cascade level */ +#define rfalNfcaNfcidLen2CL(len) \ + ((len) / 5U) /*!< Calculates cascade level by the NFCID length */ +#define rfalNfcaRunBlocking(e, fn) \ + do { \ + (e) = (fn); \ + rfalWorker(); \ + } while((e) == ERR_BUSY) /*!< Macro used for the blocking methods */ + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + +/*! Colission Resolution states */ +typedef enum { + RFAL_NFCA_CR_IDLE, /*!< IDLE state */ + RFAL_NFCA_CR_CL, /*!< New Cascading Level state */ + RFAL_NFCA_CR_SDD, /*!< Perform anticollsion state */ + RFAL_NFCA_CR_SEL, /*!< Perform CL Selection state */ + RFAL_NFCA_CR_DONE /*!< Collision Resolution done state */ +} colResState; + +/*! Colission Resolution context */ +typedef struct { + uint8_t devLimit; /*!< Device limit to be used */ + rfalComplianceMode compMode; /*!< Compliancy mode to be used */ + rfalNfcaListenDevice* + nfcaDevList; /*!< Location of the device list */ + uint8_t* devCnt; /*!< Location of the device counter */ + bool collPending; /*!< Collision pending flag */ + + bool* collPend; /*!< Location of collision pending flag (Single CR) */ + rfalNfcaSelReq selReq; /*!< SelReqused during anticollision (Single CR) */ + rfalNfcaSelRes* selRes; /*!< Location to place of the SEL_RES(SAK) (Single CR) */ + uint8_t* nfcId1; /*!< Location to place the NFCID1 (Single CR) */ + uint8_t* nfcId1Len; /*!< Location to place the NFCID1 length (Single CR) */ + uint8_t cascadeLv; /*!< Current Cascading Level (Single CR) */ + colResState state; /*!< Single Collision Resolution state (Single CR) */ + uint8_t bytesTxRx; /*!< TxRx bytes used during anticollision loop (Single CR) */ + uint8_t bitsTxRx; /*!< TxRx bits used during anticollision loop (Single CR) */ + uint16_t rxLen; + uint32_t tmrFDT; /*!< FDT timer used between SED_REQs (Single CR) */ + uint8_t retries; /*!< Retries to be performed upon a timeout error (Single CR)*/ + uint8_t backtrackCnt; /*!< Backtrack retries (Single CR) */ + bool doBacktrack; /*!< Backtrack flag (Single CR) */ +} colResParams; + +/*! RFAL NFC-A instance */ +typedef struct { + colResParams CR; /*!< Collision Resolution context */ +} rfalNfca; + +/*! SLP_REQ (HLTA) format Digital 1.1 6.9.1 & Table 20 */ +typedef struct { + uint8_t frame[RFAL_NFCA_SLP_REQ_LEN]; /*!< SLP: 0x50 0x00 */ +} rfalNfcaSlpReq; + +/* +****************************************************************************** +* LOCAL VARIABLES +****************************************************************************** +*/ +static rfalNfca gNfca; /*!< RFAL NFC-A instance */ + +/* +****************************************************************************** +* LOCAL FUNCTION PROTOTYPES +****************************************************************************** +*/ +static uint8_t rfalNfcaCalculateBcc(const uint8_t* buf, uint8_t bufLen); +static ReturnCode rfalNfcaPollerStartSingleCollisionResolution( + uint8_t devLimit, + bool* collPending, + rfalNfcaSelRes* selRes, + uint8_t* nfcId1, + uint8_t* nfcId1Len); +static ReturnCode rfalNfcaPollerGetSingleCollisionResolutionStatus(void); + +/* + ****************************************************************************** + * LOCAL FUNCTIONS + ****************************************************************************** + */ + +static uint8_t rfalNfcaCalculateBcc(const uint8_t* buf, uint8_t bufLen) { + uint8_t i; + uint8_t BCC; + + BCC = 0; + + /* BCC is XOR over first 4 bytes of the SDD_RES Digital 1.1 6.7.2 */ + for(i = 0; i < bufLen; i++) { + BCC ^= buf[i]; + } + + return BCC; +} + +/*******************************************************************************/ +static ReturnCode rfalNfcaPollerStartSingleCollisionResolution( + uint8_t devLimit, + bool* collPending, + rfalNfcaSelRes* selRes, + uint8_t* nfcId1, + uint8_t* nfcId1Len) { + /* Check parameters */ + if((collPending == NULL) || (selRes == NULL) || (nfcId1 == NULL) || (nfcId1Len == NULL)) { + return ERR_PARAM; + } + + /* Initialize output parameters */ + *collPending = false; /* Activity 1.1 9.3.4.6 */ + *nfcId1Len = 0; + ST_MEMSET(nfcId1, 0x00, RFAL_NFCA_CASCADE_3_UID_LEN); + + /* Save parameters */ + gNfca.CR.devLimit = devLimit; + gNfca.CR.collPend = collPending; + gNfca.CR.selRes = selRes; + gNfca.CR.nfcId1 = nfcId1; + gNfca.CR.nfcId1Len = nfcId1Len; + + platformTimerDestroy(gNfca.CR.tmrFDT); + gNfca.CR.tmrFDT = 0U; + gNfca.CR.retries = RFAL_NFCA_N_RETRANS; + gNfca.CR.cascadeLv = (uint8_t)RFAL_NFCA_SEL_CASCADE_L1; + gNfca.CR.state = RFAL_NFCA_CR_CL; + + gNfca.CR.doBacktrack = false; + gNfca.CR.backtrackCnt = 3U; + + return ERR_NONE; +} + +/*******************************************************************************/ +static ReturnCode rfalNfcaPollerGetSingleCollisionResolutionStatus(void) { + ReturnCode ret; + uint8_t collBit = 1U; /* standards mandate or recommend collision bit to be set to One. */ + + /* Check if FDT timer is still running */ + if(!platformTimerIsExpired(gNfca.CR.tmrFDT) && (gNfca.CR.tmrFDT != 0U)) { + return ERR_BUSY; + } + + /*******************************************************************************/ + /* Go through all Cascade Levels Activity 1.1 9.3.4 */ + if(gNfca.CR.cascadeLv > (uint8_t)RFAL_NFCA_SEL_CASCADE_L3) { + return ERR_INTERNAL; + } + + switch(gNfca.CR.state) { + /*******************************************************************************/ + case RFAL_NFCA_CR_CL: + + /* Initialize the SDD_REQ to send for the new cascade level */ + ST_MEMSET((uint8_t*)&gNfca.CR.selReq, 0x00, sizeof(rfalNfcaSelReq)); + + gNfca.CR.bytesTxRx = RFAL_NFCA_SDD_REQ_LEN; + gNfca.CR.bitsTxRx = 0U; + gNfca.CR.state = RFAL_NFCA_CR_SDD; + + /* fall through */ + + /*******************************************************************************/ + case RFAL_NFCA_CR_SDD: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + + /* Calculate SEL_CMD and SEL_PAR with the bytes/bits to be sent */ + gNfca.CR.selReq.selCmd = rfalNfcaCLn2SELCMD(gNfca.CR.cascadeLv); + gNfca.CR.selReq.selPar = rfalNfcaSelPar(gNfca.CR.bytesTxRx, gNfca.CR.bitsTxRx); + + /* Send SDD_REQ (Anticollision frame) */ + ret = rfalISO14443ATransceiveAnticollisionFrame( + (uint8_t*)&gNfca.CR.selReq, + &gNfca.CR.bytesTxRx, + &gNfca.CR.bitsTxRx, + &gNfca.CR.rxLen, + RFAL_NFCA_FDTMIN); + + /* Retry upon timeout EMVCo 2.6 9.6.1.3 */ + if((ret == ERR_TIMEOUT) && (gNfca.CR.devLimit == 0U) && (gNfca.CR.retries != 0U)) { + gNfca.CR.retries--; + platformTimerDestroy(gNfca.CR.tmrFDT); + gNfca.CR.tmrFDT = platformTimerCreate(RFAL_NFCA_T_RETRANS); + break; + } + + /* Covert rxLen into bytes */ + gNfca.CR.rxLen = rfalConvBitsToBytes(gNfca.CR.rxLen); + + if((ret == ERR_TIMEOUT) && (gNfca.CR.backtrackCnt != 0U) && (!gNfca.CR.doBacktrack) && + !((RFAL_NFCA_SDD_REQ_LEN == gNfca.CR.bytesTxRx) && (0U == gNfca.CR.bitsTxRx))) { + /* In multiple card scenarios it may always happen that some + * collisions of a weaker tag go unnoticed. If then a later + * collision is recognized and the strong tag has a 0 at the + * collision position then no tag will respond. Catch this + * corner case and then try with the bit being sent as zero. */ + rfalNfcaSensRes sensRes; + ret = ERR_RF_COLLISION; + rfalNfcaPollerCheckPresence(RFAL_14443A_SHORTFRAME_CMD_REQA, &sensRes); + /* Algorithm below does a post-increment, decrement to go back to current position */ + if(0U == gNfca.CR.bitsTxRx) { + gNfca.CR.bitsTxRx = 7; + gNfca.CR.bytesTxRx--; + } else { + gNfca.CR.bitsTxRx--; + } + collBit = (uint8_t)(((uint8_t*)&gNfca.CR.selReq)[gNfca.CR.bytesTxRx] & + (1U << gNfca.CR.bitsTxRx)); + collBit = (uint8_t)((0U == collBit) ? 1U : 0U); // invert the collision bit + gNfca.CR.doBacktrack = true; + gNfca.CR.backtrackCnt--; + } else { + gNfca.CR.doBacktrack = false; + } + + if(ret == ERR_RF_COLLISION) { + /* Check received length */ + if((gNfca.CR.bytesTxRx + ((gNfca.CR.bitsTxRx != 0U) ? 1U : 0U)) > + (RFAL_NFCA_SDD_RES_LEN + RFAL_NFCA_SDD_REQ_LEN)) { + return ERR_PROTO; + } + + if(((gNfca.CR.bytesTxRx + ((gNfca.CR.bitsTxRx != 0U) ? 1U : 0U)) > + (RFAL_NFCA_CASCADE_1_UID_LEN + RFAL_NFCA_SDD_REQ_LEN)) && + (gNfca.CR.backtrackCnt != 0U)) { /* Collision in BCC: Anticollide only UID part */ + gNfca.CR.backtrackCnt--; + gNfca.CR.bytesTxRx = RFAL_NFCA_CASCADE_1_UID_LEN + RFAL_NFCA_SDD_REQ_LEN - 1U; + gNfca.CR.bitsTxRx = 7; + collBit = + (uint8_t)(((uint8_t*)&gNfca.CR.selReq)[gNfca.CR.bytesTxRx] & + (1U + << gNfca.CR + .bitsTxRx)); /* Not a real collision, extract the actual bit for the subsequent code */ + } + + if((gNfca.CR.devLimit == 0U) && !(*gNfca.CR.collPend)) { + /* Activity 1.0 & 1.1 9.3.4.12: If CON_DEVICES_LIMIT has a value of 0, then + * NFC Forum Device is configured to perform collision detection only */ + *gNfca.CR.collPend = true; + return ERR_IGNORE; + } + + *gNfca.CR.collPend = true; + + /* Set and select the collision bit, with the number of bytes/bits successfully TxRx */ + if(collBit != 0U) { + ((uint8_t*)&gNfca.CR.selReq)[gNfca.CR.bytesTxRx] = + (uint8_t)(((uint8_t*)&gNfca.CR.selReq)[gNfca.CR.bytesTxRx] | + (1U << gNfca.CR.bitsTxRx)); /* MISRA 10.3 */ + } else { + ((uint8_t*)&gNfca.CR.selReq)[gNfca.CR.bytesTxRx] = + (uint8_t)(((uint8_t*)&gNfca.CR.selReq)[gNfca.CR.bytesTxRx] & + ~(1U << gNfca.CR.bitsTxRx)); /* MISRA 10.3 */ + } + + gNfca.CR.bitsTxRx++; + + /* Check if number of bits form a byte */ + if(gNfca.CR.bitsTxRx == RFAL_BITS_IN_BYTE) { + gNfca.CR.bitsTxRx = 0; + gNfca.CR.bytesTxRx++; + } + break; + } + + /*******************************************************************************/ + /* Check if Collision loop has failed */ + if(ret != ERR_NONE) { + return ret; + } + + /* If collisions are to be reported check whether the response is complete */ + if((gNfca.CR.devLimit == 0U) && (gNfca.CR.rxLen != sizeof(rfalNfcaSddRes))) { + return ERR_PROTO; + } + + /* Check if the received BCC match */ + if(gNfca.CR.selReq.bcc != + rfalNfcaCalculateBcc(gNfca.CR.selReq.nfcid1, RFAL_NFCA_CASCADE_1_UID_LEN)) { + return ERR_PROTO; + } + + /*******************************************************************************/ + /* Anticollision OK, Select this Cascade Level */ + gNfca.CR.selReq.selPar = RFAL_NFCA_SEL_SELPAR; + + gNfca.CR.retries = RFAL_NFCA_N_RETRANS; + gNfca.CR.state = RFAL_NFCA_CR_SEL; + break; + + /*******************************************************************************/ + case RFAL_NFCA_CR_SEL: + + /* Send SEL_REQ (Select command) - Retry upon timeout EMVCo 2.6 9.6.1.3 */ + ret = rfalTransceiveBlockingTxRx( + (uint8_t*)&gNfca.CR.selReq, + sizeof(rfalNfcaSelReq), + (uint8_t*)gNfca.CR.selRes, + sizeof(rfalNfcaSelRes), + &gNfca.CR.rxLen, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_NFCA_FDTMIN); + + /* Retry upon timeout EMVCo 2.6 9.6.1.3 */ + if((ret == ERR_TIMEOUT) && (gNfca.CR.devLimit == 0U) && (gNfca.CR.retries != 0U)) { + gNfca.CR.retries--; + platformTimerDestroy(gNfca.CR.tmrFDT); + gNfca.CR.tmrFDT = platformTimerCreate(RFAL_NFCA_T_RETRANS); + break; + } + + if(ret != ERR_NONE) { + return ret; + } + + /* Ensure proper response length */ + if(gNfca.CR.rxLen != sizeof(rfalNfcaSelRes)) { + return ERR_PROTO; + } + + /*******************************************************************************/ + /* Check cascade byte, if cascade tag then go next cascade level */ + if(*gNfca.CR.selReq.nfcid1 == RFAL_NFCA_SDD_CT) { + /* Cascade Tag present, store nfcid1 bytes (excluding cascade tag) and continue for next CL */ + ST_MEMCPY( + &gNfca.CR.nfcId1[*gNfca.CR.nfcId1Len], + &((uint8_t*)&gNfca.CR.selReq.nfcid1)[RFAL_NFCA_SDD_CT_LEN], + (RFAL_NFCA_CASCADE_1_UID_LEN - RFAL_NFCA_SDD_CT_LEN)); + *gNfca.CR.nfcId1Len += (RFAL_NFCA_CASCADE_1_UID_LEN - RFAL_NFCA_SDD_CT_LEN); + + /* Go to next cascade level */ + gNfca.CR.state = RFAL_NFCA_CR_CL; + gNfca.CR.cascadeLv++; + } else { + /* UID Selection complete, Stop Cascade Level loop */ + ST_MEMCPY( + &gNfca.CR.nfcId1[*gNfca.CR.nfcId1Len], + (uint8_t*)&gNfca.CR.selReq.nfcid1, + RFAL_NFCA_CASCADE_1_UID_LEN); + *gNfca.CR.nfcId1Len += RFAL_NFCA_CASCADE_1_UID_LEN; + + gNfca.CR.state = RFAL_NFCA_CR_DONE; + break; /* Only flag operation complete on the next execution */ + } + break; + + /*******************************************************************************/ + case RFAL_NFCA_CR_DONE: + return ERR_NONE; + + /*******************************************************************************/ + default: + return ERR_WRONG_STATE; + } + return ERR_BUSY; +} + +/* +****************************************************************************** +* GLOBAL FUNCTIONS +****************************************************************************** +*/ + +/*******************************************************************************/ +ReturnCode rfalNfcaPollerInitialize(void) { + ReturnCode ret; + + EXIT_ON_ERR(ret, rfalSetMode(RFAL_MODE_POLL_NFCA, RFAL_BR_106, RFAL_BR_106)); + rfalSetErrorHandling(RFAL_ERRORHANDLING_NFC); + + rfalSetGT(RFAL_GT_NFCA); + rfalSetFDTListen(RFAL_FDT_LISTEN_NFCA_POLLER); + rfalSetFDTPoll(RFAL_FDT_POLL_NFCA_POLLER); + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcaPollerCheckPresence(rfal14443AShortFrameCmd cmd, rfalNfcaSensRes* sensRes) { + ReturnCode ret; + uint16_t rcvLen; + + /* Digital 1.1 6.10.1.3 For Commands ALL_REQ, SENS_REQ, SDD_REQ, and SEL_REQ, the NFC Forum Device * + * MUST treat receipt of a Listen Frame at a time after FDT(Listen, min) as a Timeour Error */ + + ret = rfalISO14443ATransceiveShortFrame( + cmd, + (uint8_t*)sensRes, + (uint8_t)rfalConvBytesToBits(sizeof(rfalNfcaSensRes)), + &rcvLen, + RFAL_NFCA_FDTMIN); + if((ret == ERR_RF_COLLISION) || (ret == ERR_CRC) || (ret == ERR_NOMEM) || + (ret == ERR_FRAMING) || (ret == ERR_PAR)) { + ret = ERR_NONE; + } + + return ret; +} + +/*******************************************************************************/ +ReturnCode + rfalNfcaPollerTechnologyDetection(rfalComplianceMode compMode, rfalNfcaSensRes* sensRes) { + ReturnCode ret; + + EXIT_ON_ERR( + ret, + rfalNfcaPollerCheckPresence( + ((compMode == RFAL_COMPLIANCE_MODE_EMV) ? RFAL_14443A_SHORTFRAME_CMD_WUPA : + RFAL_14443A_SHORTFRAME_CMD_REQA), + sensRes)); + + /* Send SLP_REQ as Activity 1.1 9.2.3.6 and EMVCo 2.6 9.2.1.3 */ + if(compMode != RFAL_COMPLIANCE_MODE_ISO) { + rfalNfcaPollerSleep(); + } + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcaPollerSingleCollisionResolution( + uint8_t devLimit, + bool* collPending, + rfalNfcaSelRes* selRes, + uint8_t* nfcId1, + uint8_t* nfcId1Len) { + ReturnCode ret; + + EXIT_ON_ERR( + ret, + rfalNfcaPollerStartSingleCollisionResolution( + devLimit, collPending, selRes, nfcId1, nfcId1Len)); + rfalNfcaRunBlocking(ret, rfalNfcaPollerGetSingleCollisionResolutionStatus()); + + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalNfcaPollerStartFullCollisionResolution( + rfalComplianceMode compMode, + uint8_t devLimit, + rfalNfcaListenDevice* nfcaDevList, + uint8_t* devCnt) { + ReturnCode ret; + rfalNfcaSensRes sensRes; + uint16_t rcvLen; + + if((nfcaDevList == NULL) || (devCnt == NULL)) { + return ERR_PARAM; + } + + *devCnt = 0; + ret = ERR_NONE; + + /*******************************************************************************/ + /* Send ALL_REQ before Anticollision if a Sleep was sent before Activity 1.1 9.3.4.1 and EMVco 2.6 9.3.2.1 */ + if(compMode != RFAL_COMPLIANCE_MODE_ISO) { + ret = rfalISO14443ATransceiveShortFrame( + RFAL_14443A_SHORTFRAME_CMD_WUPA, + (uint8_t*)&nfcaDevList->sensRes, + (uint8_t)rfalConvBytesToBits(sizeof(rfalNfcaSensRes)), + &rcvLen, + RFAL_NFCA_FDTMIN); + if(ret != ERR_NONE) { + if((compMode == RFAL_COMPLIANCE_MODE_EMV) || + ((ret != ERR_RF_COLLISION) && (ret != ERR_CRC) && (ret != ERR_FRAMING) && + (ret != ERR_PAR))) { + return ret; + } + } + + /* Check proper SENS_RES/ATQA size */ + if((ret == ERR_NONE) && (rfalConvBytesToBits(sizeof(rfalNfcaSensRes)) != rcvLen)) { + return ERR_PROTO; + } + } + + /*******************************************************************************/ + /* Store the SENS_RES from Technology Detection or from WUPA */ + sensRes = nfcaDevList->sensRes; + + if(devLimit > 0U) /* MISRA 21.18 */ + { + ST_MEMSET(nfcaDevList, 0x00, (sizeof(rfalNfcaListenDevice) * devLimit)); + } + + /* Restore the prev SENS_RES, assuming that the SENS_RES received is from first device + * When only one device is detected it's not woken up then we'll have no SENS_RES (ATQA) */ + nfcaDevList->sensRes = sensRes; + + /* Save parameters */ + gNfca.CR.devCnt = devCnt; + gNfca.CR.devLimit = devLimit; + gNfca.CR.nfcaDevList = nfcaDevList; + gNfca.CR.compMode = compMode; + +#if RFAL_FEATURE_T1T + /*******************************************************************************/ + /* Only check for T1T if previous SENS_RES was received without a transmission * + * error. When collisions occur bits in the SENS_RES may look like a T1T */ + /* If T1T Anticollision is not supported Activity 1.1 9.3.4.3 */ + if(rfalNfcaIsSensResT1T(&nfcaDevList->sensRes) && (devLimit != 0U) && (ret == ERR_NONE) && + (compMode != RFAL_COMPLIANCE_MODE_EMV)) { + /* RID_REQ shall be performed Activity 1.1 9.3.4.24 */ + rfalT1TPollerInitialize(); + EXIT_ON_ERR(ret, rfalT1TPollerRid(&nfcaDevList->ridRes)); + + *devCnt = 1U; + nfcaDevList->isSleep = false; + nfcaDevList->type = RFAL_NFCA_T1T; + nfcaDevList->nfcId1Len = RFAL_NFCA_CASCADE_1_UID_LEN; + ST_MEMCPY(&nfcaDevList->nfcId1, &nfcaDevList->ridRes.uid, RFAL_NFCA_CASCADE_1_UID_LEN); + + return ERR_NONE; + } +#endif /* RFAL_FEATURE_T1T */ + + return rfalNfcaPollerStartSingleCollisionResolution( + devLimit, + &gNfca.CR.collPending, + &nfcaDevList->selRes, + (uint8_t*)&nfcaDevList->nfcId1, + &nfcaDevList->nfcId1Len); +} + +/*******************************************************************************/ +ReturnCode rfalNfcaPollerGetFullCollisionResolutionStatus(void) { + ReturnCode ret; + uint8_t newDevType; + + if((gNfca.CR.nfcaDevList == NULL) || (gNfca.CR.devCnt == NULL)) { + return ERR_WRONG_STATE; + } + + /*******************************************************************************/ + /* Check whether a T1T has already been detected */ + if(rfalNfcaIsSensResT1T(&gNfca.CR.nfcaDevList->sensRes) && + (gNfca.CR.nfcaDevList->type == RFAL_NFCA_T1T)) { + /* T1T doesn't support Anticollision */ + return ERR_NONE; + } + + /*******************************************************************************/ + EXIT_ON_ERR(ret, rfalNfcaPollerGetSingleCollisionResolutionStatus()); + + /* Assign Listen Device */ + newDevType = ((uint8_t)gNfca.CR.nfcaDevList[*gNfca.CR.devCnt].selRes.sak) & + RFAL_NFCA_SEL_RES_CONF_MASK; /* MISRA 10.8 */ + /* PRQA S 4342 1 # MISRA 10.5 - Guaranteed that no invalid enum values are created: see guard_eq_RFAL_NFCA_T2T, .... */ + gNfca.CR.nfcaDevList[*gNfca.CR.devCnt].type = (rfalNfcaListenDeviceType)newDevType; + gNfca.CR.nfcaDevList[*gNfca.CR.devCnt].isSleep = false; + (*gNfca.CR.devCnt)++; + + /* If a collision was detected and device counter is lower than limit Activity 1.1 9.3.4.21 */ + if((*gNfca.CR.devCnt < gNfca.CR.devLimit) && (gNfca.CR.collPending)) { + /* Put this device to Sleep Activity 1.1 9.3.4.22 */ + rfalNfcaPollerSleep(); + gNfca.CR.nfcaDevList[(*gNfca.CR.devCnt - 1U)].isSleep = true; + + /* Send a new SENS_REQ to check for other cards Activity 1.1 9.3.4.23 */ + ret = rfalNfcaPollerCheckPresence( + RFAL_14443A_SHORTFRAME_CMD_REQA, &gNfca.CR.nfcaDevList[*gNfca.CR.devCnt].sensRes); + if(ret == ERR_TIMEOUT) { + /* No more devices found, exit */ + gNfca.CR.collPending = false; + } else { + /* Another device found, continue loop */ + gNfca.CR.collPending = true; + } + } else { + /* Exit loop */ + gNfca.CR.collPending = false; + } + + /*******************************************************************************/ + /* Check if collision resolution shall continue */ + if((*gNfca.CR.devCnt < gNfca.CR.devLimit) && (gNfca.CR.collPending)) { + EXIT_ON_ERR( + ret, + rfalNfcaPollerStartSingleCollisionResolution( + gNfca.CR.devLimit, + &gNfca.CR.collPending, + &gNfca.CR.nfcaDevList[*gNfca.CR.devCnt].selRes, + (uint8_t*)&gNfca.CR.nfcaDevList[*gNfca.CR.devCnt].nfcId1, + &gNfca.CR.nfcaDevList[*gNfca.CR.devCnt].nfcId1Len)); + + return ERR_BUSY; + } + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcaPollerFullCollisionResolution( + rfalComplianceMode compMode, + uint8_t devLimit, + rfalNfcaListenDevice* nfcaDevList, + uint8_t* devCnt) { + ReturnCode ret; + + EXIT_ON_ERR( + ret, rfalNfcaPollerStartFullCollisionResolution(compMode, devLimit, nfcaDevList, devCnt)); + rfalNfcaRunBlocking(ret, rfalNfcaPollerGetFullCollisionResolutionStatus()); + + return ret; +} + +ReturnCode rfalNfcaPollerSleepFullCollisionResolution( + uint8_t devLimit, + rfalNfcaListenDevice* nfcaDevList, + uint8_t* devCnt) { + bool firstRound; + uint8_t tmpDevCnt; + ReturnCode ret; + + if((nfcaDevList == NULL) || (devCnt == NULL)) { + return ERR_PARAM; + } + + /* Only use ALL_REQ (WUPA) on the first round */ + firstRound = true; + *devCnt = 0; + + /* Perform collision resolution until no new device is found */ + do { + tmpDevCnt = 0; + ret = rfalNfcaPollerFullCollisionResolution( + (firstRound ? RFAL_COMPLIANCE_MODE_NFC : RFAL_COMPLIANCE_MODE_ISO), + (devLimit - *devCnt), + &nfcaDevList[*devCnt], + &tmpDevCnt); + + if((ret == ERR_NONE) && (tmpDevCnt > 0U)) { + *devCnt += tmpDevCnt; + + /* Check whether to seacrh for more devices */ + if(*devCnt < devLimit) { + /* Set last found device to sleep (all others are slept already) */ + rfalNfcaPollerSleep(); + nfcaDevList[((*devCnt) - 1U)].isSleep = true; + + /* Check if any other device is present */ + ret = rfalNfcaPollerCheckPresence( + RFAL_14443A_SHORTFRAME_CMD_REQA, &nfcaDevList[*devCnt].sensRes); + if(ret == ERR_NONE) { + firstRound = false; + continue; + } + } + } + break; + } while(true); + + return ((*devCnt > 0U) ? ERR_NONE : ret); +} + +/*******************************************************************************/ +ReturnCode rfalNfcaPollerSelect(const uint8_t* nfcid1, uint8_t nfcidLen, rfalNfcaSelRes* selRes) { + uint8_t i; + uint8_t cl; + uint8_t nfcidOffset; + uint16_t rxLen; + ReturnCode ret; + rfalNfcaSelReq selReq; + + if((nfcid1 == NULL) || (nfcidLen > RFAL_NFCA_CASCADE_3_UID_LEN) || (selRes == NULL)) { + return ERR_PARAM; + } + + /* Calculate Cascate Level */ + cl = rfalNfcaNfcidLen2CL(nfcidLen); + nfcidOffset = 0; + + /*******************************************************************************/ + /* Go through all Cascade Levels Activity 1.1 9.4.4 */ + for(i = RFAL_NFCA_SEL_CASCADE_L1; i <= cl; i++) { + /* Assign SEL_CMD according to the CLn and SEL_PAR*/ + selReq.selCmd = rfalNfcaCLn2SELCMD(i); + selReq.selPar = RFAL_NFCA_SEL_SELPAR; + + /* Compute NFCID/Data on the SEL_REQ command Digital 1.1 Table 18 */ + if(cl != i) { + *selReq.nfcid1 = RFAL_NFCA_SDD_CT; + ST_MEMCPY( + &selReq.nfcid1[RFAL_NFCA_SDD_CT_LEN], + &nfcid1[nfcidOffset], + (RFAL_NFCA_CASCADE_1_UID_LEN - RFAL_NFCA_SDD_CT_LEN)); + nfcidOffset += (RFAL_NFCA_CASCADE_1_UID_LEN - RFAL_NFCA_SDD_CT_LEN); + } else { + ST_MEMCPY(selReq.nfcid1, &nfcid1[nfcidOffset], RFAL_NFCA_CASCADE_1_UID_LEN); + } + + /* Calculate nfcid's BCC */ + selReq.bcc = rfalNfcaCalculateBcc((uint8_t*)&selReq.nfcid1, sizeof(selReq.nfcid1)); + + /*******************************************************************************/ + /* Send SEL_REQ */ + EXIT_ON_ERR( + ret, + rfalTransceiveBlockingTxRx( + (uint8_t*)&selReq, + sizeof(rfalNfcaSelReq), + (uint8_t*)selRes, + sizeof(rfalNfcaSelRes), + &rxLen, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_NFCA_FDTMIN)); + + /* Ensure proper response length */ + if(rxLen != sizeof(rfalNfcaSelRes)) { + return ERR_PROTO; + } + } + + /* REMARK: Could check if NFCID1 is complete */ + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcaPollerSleep(void) { + rfalNfcaSlpReq slpReq; + uint8_t rxBuf; /* dummy buffer, just to perform Rx */ + + slpReq.frame[RFAL_NFCA_SLP_CMD_POS] = RFAL_NFCA_SLP_CMD; + slpReq.frame[RFAL_NFCA_SLP_BYTE2_POS] = RFAL_NFCA_SLP_BYTE2; + + rfalTransceiveBlockingTxRx( + (uint8_t*)&slpReq, + sizeof(rfalNfcaSlpReq), + &rxBuf, + sizeof(rxBuf), + NULL, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_NFCA_SLP_FWT); + + /* ISO14443-3 6.4.3 HLTA - If PICC responds with any modulation during 1 ms this response shall be interpreted as not acknowledge + Digital 2.0 6.9.2.1 & EMVCo 3.0 5.6.2.1 - consider the HLTA command always acknowledged + No check to be compliant with NFC and EMVCo, and to improve interoprability (Kovio RFID Tag) + */ + + return ERR_NONE; +} + +/*******************************************************************************/ +bool rfalNfcaListenerIsSleepReq(const uint8_t* buf, uint16_t bufLen) { + /* Check if length and payload match */ + if((bufLen != sizeof(rfalNfcaSlpReq)) || (buf[RFAL_NFCA_SLP_CMD_POS] != RFAL_NFCA_SLP_CMD) || + (buf[RFAL_NFCA_SLP_BYTE2_POS] != RFAL_NFCA_SLP_BYTE2)) { + return false; + } + + return true; +} + +/* If the guards here don't compile then the code above cannot work anymore. */ +extern uint8_t guard_eq_RFAL_NFCA_T2T + [((RFAL_NFCA_SEL_RES_CONF_MASK & (uint8_t)RFAL_NFCA_T2T) == (uint8_t)RFAL_NFCA_T2T) ? 1 : (-1)]; +extern uint8_t guard_eq_RFAL_NFCA_T4T + [((RFAL_NFCA_SEL_RES_CONF_MASK & (uint8_t)RFAL_NFCA_T4T) == (uint8_t)RFAL_NFCA_T4T) ? 1 : (-1)]; +extern uint8_t guard_eq_RFAL_NFCA_NFCDEP + [((RFAL_NFCA_SEL_RES_CONF_MASK & (uint8_t)RFAL_NFCA_NFCDEP) == (uint8_t)RFAL_NFCA_NFCDEP) ? + 1 : + (-1)]; +extern uint8_t guard_eq_RFAL_NFCA_T4T_NFCDEP + [((RFAL_NFCA_SEL_RES_CONF_MASK & (uint8_t)RFAL_NFCA_T4T_NFCDEP) == + (uint8_t)RFAL_NFCA_T4T_NFCDEP) ? + 1 : + (-1)]; +#endif /* RFAL_FEATURE_NFCA */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_nfcb.c b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_nfcb.c new file mode 100644 index 00000000000..8016ef839f6 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_nfcb.c @@ -0,0 +1,519 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_nfcb.c + * + * \author Gustavo Patricio + * + * \brief Implementation of NFC-B (ISO14443B) helpers + * + */ + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "../include/rfal_nfcb.h" +#include "../utils.h" + +/* + ****************************************************************************** + * ENABLE SWITCH + ****************************************************************************** + */ + +#ifndef RFAL_FEATURE_NFCB +#define RFAL_FEATURE_NFCB false /* NFC-B module configuration missing. Disabled by default */ +#endif + +#if RFAL_FEATURE_NFCB + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ + +#define RFAL_NFCB_SENSB_REQ_EXT_SENSB_RES_SUPPORTED \ + 0x10U /*!< Bit mask for Extended SensB Response support in SENSB_REQ */ +#define RFAL_NFCB_SENSB_RES_PROT_TYPE_RFU \ + 0x08U /*!< Bit mask for Protocol Type RFU in SENSB_RES */ +#define RFAL_NFCB_SLOT_MARKER_SC_SHIFT \ + 4U /*!< Slot Code position on SLOT_MARKER APn */ + +#define RFAL_NFCB_SLOTMARKER_SLOTCODE_MIN \ + 1U /*!< SLOT_MARKER Slot Code minimum Digital 1.1 Table 37 */ +#define RFAL_NFCB_SLOTMARKER_SLOTCODE_MAX \ + 16U /*!< SLOT_MARKER Slot Code maximum Digital 1.1 Table 37 */ + +#define RFAL_NFCB_ACTIVATION_FWT \ + (RFAL_NFCB_FWTSENSB + RFAL_NFCB_DTPOLL_20) /*!< FWT(SENSB) + dTbPoll Digital 2.0 7.9.1.3 */ + +/*! Advanced and Extended bit mask in Parameter of SENSB_REQ */ +#define RFAL_NFCB_SENSB_REQ_PARAM \ + (RFAL_NFCB_SENSB_REQ_ADV_FEATURE | RFAL_NFCB_SENSB_REQ_EXT_SENSB_RES_SUPPORTED) + +/*! NFC-B commands definition */ +enum { + RFAL_NFCB_CMD_SENSB_REQ = 0x05, /*!< SENSB_REQ (REQB) & SLOT_MARKER Digital 1.1 Table 24 */ + RFAL_NFCB_CMD_SENSB_RES = 0x50, /*!< SENSB_RES (ATQB) & SLOT_MARKER Digital 1.1 Table 27 */ + RFAL_NFCB_CMD_SLPB_REQ = 0x50, /*!< SLPB_REQ (HLTB command) Digital 1.1 Table 38 */ + RFAL_NFCB_CMD_SLPB_RES = 0x00 /*!< SLPB_RES (HLTB Answer) Digital 1.1 Table 39 */ +}; + +/* + ****************************************************************************** + * GLOBAL MACROS + ****************************************************************************** + */ + +#define rfalNfcbNI2NumberOfSlots(ni) \ + (uint8_t)(1U << (ni)) /*!< Converts the Number of slots Identifier to slot number */ + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + +/*! ALLB_REQ (WUPB) and SENSB_REQ (REQB) Command Format Digital 1.1 7.6.1 */ +typedef struct { + uint8_t cmd; /*!< xxxxB_REQ: 05h */ + uint8_t AFI; /*!< NFC Identifier */ + uint8_t PARAM; /*!< Application Data */ +} rfalNfcbSensbReq; + +/*! SLOT_MARKER Command format Digital 1.1 7.7.1 */ +typedef struct { + uint8_t APn; /*!< Slot number 2..16 | 0101b */ +} rfalNfcbSlotMarker; + +/*! SLPB_REQ (HLTB) Command Format Digital 1.1 7.8.1 */ +typedef struct { + uint8_t cmd; /*!< SLPB_REQ: 50h */ + uint8_t nfcid0[RFAL_NFCB_NFCID0_LEN]; /*!< NFC Identifier (PUPI)*/ +} rfalNfcbSlpbReq; + +/*! SLPB_RES (HLTB) Response Format Digital 1.1 7.8.2 */ +typedef struct { + uint8_t cmd; /*!< SLPB_RES: 00h */ +} rfalNfcbSlpbRes; + +/*! RFAL NFC-B instance */ +typedef struct { + uint8_t AFI; /*!< AFI to be used */ + uint8_t PARAM; /*!< PARAM to be used */ +} rfalNfcb; + +/* +****************************************************************************** +* LOCAL FUNCTION PROTOTYPES +****************************************************************************** +*/ +static ReturnCode rfalNfcbCheckSensbRes(const rfalNfcbSensbRes* sensbRes, uint8_t sensbResLen); + +/* +****************************************************************************** +* LOCAL VARIABLES +****************************************************************************** +*/ + +static rfalNfcb gRfalNfcb; /*!< RFAL NFC-B Instance */ + +/* +****************************************************************************** +* LOCAL FUNCTIONS +****************************************************************************** +*/ + +/*******************************************************************************/ +static ReturnCode rfalNfcbCheckSensbRes(const rfalNfcbSensbRes* sensbRes, uint8_t sensbResLen) { + /* Check response length */ + if(((sensbResLen != RFAL_NFCB_SENSB_RES_LEN) && + (sensbResLen != RFAL_NFCB_SENSB_RES_EXT_LEN))) { + return ERR_PROTO; + } + + /* Check SENSB_RES and Protocol Type Digital 1.1 7.6.2.19 */ + if(((sensbRes->protInfo.FsciProType & RFAL_NFCB_SENSB_RES_PROT_TYPE_RFU) != 0U) || + (sensbRes->cmd != (uint8_t)RFAL_NFCB_CMD_SENSB_RES)) { + return ERR_PROTO; + } + return ERR_NONE; +} + +/* +****************************************************************************** +* GLOBAL FUNCTIONS +****************************************************************************** +*/ + +/*******************************************************************************/ +ReturnCode rfalNfcbPollerInitialize(void) { + ReturnCode ret; + + EXIT_ON_ERR(ret, rfalSetMode(RFAL_MODE_POLL_NFCB, RFAL_BR_106, RFAL_BR_106)); + rfalSetErrorHandling(RFAL_ERRORHANDLING_NFC); + + rfalSetGT(RFAL_GT_NFCB); + rfalSetFDTListen(RFAL_FDT_LISTEN_NFCB_POLLER); + rfalSetFDTPoll(RFAL_FDT_POLL_NFCB_POLLER); + + gRfalNfcb.AFI = RFAL_NFCB_AFI; + gRfalNfcb.PARAM = RFAL_NFCB_PARAM; + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcbPollerInitializeWithParams(uint8_t AFI, uint8_t PARAM) { + ReturnCode ret; + + EXIT_ON_ERR(ret, rfalNfcbPollerInitialize()); + + gRfalNfcb.AFI = AFI; + gRfalNfcb.PARAM = (PARAM & RFAL_NFCB_SENSB_REQ_PARAM); + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcbPollerCheckPresence( + rfalNfcbSensCmd cmd, + rfalNfcbSlots slots, + rfalNfcbSensbRes* sensbRes, + uint8_t* sensbResLen) { + uint16_t rxLen; + ReturnCode ret; + rfalNfcbSensbReq sensbReq; + + /* Check if the command requested and given the slot number are valid */ + if(((RFAL_NFCB_SENS_CMD_SENSB_REQ != cmd) && (RFAL_NFCB_SENS_CMD_ALLB_REQ != cmd)) || + (slots > RFAL_NFCB_SLOT_NUM_16) || (sensbRes == NULL) || (sensbResLen == NULL)) { + return ERR_PARAM; + } + + *sensbResLen = 0; + ST_MEMSET(sensbRes, 0x00, sizeof(rfalNfcbSensbRes)); + + /* Compute SENSB_REQ */ + sensbReq.cmd = RFAL_NFCB_CMD_SENSB_REQ; + sensbReq.AFI = gRfalNfcb.AFI; + sensbReq.PARAM = + (((uint8_t)gRfalNfcb.PARAM & RFAL_NFCB_SENSB_REQ_PARAM) | (uint8_t)cmd | (uint8_t)slots); + + /* Send SENSB_REQ and disable AGC to detect collisions */ + ret = rfalTransceiveBlockingTxRx( + (uint8_t*)&sensbReq, + sizeof(rfalNfcbSensbReq), + (uint8_t*)sensbRes, + sizeof(rfalNfcbSensbRes), + &rxLen, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_NFCB_FWTSENSB); + + *sensbResLen = (uint8_t)rxLen; + + /* Check if a transmission error was detected */ + if((ret == ERR_CRC) || (ret == ERR_FRAMING)) { + /* Invalidate received frame as an error was detected (CollisionResolution checks if valid) */ + *sensbResLen = 0; + return ERR_NONE; + } + + if(ret == ERR_NONE) { + return rfalNfcbCheckSensbRes(sensbRes, *sensbResLen); + } + + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalNfcbPollerSleep(const uint8_t* nfcid0) { + uint16_t rxLen; + ReturnCode ret; + rfalNfcbSlpbReq slpbReq; + rfalNfcbSlpbRes slpbRes; + + if(nfcid0 == NULL) { + return ERR_PARAM; + } + + /* Compute SLPB_REQ */ + slpbReq.cmd = RFAL_NFCB_CMD_SLPB_REQ; + ST_MEMCPY(slpbReq.nfcid0, nfcid0, RFAL_NFCB_NFCID0_LEN); + + EXIT_ON_ERR( + ret, + rfalTransceiveBlockingTxRx( + (uint8_t*)&slpbReq, + sizeof(rfalNfcbSlpbReq), + (uint8_t*)&slpbRes, + sizeof(rfalNfcbSlpbRes), + &rxLen, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_NFCB_ACTIVATION_FWT)); + + /* Check SLPB_RES */ + if((rxLen != sizeof(rfalNfcbSlpbRes)) || (slpbRes.cmd != (uint8_t)RFAL_NFCB_CMD_SLPB_RES)) { + return ERR_PROTO; + } + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode + rfalNfcbPollerSlotMarker(uint8_t slotCode, rfalNfcbSensbRes* sensbRes, uint8_t* sensbResLen) { + ReturnCode ret; + rfalNfcbSlotMarker slotMarker; + uint16_t rxLen; + + /* Check parameters */ + if((sensbRes == NULL) || (sensbResLen == NULL) || + (slotCode < RFAL_NFCB_SLOTMARKER_SLOTCODE_MIN) || + (slotCode > RFAL_NFCB_SLOTMARKER_SLOTCODE_MAX)) { + return ERR_PARAM; + } + /* Compose and send SLOT_MARKER with disabled AGC to detect collisions */ + slotMarker.APn = + ((slotCode << RFAL_NFCB_SLOT_MARKER_SC_SHIFT) | (uint8_t)RFAL_NFCB_CMD_SENSB_REQ); + + ret = rfalTransceiveBlockingTxRx( + (uint8_t*)&slotMarker, + sizeof(rfalNfcbSlotMarker), + (uint8_t*)sensbRes, + sizeof(rfalNfcbSensbRes), + &rxLen, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_NFCB_ACTIVATION_FWT); + + *sensbResLen = (uint8_t)rxLen; + + /* Check if a transmission error was detected */ + if((ret == ERR_CRC) || (ret == ERR_FRAMING)) { + return ERR_RF_COLLISION; + } + + if(ret == ERR_NONE) { + return rfalNfcbCheckSensbRes(sensbRes, *sensbResLen); + } + + return ret; +} + +ReturnCode rfalNfcbPollerTechnologyDetection( + rfalComplianceMode compMode, + rfalNfcbSensbRes* sensbRes, + uint8_t* sensbResLen) { + NO_WARNING(compMode); + + return rfalNfcbPollerCheckPresence( + RFAL_NFCB_SENS_CMD_SENSB_REQ, RFAL_NFCB_SLOT_NUM_1, sensbRes, sensbResLen); +} + +/*******************************************************************************/ +ReturnCode rfalNfcbPollerCollisionResolution( + rfalComplianceMode compMode, + uint8_t devLimit, + rfalNfcbListenDevice* nfcbDevList, + uint8_t* devCnt) { + bool colPending; /* dummy */ + return rfalNfcbPollerSlottedCollisionResolution( + compMode, + devLimit, + RFAL_NFCB_SLOT_NUM_1, + RFAL_NFCB_SLOT_NUM_16, + nfcbDevList, + devCnt, + &colPending); +} + +/*******************************************************************************/ +ReturnCode rfalNfcbPollerSlottedCollisionResolution( + rfalComplianceMode compMode, + uint8_t devLimit, + rfalNfcbSlots initSlots, + rfalNfcbSlots endSlots, + rfalNfcbListenDevice* nfcbDevList, + uint8_t* devCnt, + bool* colPending) { + ReturnCode ret; + uint8_t slotsNum; + uint8_t slotCode; + uint8_t curDevCnt; + + /* Check parameters. In ISO | Activity 1.0 mode the initial slots must be 1 as continuation of Technology Detection */ + if((nfcbDevList == NULL) || (devCnt == NULL) || (colPending == NULL) || + (initSlots > RFAL_NFCB_SLOT_NUM_16) || (endSlots > RFAL_NFCB_SLOT_NUM_16) || + ((compMode == RFAL_COMPLIANCE_MODE_ISO) && (initSlots != RFAL_NFCB_SLOT_NUM_1))) { + return ERR_PARAM; + } + + /* Initialise as no error in case Activity 1.0 where the previous SENSB_RES from technology detection should be used */ + ret = ERR_NONE; + *devCnt = 0; + curDevCnt = 0; + *colPending = false; + + /* Send ALLB_REQ Activity 1.1 9.3.5.2 and 9.3.5.3 (Symbol 1 and 2) */ + if(compMode != RFAL_COMPLIANCE_MODE_ISO) { + ret = rfalNfcbPollerCheckPresence( + RFAL_NFCB_SENS_CMD_ALLB_REQ, + initSlots, + &nfcbDevList->sensbRes, + &nfcbDevList->sensbResLen); + if((ret != ERR_NONE) && (initSlots == RFAL_NFCB_SLOT_NUM_1)) { + return ret; + } + } + + /* Check if there was a transmission error on WUPB EMVCo 2.6 9.3.3.1 */ + if((compMode == RFAL_COMPLIANCE_MODE_EMV) && (nfcbDevList->sensbResLen == 0U)) { + return ERR_FRAMING; + } + + for(slotsNum = (uint8_t)initSlots; slotsNum <= (uint8_t)endSlots; slotsNum++) { + do { + /* Activity 1.1 9.3.5.23 - Symbol 22 */ + if((compMode == RFAL_COMPLIANCE_MODE_NFC) && (curDevCnt != 0U)) { + rfalNfcbPollerSleep(nfcbDevList[((*devCnt) - (uint8_t)1U)].sensbRes.nfcid0); + nfcbDevList[((*devCnt) - (uint8_t)1U)].isSleep = true; + } + + /* Send SENSB_REQ with number of slots if not the first Activity 1.1 9.3.5.24 - Symbol 23 */ + if((slotsNum != (uint8_t)initSlots) || *colPending) { + /* PRQA S 4342 1 # MISRA 10.5 - Layout of rfalNfcbSlots and above loop guarantee that no invalid enum values are created. */ + ret = rfalNfcbPollerCheckPresence( + RFAL_NFCB_SENS_CMD_SENSB_REQ, + (rfalNfcbSlots)slotsNum, + &nfcbDevList[*devCnt].sensbRes, + &nfcbDevList[*devCnt].sensbResLen); + } + + /* Activity 1.1 9.3.5.6 - Symbol 5 */ + slotCode = 0; + curDevCnt = 0; + *colPending = false; + + do { + /* Activity 1.1 9.3.5.26 - Symbol 25 */ + if(slotCode != 0U) { + ret = rfalNfcbPollerSlotMarker( + slotCode, + &nfcbDevList[*devCnt].sensbRes, + &nfcbDevList[*devCnt].sensbResLen); + } + + /* Activity 1.1 9.3.5.7 and 9.3.5.8 - Symbol 6 */ + if(ret != ERR_TIMEOUT) { + /* Activity 1.1 9.3.5.8 - Symbol 7 */ + if((rfalNfcbCheckSensbRes( + &nfcbDevList[*devCnt].sensbRes, nfcbDevList[*devCnt].sensbResLen) == + ERR_NONE) && + (ret == ERR_NONE)) { + nfcbDevList[*devCnt].isSleep = false; + + if(compMode == RFAL_COMPLIANCE_MODE_EMV) { + (*devCnt)++; + return ret; + } else if(compMode == RFAL_COMPLIANCE_MODE_ISO) { + /* Activity 1.0 9.3.5.8 - Symbol 7 */ + (*devCnt)++; + curDevCnt++; + + /* Activity 1.0 9.3.5.10 - Symbol 9 */ + if((*devCnt >= devLimit) || + (slotsNum == (uint8_t)RFAL_NFCB_SLOT_NUM_1)) { + return ret; + } + + /* Activity 1.0 9.3.5.11 - Symbol 10 */ + rfalNfcbPollerSleep(nfcbDevList[*devCnt - 1U].sensbRes.nfcid0); + nfcbDevList[*devCnt - 1U].isSleep = true; + } else if(compMode == RFAL_COMPLIANCE_MODE_NFC) { + /* Activity 1.1 9.3.5.10 and 9.3.5.11 - Symbol 9 and Symbol 11*/ + if(curDevCnt != 0U) { + rfalNfcbPollerSleep( + nfcbDevList[(*devCnt) - (uint8_t)1U].sensbRes.nfcid0); + nfcbDevList[(*devCnt) - (uint8_t)1U].isSleep = true; + } + + /* Activity 1.1 9.3.5.12 - Symbol 11 */ + (*devCnt)++; + curDevCnt++; + + /* Activity 1.1 9.3.5.6 - Symbol 13 */ + if((*devCnt >= devLimit) || + (slotsNum == (uint8_t)RFAL_NFCB_SLOT_NUM_1)) { + return ret; + } + } else { + /* MISRA 15.7 - Empty else */ + } + } else { + /* If deviceLimit is set to 0 the NFC Forum Device is configured to perform collision detection only Activity 1.0 and 1.1 9.3.5.5 - Symbol 4 */ + if((devLimit == 0U) && (slotsNum == (uint8_t)RFAL_NFCB_SLOT_NUM_1)) { + return ERR_RF_COLLISION; + } + + /* Activity 1.1 9.3.5.9 - Symbol 8 */ + *colPending = true; + } + } + + /* Activity 1.1 9.3.5.15 - Symbol 14 */ + slotCode++; + } while(slotCode < rfalNfcbNI2NumberOfSlots(slotsNum)); + + /* Activity 1.1 9.3.5.17 - Symbol 16 */ + if(!(*colPending)) { + return ERR_NONE; + } + + /* Activity 1.1 9.3.5.18 - Symbol 17 */ + } while( + curDevCnt != + 0U); /* If a collision is detected and card(s) were found on this loop keep the same number of available slots */ + } + + return ERR_NONE; +} + +/*******************************************************************************/ +uint32_t rfalNfcbTR2ToFDT(uint8_t tr2Code) { + /*******************************************************************************/ + /* MISRA 8.9 An object should be defined at block scope if its identifier only appears in a single function */ + /*! TR2 Table according to Digital 1.1 Table 33 */ + const uint16_t rfalNfcbTr2Table[] = {1792, 3328, 5376, 9472}; + /*******************************************************************************/ + + return rfalNfcbTr2Table[(tr2Code & RFAL_NFCB_SENSB_RES_PROTO_TR2_MASK)]; +} + +#endif /* RFAL_FEATURE_NFCB */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_nfcf.c b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_nfcf.c new file mode 100644 index 00000000000..f5f6373ebfc --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_nfcf.c @@ -0,0 +1,587 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_nfcf.c + * + * \author Gustavo Patricio + * + * \brief Implementation of NFC-F Poller (FeliCa PCD) device + * + * The definitions and helpers methods provided by this module are + * aligned with NFC-F (FeliCa - JIS X6319-4) + * + */ + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "../include/rfal_nfcf.h" +#include "../utils.h" + +/* + ****************************************************************************** + * ENABLE SWITCH + ****************************************************************************** + */ + +#ifndef RFAL_FEATURE_NFCF +#define RFAL_FEATURE_NFCF false /* NFC-F module configuration missing. Disabled by default */ +#endif + +#if RFAL_FEATURE_NFCF + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ +#define RFAL_NFCF_SENSF_REQ_LEN_MIN \ + 5U /*!< SENSF_RES minimum length */ + +#define RFAL_NFCF_READ_WO_ENCRYPTION_MIN_LEN \ + 15U /*!< Minimum length for a Check Command T3T 5.4.1 */ +#define RFAL_NFCF_WRITE_WO_ENCRYPTION_MIN_LEN \ + 31U /*!< Minimum length for an Update Command T3T 5.5.1 */ + +#define RFAL_NFCF_CHECK_RES_MIN_LEN \ + 11U /*!< CHECK Response minimum length T3T 1.0 Table 8 */ +#define RFAL_NFCF_UPDATE_RES_MIN_LEN \ + 11U /*!< UPDATE Response minimum length T3T 1.0 Table 8 */ + +#define RFAL_NFCF_CHECK_REQ_MAX_LEN \ + 86U /*!< Max length of a Check request T3T 1.0 Table 7 */ +#define RFAL_NFCF_CHECK_REQ_MAX_SERV \ + 15U /*!< Max Services number on Check request T3T 1.0 5.4.1.5 */ +#define RFAL_NFCF_CHECK_REQ_MAX_BLOCK \ + 15U /*!< Max Blocks number on Check request T3T 1.0 5.4.1.10 */ +#define RFAL_NFCF_UPDATE_REQ_MAX_SERV \ + 15U /*!< Max Services number Update request T3T 1.0 5.4.1.5 */ +#define RFAL_NFCF_UPDATE_REQ_MAX_BLOCK \ + 13U /*!< Max Blocks number on Update request T3T 1.0 5.4.1.10 */ + +/*! MRT Check | Uupdate = (Tt3t x ((A+1) + n (B+1)) x 4^E) + dRWTt3t T3T 5.8 + Max values used: A = 7 ; B = 7 ; E = 3 ; n = 15 (NFC Forum n = 15, JIS n = 32) +*/ +#define RFAL_NFCF_MRT_CHECK_UPDATE ((4096 * (8 + (15 * 8)) * 64) + 16) + +/* + ****************************************************************************** + * GLOBAL MACROS + ****************************************************************************** + */ +#define rfalNfcfSlots2CardNum(s) \ + ((uint8_t)(s) + 1U) /*!< Converts Time Slot Number (TSN) into num of slots */ + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + +/*! Structure/Buffer to hold the SENSF_RES with LEN byte prepended */ +typedef struct { + uint8_t LEN; /*!< NFC-F LEN byte */ + rfalNfcfSensfRes SENSF_RES; /*!< SENSF_RES */ +} rfalNfcfSensfResBuf; + +/*! Greedy collection for NFCF GRE_POLL_F Activity 1.0 Table 10 */ +typedef struct { + uint8_t pollFound; /*!< Number of devices found by the Poll */ + uint8_t pollCollision; /*!< Number of collisions detected */ + rfalFeliCaPollRes POLL_F[RFAL_NFCF_POLL_MAXCARDS]; /*!< GRE_POLL_F Activity 1.0 Table 10 */ +} rfalNfcfGreedyF; + +/*! NFC-F SENSF_REQ format Digital 1.1 8.6.1 */ +typedef struct { + uint8_t CMD; /*!< Command code: 00h */ + uint8_t SC[RFAL_NFCF_SENSF_SC_LEN]; /*!< System Code */ + uint8_t RC; /*!< Request Code */ + uint8_t TSN; /*!< Time Slot Number */ +} rfalNfcfSensfReq; + +/* +****************************************************************************** +* LOCAL VARIABLES +****************************************************************************** +*/ +static rfalNfcfGreedyF gRfalNfcfGreedyF; /*!< Activity's NFCF Greedy collection */ + +/* +****************************************************************************** +* LOCAL FUNCTION PROTOTYPES +****************************************************************************** +*/ +static void rfalNfcfComputeValidSENF( + rfalNfcfListenDevice* outDevInfo, + uint8_t* curDevIdx, + uint8_t devLimit, + bool overwrite, + bool* nfcDepFound); + +/* +****************************************************************************** +* LOCAL VARIABLES +****************************************************************************** +*/ + +/*******************************************************************************/ +static void rfalNfcfComputeValidSENF( + rfalNfcfListenDevice* outDevInfo, + uint8_t* curDevIdx, + uint8_t devLimit, + bool overwrite, + bool* nfcDepFound) { + uint8_t tmpIdx; + bool duplicate; + const rfalNfcfSensfResBuf* sensfBuf; + rfalNfcfSensfResBuf sensfCopy; + + /*******************************************************************************/ + /* Go through all responses check if valid and duplicates */ + /*******************************************************************************/ + while((gRfalNfcfGreedyF.pollFound > 0U) && ((*curDevIdx) < devLimit)) { + duplicate = false; + gRfalNfcfGreedyF.pollFound--; + + /* MISRA 11.3 - Cannot point directly into different object type, use local copy */ + ST_MEMCPY( + (uint8_t*)&sensfCopy, + (uint8_t*)&gRfalNfcfGreedyF.POLL_F[gRfalNfcfGreedyF.pollFound], + sizeof(rfalNfcfSensfResBuf)); + + /* Point to received SENSF_RES */ + sensfBuf = &sensfCopy; + + /* Check for devices that are already in device list */ + for(tmpIdx = 0; tmpIdx < (*curDevIdx); tmpIdx++) { + if(ST_BYTECMP( + sensfBuf->SENSF_RES.NFCID2, + outDevInfo[tmpIdx].sensfRes.NFCID2, + RFAL_NFCF_NFCID2_LEN) == 0) { + duplicate = true; + break; + } + } + + /* If is a duplicate skip this (and not to overwrite)*/ + if(duplicate && !overwrite) { + continue; + } + + /* Check if response length is OK */ + if(((sensfBuf->LEN - RFAL_NFCF_HEADER_LEN) < RFAL_NFCF_SENSF_RES_LEN_MIN) || + ((sensfBuf->LEN - RFAL_NFCF_HEADER_LEN) > RFAL_NFCF_SENSF_RES_LEN_MAX)) { + continue; + } + + /* Check if the response is a SENSF_RES / Polling response */ + if(sensfBuf->SENSF_RES.CMD != (uint8_t)RFAL_NFCF_CMD_POLLING_RES) { + continue; + } + + /* Check if is an overwrite request or new device*/ + if(duplicate && overwrite) { + /* overwrite deviceInfo/GRE_SENSF_RES with SENSF_RES */ + outDevInfo[tmpIdx].sensfResLen = (sensfBuf->LEN - RFAL_NFCF_LENGTH_LEN); + ST_MEMCPY( + &outDevInfo[tmpIdx].sensfRes, + &sensfBuf->SENSF_RES, + outDevInfo[tmpIdx].sensfResLen); + continue; + } else { + /* fill deviceInfo/GRE_SENSF_RES with new SENSF_RES */ + outDevInfo[(*curDevIdx)].sensfResLen = (sensfBuf->LEN - RFAL_NFCF_LENGTH_LEN); + ST_MEMCPY( + &outDevInfo[(*curDevIdx)].sensfRes, + &sensfBuf->SENSF_RES, + outDevInfo[(*curDevIdx)].sensfResLen); + } + + /* Check if this device supports NFC-DEP and signal it (ACTIVITY 1.1 9.3.6.63) */ + *nfcDepFound = rfalNfcfIsNfcDepSupported(&outDevInfo[(*curDevIdx)]); + + (*curDevIdx)++; + } +} + +/* +****************************************************************************** +* GLOBAL FUNCTIONS +****************************************************************************** +*/ + +/*******************************************************************************/ +ReturnCode rfalNfcfPollerInitialize(rfalBitRate bitRate) { + ReturnCode ret; + + if((bitRate != RFAL_BR_212) && (bitRate != RFAL_BR_424)) { + return ERR_PARAM; + } + + EXIT_ON_ERR(ret, rfalSetMode(RFAL_MODE_POLL_NFCF, bitRate, bitRate)); + rfalSetErrorHandling(RFAL_ERRORHANDLING_NFC); + + rfalSetGT(RFAL_GT_NFCF); + rfalSetFDTListen(RFAL_FDT_LISTEN_NFCF_POLLER); + rfalSetFDTPoll(RFAL_FDT_POLL_NFCF_POLLER); + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcfPollerPoll( + rfalFeliCaPollSlots slots, + uint16_t sysCode, + uint8_t reqCode, + rfalFeliCaPollRes* cardList, + uint8_t* devCnt, + uint8_t* collisions) { + return rfalFeliCaPoll( + slots, sysCode, reqCode, cardList, rfalNfcfSlots2CardNum(slots), devCnt, collisions); +} + +/*******************************************************************************/ +ReturnCode rfalNfcfPollerCheckPresence(void) { + gRfalNfcfGreedyF.pollFound = 0; + gRfalNfcfGreedyF.pollCollision = 0; + + /* ACTIVITY 1.0 & 1.1 - 9.2.3.17 SENSF_REQ must be with number of slots equal to 4 + * SC must be 0xFFFF + * RC must be 0x00 (No system code info required) */ + return rfalFeliCaPoll( + RFAL_FELICA_4_SLOTS, + RFAL_NFCF_SYSTEMCODE, + RFAL_FELICA_POLL_RC_NO_REQUEST, + gRfalNfcfGreedyF.POLL_F, + rfalNfcfSlots2CardNum(RFAL_FELICA_4_SLOTS), + &gRfalNfcfGreedyF.pollFound, + &gRfalNfcfGreedyF.pollCollision); +} + +/*******************************************************************************/ +ReturnCode rfalNfcfPollerCollisionResolution( + rfalComplianceMode compMode, + uint8_t devLimit, + rfalNfcfListenDevice* nfcfDevList, + uint8_t* devCnt) { + ReturnCode ret; + bool nfcDepFound; + + if((nfcfDevList == NULL) || (devCnt == NULL)) { + return ERR_PARAM; + } + + *devCnt = 0; + nfcDepFound = false; + + /*******************************************************************************************/ + /* ACTIVITY 1.0 - 9.3.6.3 Copy valid SENSF_RES in GRE_POLL_F into GRE_SENSF_RES */ + /* ACTIVITY 1.0 - 9.3.6.6 The NFC Forum Device MUST remove all entries from GRE_SENSF_RES[]*/ + /* ACTIVITY 1.1 - 9.3.63.59 Populate GRE_SENSF_RES with data from GRE_POLL_F */ + /* */ + /* CON_DEVICES_LIMIT = 0 Just check if devices from Tech Detection exceeds -> always true */ + /* Allow the number of slots open on Technology Detection */ + /*******************************************************************************************/ + rfalNfcfComputeValidSENF( + nfcfDevList, + devCnt, + ((devLimit == 0U) ? rfalNfcfSlots2CardNum(RFAL_FELICA_4_SLOTS) : devLimit), + false, + &nfcDepFound); + + /*******************************************************************************/ + /* ACTIVITY 1.0 - 9.3.6.4 */ + /* ACTIVITY 1.1 - 9.3.63.60 Check if devices found are lower than the limit */ + /* and send a SENSF_REQ if so */ + /*******************************************************************************/ + if(*devCnt < devLimit) { + /* ACTIVITY 1.0 - 9.3.6.5 Copy valid SENSF_RES and then to remove it + * ACTIVITY 1.1 - 9.3.6.65 Copy and filter duplicates + * For now, due to some devices keep generating different nfcid2, we use 1.0 + * Phones detected: Samsung Galaxy Nexus,Samsung Galaxy S3,Samsung Nexus S */ + *devCnt = 0; + + ret = rfalNfcfPollerPoll( + RFAL_FELICA_16_SLOTS, + RFAL_NFCF_SYSTEMCODE, + RFAL_FELICA_POLL_RC_NO_REQUEST, + gRfalNfcfGreedyF.POLL_F, + &gRfalNfcfGreedyF.pollFound, + &gRfalNfcfGreedyF.pollCollision); + if(ret == ERR_NONE) { + rfalNfcfComputeValidSENF(nfcfDevList, devCnt, devLimit, false, &nfcDepFound); + } + + /*******************************************************************************/ + /* ACTIVITY 1.1 - 9.3.6.63 Check if any device supports NFC DEP */ + /*******************************************************************************/ + if(nfcDepFound && (compMode == RFAL_COMPLIANCE_MODE_NFC)) { + ret = rfalNfcfPollerPoll( + RFAL_FELICA_16_SLOTS, + RFAL_NFCF_SYSTEMCODE, + RFAL_FELICA_POLL_RC_SYSTEM_CODE, + gRfalNfcfGreedyF.POLL_F, + &gRfalNfcfGreedyF.pollFound, + &gRfalNfcfGreedyF.pollCollision); + if(ret == ERR_NONE) { + rfalNfcfComputeValidSENF(nfcfDevList, devCnt, devLimit, true, &nfcDepFound); + } + } + } + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcfPollerCheck( + const uint8_t* nfcid2, + const rfalNfcfServBlockListParam* servBlock, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvdLen) { + uint8_t txBuf[RFAL_NFCF_CHECK_REQ_MAX_LEN]; + uint8_t msgIt; + uint8_t i; + ReturnCode ret; + const uint8_t* checkRes; + + /* Check parameters */ + if((nfcid2 == NULL) || (rxBuf == NULL) || (servBlock == NULL) || (servBlock->numBlock == 0U) || + (servBlock->numBlock > RFAL_NFCF_CHECK_REQ_MAX_BLOCK) || (servBlock->numServ == 0U) || + (servBlock->numServ > RFAL_NFCF_CHECK_REQ_MAX_SERV) || + (rxBufLen < (RFAL_NFCF_LENGTH_LEN + RFAL_NFCF_CHECK_RES_MIN_LEN))) { + return ERR_PARAM; + } + + msgIt = 0; + + /*******************************************************************************/ + /* Compose CHECK command/request */ + + txBuf[msgIt++] = RFAL_NFCF_CMD_READ_WITHOUT_ENCRYPTION; /* Command Code */ + + ST_MEMCPY(&txBuf[msgIt], nfcid2, RFAL_NFCF_NFCID2_LEN); /* NFCID2 */ + msgIt += RFAL_NFCF_NFCID2_LEN; + + txBuf[msgIt++] = servBlock->numServ; /* NoS */ + for(i = 0; i < servBlock->numServ; i++) { + txBuf[msgIt++] = (uint8_t)((servBlock->servList[i] >> 0U) & 0xFFU); /* Service Code */ + txBuf[msgIt++] = (uint8_t)((servBlock->servList[i] >> 8U) & 0xFFU); + } + + txBuf[msgIt++] = servBlock->numBlock; /* NoB */ + for(i = 0; i < servBlock->numBlock; i++) { + txBuf[msgIt++] = + servBlock->blockList[i].conf; /* Block list element conf (Flag|Access|Service) */ + if((servBlock->blockList[i].conf & 0x80U) != + 0U) /* Check if 2 or 3 byte block list element */ + { + txBuf[msgIt++] = + (uint8_t)(servBlock->blockList[i].blockNum & 0xFFU); /* 1byte Block Num */ + } else { + txBuf[msgIt++] = + (uint8_t)((servBlock->blockList[i].blockNum >> 0U) & 0xFFU); /* 2byte Block Num */ + txBuf[msgIt++] = (uint8_t)((servBlock->blockList[i].blockNum >> 8U) & 0xFFU); + } + } + + /*******************************************************************************/ + /* Transceive CHECK command/request */ + ret = rfalTransceiveBlockingTxRx( + txBuf, + msgIt, + rxBuf, + rxBufLen, + rcvdLen, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_NFCF_MRT_CHECK_UPDATE); + + if(ret == ERR_NONE) { + /* Skip LEN byte */ + checkRes = (rxBuf + RFAL_NFCF_LENGTH_LEN); + + /* Check response length */ + if(*rcvdLen < (RFAL_NFCF_LENGTH_LEN + RFAL_NFCF_CHECKUPDATE_RES_ST2_POS)) { + ret = ERR_PROTO; + } + /* Check for a valid response */ + else if( + (checkRes[RFAL_NFCF_CMD_POS] != (uint8_t)RFAL_NFCF_CMD_READ_WITHOUT_ENCRYPTION_RES) || + (checkRes[RFAL_NFCF_CHECKUPDATE_RES_ST1_POS] != RFAL_NFCF_STATUS_FLAG_SUCCESS) || + (checkRes[RFAL_NFCF_CHECKUPDATE_RES_ST2_POS] != RFAL_NFCF_STATUS_FLAG_SUCCESS)) { + ret = ERR_REQUEST; + } + /* CHECK succesfull, remove header */ + else { + (*rcvdLen) -= (RFAL_NFCF_LENGTH_LEN + RFAL_NFCF_CHECKUPDATE_RES_NOB_POS); + + if(*rcvdLen > 0U) { + ST_MEMMOVE(rxBuf, &checkRes[RFAL_NFCF_CHECKUPDATE_RES_NOB_POS], (*rcvdLen)); + } + } + } + + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalNfcfPollerUpdate( + const uint8_t* nfcid2, + const rfalNfcfServBlockListParam* servBlock, + uint8_t* txBuf, + uint16_t txBufLen, + const uint8_t* blockData, + uint8_t* rxBuf, + uint16_t rxBufLen) { + uint8_t i; + uint16_t msgIt; + uint16_t rcvdLen; + uint16_t auxLen; + const uint8_t* updateRes; + ReturnCode ret; + + /* Check parameters */ + if((nfcid2 == NULL) || (rxBuf == NULL) || (servBlock == NULL) || (txBuf == NULL) || + (servBlock->numBlock == 0U) || (servBlock->numBlock > RFAL_NFCF_UPDATE_REQ_MAX_BLOCK) || + (servBlock->numServ == 0U) || (servBlock->numServ > RFAL_NFCF_UPDATE_REQ_MAX_SERV) || + (rxBufLen < (RFAL_NFCF_LENGTH_LEN + RFAL_NFCF_UPDATE_RES_MIN_LEN))) { + return ERR_PARAM; + } + + /* Calculate required txBuffer lenth */ + auxLen = (uint16_t)(RFAL_NFCF_CMD_LEN + RFAL_NFCF_NFCID2_LEN + + (servBlock->numServ * sizeof(rfalNfcfServ)) + + (servBlock->numBlock * sizeof(rfalNfcfBlockListElem)) + + (uint16_t)((uint16_t)servBlock->numBlock * RFAL_NFCF_BLOCK_LEN)); + + /* Check whether the provided buffer is sufficient for this request */ + if(txBufLen < auxLen) { + return ERR_PARAM; + } + + msgIt = 0; + + /*******************************************************************************/ + /* Compose UPDATE command/request */ + + txBuf[msgIt++] = RFAL_NFCF_CMD_WRITE_WITHOUT_ENCRYPTION; /* Command Code */ + + ST_MEMCPY(&txBuf[msgIt], nfcid2, RFAL_NFCF_NFCID2_LEN); /* NFCID2 */ + msgIt += RFAL_NFCF_NFCID2_LEN; + + txBuf[msgIt++] = servBlock->numServ; /* NoS */ + for(i = 0; i < servBlock->numServ; i++) { + txBuf[msgIt++] = (uint8_t)((servBlock->servList[i] >> 0U) & 0xFFU); /* Service Code */ + txBuf[msgIt++] = (uint8_t)((servBlock->servList[i] >> 8U) & 0xFFU); + } + + txBuf[msgIt++] = servBlock->numBlock; /* NoB */ + for(i = 0; i < servBlock->numBlock; i++) { + txBuf[msgIt++] = + servBlock->blockList[i].conf; /* Block list element conf (Flag|Access|Service) */ + if((servBlock->blockList[i].conf & 0x80U) != + 0U) /* Check if 2 or 3 byte block list element */ + { + txBuf[msgIt++] = + (uint8_t)(servBlock->blockList[i].blockNum & 0xFFU); /* 1byte Block Num */ + } else { + txBuf[msgIt++] = + (uint8_t)((servBlock->blockList[i].blockNum >> 0U) & 0xFFU); /* 2byte Block Num */ + txBuf[msgIt++] = (uint8_t)((servBlock->blockList[i].blockNum >> 8U) & 0xFFU); + } + } + + auxLen = ((uint16_t)servBlock->numBlock * RFAL_NFCF_BLOCK_LEN); + ST_MEMCPY(&txBuf[msgIt], blockData, auxLen); /* Block Data */ + msgIt += auxLen; + + /*******************************************************************************/ + /* Transceive UPDATE command/request */ + ret = rfalTransceiveBlockingTxRx( + txBuf, + msgIt, + rxBuf, + rxBufLen, + &rcvdLen, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_NFCF_MRT_CHECK_UPDATE); + + if(ret == ERR_NONE) { + /* Skip LEN byte */ + updateRes = (rxBuf + RFAL_NFCF_LENGTH_LEN); + + /* Check response length */ + if(rcvdLen < (RFAL_NFCF_LENGTH_LEN + RFAL_NFCF_CHECKUPDATE_RES_ST2_POS)) { + ret = ERR_PROTO; + } + /* Check for a valid response */ + else if( + (updateRes[RFAL_NFCF_CMD_POS] != + (uint8_t)RFAL_NFCF_CMD_WRITE_WITHOUT_ENCRYPTION_RES) || + (updateRes[RFAL_NFCF_CHECKUPDATE_RES_ST1_POS] != RFAL_NFCF_STATUS_FLAG_SUCCESS) || + (updateRes[RFAL_NFCF_CHECKUPDATE_RES_ST2_POS] != RFAL_NFCF_STATUS_FLAG_SUCCESS)) { + ret = ERR_REQUEST; + } else { + /* MISRA 15.7 - Empty else */ + } + } + + return ret; +} + +/*******************************************************************************/ +bool rfalNfcfListenerIsT3TReq(const uint8_t* buf, uint16_t bufLen, uint8_t* nfcid2) { + /* Check cmd byte */ + switch(*buf) { + case RFAL_NFCF_CMD_READ_WITHOUT_ENCRYPTION: + if(bufLen < RFAL_NFCF_READ_WO_ENCRYPTION_MIN_LEN) { + return false; + } + break; + + case RFAL_NFCF_CMD_WRITE_WITHOUT_ENCRYPTION: + if(bufLen < RFAL_NFCF_WRITE_WO_ENCRYPTION_MIN_LEN) { + return false; + } + break; + + default: + return false; + } + + /* Output NFID2 if requested */ + if(nfcid2 != NULL) { + ST_MEMCPY(nfcid2, &buf[RFAL_NFCF_CMD_LEN], RFAL_NFCF_NFCID2_LEN); + } + + return true; +} + +#endif /* RFAL_FEATURE_NFCF */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_nfcv.c b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_nfcv.c new file mode 100644 index 00000000000..25ec00ca388 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_nfcv.c @@ -0,0 +1,1059 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_nfcv.c + * + * \author Gustavo Patricio + * + * \brief Implementation of NFC-V Poller (ISO15693) device + * + * The definitions and helpers methods provided by this module are + * aligned with NFC-V (ISO15693) + * + * The definitions and helpers methods provided by this module + * are aligned with NFC-V Digital 2.1 + * + */ + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "../include/rfal_nfcv.h" +#include "../utils.h" + +/* + ****************************************************************************** + * ENABLE SWITCH + ****************************************************************************** + */ + +#ifndef RFAL_FEATURE_NFCV +#define RFAL_FEATURE_NFCV false /* NFC-V module configuration missing. Disabled by default */ +#endif + +#if RFAL_FEATURE_NFCV + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ + +#define RFAL_NFCV_INV_REQ_FLAG \ + 0x06U /*!< INVENTORY_REQ INV_FLAG Digital 2.1 9.6.1 */ +#define RFAL_NFCV_MASKVAL_MAX_LEN \ + 8U /*!< Mask value max length: 64 bits (UID length) */ +#define RFAL_NFCV_MASKVAL_MAX_1SLOT_LEN \ + 64U /*!< Mask value max length in 1 Slot mode in bits Digital 2.1 9.6.1.6 */ +#define RFAL_NFCV_MASKVAL_MAX_16SLOT_LEN \ + 60U /*!< Mask value max length in 16 Slot mode in bits Digital 2.1 9.6.1.6 */ +#define RFAL_NFCV_MAX_SLOTS \ + 16U /*!< NFC-V max number of Slots */ +#define RFAL_NFCV_INV_REQ_HEADER_LEN \ + 3U /*!< INVENTORY_REQ header length (INV_FLAG, CMD, MASK_LEN) */ +#define RFAL_NFCV_INV_RES_LEN \ + 10U /*!< INVENTORY_RES length */ +#define RFAL_NFCV_WR_MUL_REQ_HEADER_LEN \ + 4U /*!< Write Multiple header length (INV_FLAG, CMD, [UID], BNo, Bno) */ + +#define RFAL_NFCV_CMD_LEN \ + 1U /*!< Commandbyte length */ +#define RFAL_NFCV_FLAG_POS \ + 0U /*!< Flag byte position */ +#define RFAL_NFCV_FLAG_LEN \ + 1U /*!< Flag byte length */ +#define RFAL_NFCV_DATASTART_POS \ + 1U /*!< Position of start of data */ +#define RFAL_NFCV_DSFI_LEN \ + 1U /*!< DSFID length */ +#define RFAL_NFCV_SLPREQ_REQ_FLAG \ + 0x22U /*!< SLPV_REQ request flags Digital 2.0 (Candidate) 9.7.1.1 */ +#define RFAL_NFCV_RES_FLAG_NOERROR \ + 0x00U /*!< RES_FLAG indicating no error (checked during activation) */ + +#define RFAL_NFCV_MAX_COLL_SUPPORTED \ + 16U /*!< Maximum number of collisions supported by the Anticollision loop */ + +#define RFAL_NFCV_FDT_MAX \ + rfalConvMsTo1fc(20) /*!< Maximum Wait time FDTV,EOF and MAX2 Digital 2.1 B.5*/ +#define RFAL_NFCV_FDT_MAX1 \ + 4394U /*!< Read alike command FWT FDTV,LISTEN,MAX1 Digital 2.0 B.5 */ + +/*! Time from special frame to EOF + * ISO15693 2009 10.4.2 : 20ms + * NFC Forum defines Digital 2.0 9.7.4 : FDTV,EOF = [10 ; 20]ms + */ +#define RFAL_NFCV_FDT_EOF 20U + +/*! Time between slots - ISO 15693 defines t3min depending on modulation depth and data rate. + * With only high-bitrate supported, AM modulation and a length of 12 bytes (96bits) for INV_RES we get: + * - ISO t3min = 96/26 ms + 300us = 4 ms + * - NFC Forum defines FDTV,INVENT_NORES = (4394 + 2048)/fc. Digital 2.0 B.5*/ +#define RFAL_NFCV_FDT_V_INVENT_NORES 4U + +/* + ****************************************************************************** + * GLOBAL MACROS + ****************************************************************************** + */ + +/*! Checks if a valid INVENTORY_RES is valid Digital 2.2 9.6.2.1 & 9.6.2.3 */ +#define rfalNfcvCheckInvRes(f, l) \ + (((l) == rfalConvBytesToBits(RFAL_NFCV_INV_RES_LEN + RFAL_NFCV_CRC_LEN)) && \ + ((f) == RFAL_NFCV_RES_FLAG_NOERROR)) + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + +/*! NFC-V INVENTORY_REQ format Digital 2.0 9.6.1 */ +typedef struct { + uint8_t INV_FLAG; /*!< Inventory Flags */ + uint8_t CMD; /*!< Command code: 01h */ + uint8_t MASK_LEN; /*!< Mask Value Length */ + uint8_t MASK_VALUE[RFAL_NFCV_MASKVAL_MAX_LEN]; /*!< Mask Value */ +} rfalNfcvInventoryReq; + +/*! NFC-V SLP_REQ format Digital 2.0 (Candidate) 9.7.1 */ +typedef struct { + uint8_t REQ_FLAG; /*!< Request Flags */ + uint8_t CMD; /*!< Command code: 02h */ + uint8_t UID[RFAL_NFCV_UID_LEN]; /*!< Mask Value */ +} rfalNfcvSlpvReq; + +/*! Container for a collision found during Anticollision loop */ +typedef struct { + uint8_t maskLen; + uint8_t maskVal[RFAL_NFCV_MASKVAL_MAX_LEN]; +} rfalNfcvCollision; + +/* +****************************************************************************** +* LOCAL FUNCTION PROTOTYPES +****************************************************************************** +*/ +static ReturnCode rfalNfcvParseError(uint8_t err); + +/* +****************************************************************************** +* LOCAL VARIABLES +****************************************************************************** +*/ + +/* +****************************************************************************** +* LOCAL FUNCTIONS +****************************************************************************** +*/ + +/*******************************************************************************/ +static ReturnCode rfalNfcvParseError(uint8_t err) { + switch(err) { + case RFAL_NFCV_ERROR_CMD_NOT_SUPPORTED: + case RFAL_NFCV_ERROR_OPTION_NOT_SUPPORTED: + return ERR_NOTSUPP; + + case RFAL_NFCV_ERROR_CMD_NOT_RECOGNIZED: + return ERR_PROTO; + + case RFAL_NFCV_ERROR_WRITE_FAILED: + return ERR_WRITE; + + default: + return ERR_REQUEST; + } +} + +/* +****************************************************************************** +* GLOBAL FUNCTIONS +****************************************************************************** +*/ + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerInitialize(void) { + ReturnCode ret; + + EXIT_ON_ERR(ret, rfalSetMode(RFAL_MODE_POLL_NFCV, RFAL_BR_26p48, RFAL_BR_26p48)); + rfalSetErrorHandling(RFAL_ERRORHANDLING_NFC); + + rfalSetGT(RFAL_GT_NFCV); + rfalSetFDTListen(RFAL_FDT_LISTEN_NFCV_POLLER); + rfalSetFDTPoll(RFAL_FDT_POLL_NFCV_POLLER); + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerCheckPresence(rfalNfcvInventoryRes* invRes) { + ReturnCode ret; + + /* INVENTORY_REQ with 1 slot and no Mask Activity 2.0 (Candidate) 9.2.3.32 */ + ret = rfalNfcvPollerInventory(RFAL_NFCV_NUM_SLOTS_1, 0, NULL, invRes, NULL); + + if((ret == ERR_RF_COLLISION) || (ret == ERR_CRC) || (ret == ERR_FRAMING) || + (ret == ERR_PROTO)) { + ret = ERR_NONE; + } + + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerInventory( + rfalNfcvNumSlots nSlots, + uint8_t maskLen, + const uint8_t* maskVal, + rfalNfcvInventoryRes* invRes, + uint16_t* rcvdLen) { + ReturnCode ret; + rfalNfcvInventoryReq invReq; + uint16_t rxLen; + + if(((maskVal == NULL) && (maskLen != 0U)) || (invRes == NULL)) { + return ERR_PARAM; + } + + invReq.INV_FLAG = (RFAL_NFCV_INV_REQ_FLAG | (uint8_t)nSlots); + invReq.CMD = RFAL_NFCV_CMD_INVENTORY; + invReq.MASK_LEN = (uint8_t)MIN( + maskLen, + ((nSlots == RFAL_NFCV_NUM_SLOTS_1) ? + RFAL_NFCV_MASKVAL_MAX_1SLOT_LEN : + RFAL_NFCV_MASKVAL_MAX_16SLOT_LEN)); /* Digital 2.0 9.6.1.6 */ + + if((rfalConvBitsToBytes(invReq.MASK_LEN) > 0U) && (maskVal != NULL)) /* MISRA 21.18 & 1.3 */ + { + ST_MEMCPY(invReq.MASK_VALUE, maskVal, rfalConvBitsToBytes(invReq.MASK_LEN)); + } + + ret = rfalISO15693TransceiveAnticollisionFrame( + (uint8_t*)&invReq, + (uint8_t)(RFAL_NFCV_INV_REQ_HEADER_LEN + rfalConvBitsToBytes(invReq.MASK_LEN)), + (uint8_t*)invRes, + sizeof(rfalNfcvInventoryRes), + &rxLen); + + /* Check for optional output parameter */ + if(rcvdLen != NULL) { + *rcvdLen = rxLen; + } + + if(ret == ERR_NONE) { + /* Check for valid INVENTORY_RES Digital 2.2 9.6.2.1 & 9.6.2.3 */ + if(!rfalNfcvCheckInvRes(invRes->RES_FLAG, rxLen)) { + return ERR_PROTO; + } + } + + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerCollisionResolution( + rfalComplianceMode compMode, + uint8_t devLimit, + rfalNfcvListenDevice* nfcvDevList, + uint8_t* devCnt) { + ReturnCode ret; + uint8_t slotNum; + uint16_t rcvdLen; + uint8_t colIt; + uint8_t colCnt; + uint8_t colPos; + bool colPending; + rfalNfcvCollision colFound[RFAL_NFCV_MAX_COLL_SUPPORTED]; + + if((nfcvDevList == NULL) || (devCnt == NULL)) { + return ERR_PARAM; + } + + /* Initialize parameters */ + *devCnt = 0; + colIt = 0; + colCnt = 0; + colPending = false; + ST_MEMSET(colFound, 0x00, (sizeof(rfalNfcvCollision) * RFAL_NFCV_MAX_COLL_SUPPORTED)); + + if(devLimit > 0U) /* MISRA 21.18 */ + { + ST_MEMSET(nfcvDevList, 0x00, (sizeof(rfalNfcvListenDevice) * devLimit)); + } + + NO_WARNING( + colPending); /* colPending is not exposed externally, in future it might become exposed/ouput parameter */ + + if(compMode == RFAL_COMPLIANCE_MODE_NFC) { + /* Send INVENTORY_REQ with one slot Activity 2.1 9.3.7.1 (Symbol 0) */ + ret = rfalNfcvPollerInventory(RFAL_NFCV_NUM_SLOTS_1, 0, NULL, &nfcvDevList->InvRes, NULL); + + if(ret == ERR_TIMEOUT) /* Exit if no device found Activity 2.1 9.3.7.2 (Symbol 1) */ + { + return ERR_NONE; + } + if(ret == + ERR_NONE) /* Device found without transmission error/collision Activity 2.1 9.3.7.3 (Symbol 2) */ + { + (*devCnt)++; + return ERR_NONE; + } + + /* A Collision has been identified Activity 2.1 9.3.7.4 (Symbol 3) */ + colPending = true; + colCnt = 1; + + /* Check if the Collision Resolution is set to perform only Collision detection Activity 2.1 9.3.7.5 (Symbol 4)*/ + if(devLimit == 0U) { + return ERR_RF_COLLISION; + } + + platformDelay(RFAL_NFCV_FDT_V_INVENT_NORES); + + /*******************************************************************************/ + /* Collisions pending, Anticollision loop must be executed */ + /*******************************************************************************/ + } else { + /* Advance to 16 slots below without mask. Will give a good chance to identify multiple cards */ + colPending = true; + colCnt = 1; + } + + /* Execute until all collisions are resolved Activity 2.1 9.3.7.18 (Symbol 17) */ + do { + /* Activity 2.1 9.3.7.7 (Symbol 6 / 7) */ + colPending = false; + slotNum = 0; + + do { + if(slotNum == 0U) { + /* Send INVENTORY_REQ with 16 slots Activity 2.1 9.3.7.9 (Symbol 8) */ + ret = rfalNfcvPollerInventory( + RFAL_NFCV_NUM_SLOTS_16, + colFound[colIt].maskLen, + colFound[colIt].maskVal, + &nfcvDevList[(*devCnt)].InvRes, + &rcvdLen); + } else { + ret = rfalISO15693TransceiveEOFAnticollision( + (uint8_t*)&nfcvDevList[(*devCnt)].InvRes, + sizeof(rfalNfcvInventoryRes), + &rcvdLen); + } + slotNum++; + + /*******************************************************************************/ + if(ret != ERR_TIMEOUT) { + if(rcvdLen < + rfalConvBytesToBits( + RFAL_NFCV_INV_RES_LEN + + RFAL_NFCV_CRC_LEN)) { /* If only a partial frame was received make sure the FDT_V_INVENT_NORES is fulfilled */ + platformDelay(RFAL_NFCV_FDT_V_INVENT_NORES); + } + + /* Check if response is a correct frame (no TxRx error) Activity 2.1 9.3.7.11 (Symbol 10)*/ + if((ret == ERR_NONE) || (ret == ERR_PROTO)) { + /* Check if the device found is already on the list and its response is a valid INVENTORY_RES */ + if(rfalNfcvCheckInvRes(nfcvDevList[(*devCnt)].InvRes.RES_FLAG, rcvdLen)) { + /* Activity 2.1 9.3.7.12 (Symbol 11) */ + (*devCnt)++; + } + } else /* Treat everything else as collision */ + { + /* Activity 2.1 9.3.7.17 (Symbol 16) */ + colPending = true; + + /*******************************************************************************/ + /* Ensure that this collision still fits on the container */ + if(colCnt < RFAL_NFCV_MAX_COLL_SUPPORTED) { + /* Store this collision on the container to be resolved later */ + /* Activity 2.1 9.3.7.17 (Symbol 16): add the collision information + * (MASK_VAL + SN) to the list containing the collision information */ + ST_MEMCPY( + colFound[colCnt].maskVal, colFound[colIt].maskVal, RFAL_NFCV_UID_LEN); + colPos = colFound[colIt].maskLen; + colFound[colCnt].maskVal[(colPos / RFAL_BITS_IN_BYTE)] &= + (uint8_t)((1U << (colPos % RFAL_BITS_IN_BYTE)) - 1U); + colFound[colCnt].maskVal[(colPos / RFAL_BITS_IN_BYTE)] |= + (uint8_t)((slotNum - 1U) << (colPos % RFAL_BITS_IN_BYTE)); + colFound[colCnt].maskVal[((colPos / RFAL_BITS_IN_BYTE) + 1U)] = + (uint8_t)((slotNum - 1U) >> + (RFAL_BITS_IN_BYTE - (colPos % RFAL_BITS_IN_BYTE))); + + colFound[colCnt].maskLen = (colFound[colIt].maskLen + 4U); + + colCnt++; + } + } + } else { + /* Timeout */ + platformDelay(RFAL_NFCV_FDT_V_INVENT_NORES); + } + + /* Check if devices found have reached device limit Activity 2.1 9.3.7.13 (Symbol 12) */ + if(*devCnt >= devLimit) { + return ERR_NONE; + } + + } while(slotNum < RFAL_NFCV_MAX_SLOTS); /* Slot loop */ + colIt++; + } while(colIt < colCnt); /* Collisions found loop */ + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerSleepCollisionResolution( + uint8_t devLimit, + rfalNfcvListenDevice* nfcvDevList, + uint8_t* devCnt) { + uint8_t tmpDevCnt; + ReturnCode ret; + uint8_t i; + + if((nfcvDevList == NULL) || (devCnt == NULL)) { + return ERR_PARAM; + } + + *devCnt = 0; + + do { + tmpDevCnt = 0; + ret = rfalNfcvPollerCollisionResolution( + RFAL_COMPLIANCE_MODE_ISO, (devLimit - *devCnt), &nfcvDevList[*devCnt], &tmpDevCnt); + + for(i = *devCnt; i < (*devCnt + tmpDevCnt); i++) { + rfalNfcvPollerSleep(0x00, nfcvDevList[i].InvRes.UID); + nfcvDevList[i].isSleep = true; + } + *devCnt += tmpDevCnt; + } while((ret == ERR_NONE) && (tmpDevCnt > 0U) && (*devCnt < devLimit)); + + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerSleep(uint8_t flags, const uint8_t* uid) { + ReturnCode ret; + rfalNfcvSlpvReq slpReq; + uint8_t rxBuf; /* dummy buffer, just to perform Rx */ + + if(uid == NULL) { + return ERR_PARAM; + } + + /* Compute SLPV_REQ */ + slpReq.REQ_FLAG = + (flags | + (uint8_t) + RFAL_NFCV_REQ_FLAG_ADDRESS); /* Should be with UID according Digital 2.0 (Candidate) 9.7.1.1 */ + slpReq.CMD = RFAL_NFCV_CMD_SLPV; + ST_MEMCPY(slpReq.UID, uid, RFAL_NFCV_UID_LEN); + + /* NFC Forum device SHALL wait at least FDTVpp to consider the SLPV acknowledged (FDTVpp = FDTVpoll) Digital 2.0 (Candidate) 9.7 9.8.2 */ + ret = rfalTransceiveBlockingTxRx( + (uint8_t*)&slpReq, + sizeof(rfalNfcvSlpvReq), + &rxBuf, + sizeof(rxBuf), + NULL, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_NFCV_FDT_MAX1); + if(ret != ERR_TIMEOUT) { + return ret; + } + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerSelect(uint8_t flags, const uint8_t* uid) { + uint16_t rcvLen; + rfalNfcvGenericRes res; + + if(uid == NULL) { + return ERR_PARAM; + } + + return rfalNfcvPollerTransceiveReq( + RFAL_NFCV_CMD_SELECT, + flags, + RFAL_NFCV_PARAM_SKIP, + uid, + NULL, + 0U, + (uint8_t*)&res, + sizeof(rfalNfcvGenericRes), + &rcvLen); +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerReadSingleBlock( + uint8_t flags, + const uint8_t* uid, + uint8_t blockNum, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvLen) { + uint8_t bn; + + bn = blockNum; + + return rfalNfcvPollerTransceiveReq( + RFAL_NFCV_CMD_READ_SINGLE_BLOCK, + flags, + RFAL_NFCV_PARAM_SKIP, + uid, + &bn, + sizeof(uint8_t), + rxBuf, + rxBufLen, + rcvLen); +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerWriteSingleBlock( + uint8_t flags, + const uint8_t* uid, + uint8_t blockNum, + const uint8_t* wrData, + uint8_t blockLen) { + uint8_t data[(RFAL_NFCV_BLOCKNUM_LEN + RFAL_NFCV_MAX_BLOCK_LEN)]; + uint8_t dataLen; + uint16_t rcvLen; + rfalNfcvGenericRes res; + + /* Check for valid parameters */ + if((blockLen == 0U) || (blockLen > (uint8_t)RFAL_NFCV_MAX_BLOCK_LEN) || (wrData == NULL)) { + return ERR_PARAM; + } + + dataLen = 0U; + + /* Compute Request Data */ + data[dataLen++] = blockNum; /* Set Block Number (8 bits) */ + ST_MEMCPY(&data[dataLen], wrData, blockLen); /* Append Block data to write */ + dataLen += blockLen; + + return rfalNfcvPollerTransceiveReq( + RFAL_NFCV_CMD_WRITE_SINGLE_BLOCK, + flags, + RFAL_NFCV_PARAM_SKIP, + uid, + data, + dataLen, + (uint8_t*)&res, + sizeof(rfalNfcvGenericRes), + &rcvLen); +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerLockBlock(uint8_t flags, const uint8_t* uid, uint8_t blockNum) { + uint16_t rcvLen; + rfalNfcvGenericRes res; + uint8_t bn; + + bn = blockNum; + + return rfalNfcvPollerTransceiveReq( + RFAL_NFCV_CMD_LOCK_BLOCK, + flags, + RFAL_NFCV_PARAM_SKIP, + uid, + &bn, + sizeof(uint8_t), + (uint8_t*)&res, + sizeof(rfalNfcvGenericRes), + &rcvLen); +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerReadMultipleBlocks( + uint8_t flags, + const uint8_t* uid, + uint8_t firstBlockNum, + uint8_t numOfBlocks, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvLen) { + uint8_t data[(RFAL_NFCV_BLOCKNUM_LEN + RFAL_NFCV_BLOCKNUM_LEN)]; + uint8_t dataLen; + + dataLen = 0U; + + /* Compute Request Data */ + data[dataLen++] = firstBlockNum; /* Set first Block Number */ + data[dataLen++] = numOfBlocks; /* Set number of blocks to read */ + + return rfalNfcvPollerTransceiveReq( + RFAL_NFCV_CMD_READ_MULTIPLE_BLOCKS, + flags, + RFAL_NFCV_PARAM_SKIP, + uid, + data, + dataLen, + rxBuf, + rxBufLen, + rcvLen); +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerWriteMultipleBlocks( + uint8_t flags, + const uint8_t* uid, + uint8_t firstBlockNum, + uint8_t numOfBlocks, + uint8_t* txBuf, + uint16_t txBufLen, + uint8_t blockLen, + const uint8_t* wrData, + uint16_t wrDataLen) { + ReturnCode ret; + uint16_t rcvLen; + uint16_t reqLen; + rfalNfcvGenericRes res; + uint16_t msgIt; + + /* Calculate required buffer length */ + reqLen = (uint16_t)((uid != NULL) ? + (RFAL_NFCV_WR_MUL_REQ_HEADER_LEN + RFAL_NFCV_UID_LEN + wrDataLen) : + (RFAL_NFCV_WR_MUL_REQ_HEADER_LEN + wrDataLen)); + + if((reqLen > txBufLen) || (blockLen > (uint8_t)RFAL_NFCV_MAX_BLOCK_LEN) || + ((((uint16_t)numOfBlocks) * (uint16_t)blockLen) != wrDataLen) || (numOfBlocks == 0U) || + (wrData == NULL)) { + return ERR_PARAM; + } + + msgIt = 0; + + /* Compute Request Command */ + txBuf[msgIt++] = (uint8_t)(flags & (~((uint32_t)RFAL_NFCV_REQ_FLAG_ADDRESS))); + txBuf[msgIt++] = RFAL_NFCV_CMD_WRITE_MULTIPLE_BLOCKS; + + /* Check if Request is to be sent in Addressed mode. Select mode flag shall be set by user */ + if(uid != NULL) { + txBuf[RFAL_NFCV_FLAG_POS] |= (uint8_t)RFAL_NFCV_REQ_FLAG_ADDRESS; + ST_MEMCPY(&txBuf[msgIt], uid, RFAL_NFCV_UID_LEN); + msgIt += (uint8_t)RFAL_NFCV_UID_LEN; + } + + txBuf[msgIt++] = firstBlockNum; + txBuf[msgIt++] = (numOfBlocks - 1U); + + if(wrDataLen > 0U) /* MISRA 21.18 */ + { + ST_MEMCPY(&txBuf[msgIt], wrData, wrDataLen); + msgIt += wrDataLen; + } + + /* Transceive Command */ + ret = rfalTransceiveBlockingTxRx( + txBuf, + msgIt, + (uint8_t*)&res, + sizeof(rfalNfcvGenericRes), + &rcvLen, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_NFCV_FDT_MAX); + + if(ret != ERR_NONE) { + return ret; + } + + /* Check if the response minimum length has been received */ + if(rcvLen < (uint8_t)RFAL_NFCV_FLAG_LEN) { + return ERR_PROTO; + } + + /* Check if an error has been signalled */ + if((res.RES_FLAG & (uint8_t)RFAL_NFCV_RES_FLAG_ERROR) != 0U) { + return rfalNfcvParseError(*res.data); + } + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerExtendedReadSingleBlock( + uint8_t flags, + const uint8_t* uid, + uint16_t blockNum, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvLen) { + uint8_t data[RFAL_NFCV_BLOCKNUM_EXTENDED_LEN]; + uint8_t dataLen; + + dataLen = 0U; + + /* Compute Request Data */ + data[dataLen++] = (uint8_t) + blockNum; /* TS T5T 1.0 BNo is considered as a multi-byte field. TS T5T 1.0 5.1.1.13 multi-byte field follows [DIGITAL]. [DIGITAL] 9.3.1 A multiple byte field is transmitted LSB first. */ + data[dataLen++] = (uint8_t)((blockNum >> 8U) & 0xFFU); + + return rfalNfcvPollerTransceiveReq( + RFAL_NFCV_CMD_EXTENDED_READ_SINGLE_BLOCK, + flags, + RFAL_NFCV_PARAM_SKIP, + uid, + data, + dataLen, + rxBuf, + rxBufLen, + rcvLen); +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerExtendedWriteSingleBlock( + uint8_t flags, + const uint8_t* uid, + uint16_t blockNum, + const uint8_t* wrData, + uint8_t blockLen) { + uint8_t data[(RFAL_NFCV_BLOCKNUM_EXTENDED_LEN + RFAL_NFCV_MAX_BLOCK_LEN)]; + uint8_t dataLen; + uint16_t rcvLen; + rfalNfcvGenericRes res; + + /* Check for valid parameters */ + if((blockLen == 0U) || (blockLen > (uint8_t)RFAL_NFCV_MAX_BLOCK_LEN)) { + return ERR_PARAM; + } + + dataLen = 0U; + + /* Compute Request Data */ + data[dataLen++] = (uint8_t) + blockNum; /* TS T5T 1.0 BNo is considered as a multi-byte field. TS T5T 1.0 5.1.1.13 multi-byte field follows [DIGITAL]. [DIGITAL] 9.3.1 A multiple byte field is transmitted LSB first. */ + data[dataLen++] = (uint8_t)((blockNum >> 8U) & 0xFFU); + ST_MEMCPY(&data[dataLen], wrData, blockLen); /* Append Block data to write */ + dataLen += blockLen; + + return rfalNfcvPollerTransceiveReq( + RFAL_NFCV_CMD_EXTENDED_WRITE_SINGLE_BLOCK, + flags, + RFAL_NFCV_PARAM_SKIP, + uid, + data, + dataLen, + (uint8_t*)&res, + sizeof(rfalNfcvGenericRes), + &rcvLen); +} + +/*******************************************************************************/ +ReturnCode + rfalNfcvPollerExtendedLockSingleBlock(uint8_t flags, const uint8_t* uid, uint16_t blockNum) { + uint8_t data[RFAL_NFCV_BLOCKNUM_EXTENDED_LEN]; + uint8_t dataLen; + uint16_t rcvLen; + rfalNfcvGenericRes res; + + dataLen = 0U; + + /* Compute Request Data */ + data[dataLen++] = (uint8_t) + blockNum; /* TS T5T 1.0 BNo is considered as a multi-byte field. TS T5T 1.0 5.1.1.13 multi-byte field follows [DIGITAL]. [DIGITAL] 9.3.1 A multiple byte field is transmitted LSB first. */ + data[dataLen++] = (uint8_t)((blockNum >> 8U) & 0xFFU); + + return rfalNfcvPollerTransceiveReq( + RFAL_NFCV_CMD_EXTENDED_LOCK_SINGLE_BLOCK, + flags, + RFAL_NFCV_PARAM_SKIP, + uid, + data, + dataLen, + (uint8_t*)&res, + sizeof(rfalNfcvGenericRes), + &rcvLen); +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerExtendedReadMultipleBlocks( + uint8_t flags, + const uint8_t* uid, + uint16_t firstBlockNum, + uint16_t numOfBlocks, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvLen) { + uint8_t data[(RFAL_NFCV_BLOCKNUM_EXTENDED_LEN + RFAL_NFCV_BLOCKNUM_EXTENDED_LEN)]; + uint8_t dataLen; + + dataLen = 0U; + + /* Compute Request Data */ + data[dataLen++] = (uint8_t)((firstBlockNum >> 0U) & 0xFFU); + data[dataLen++] = (uint8_t)((firstBlockNum >> 8U) & 0xFFU); + data[dataLen++] = (uint8_t)((numOfBlocks >> 0U) & 0xFFU); + data[dataLen++] = (uint8_t)((numOfBlocks >> 8U) & 0xFFU); + + return rfalNfcvPollerTransceiveReq( + RFAL_NFCV_CMD_EXTENDED_READ_MULTIPLE_BLOCK, + flags, + RFAL_NFCV_PARAM_SKIP, + uid, + data, + dataLen, + rxBuf, + rxBufLen, + rcvLen); +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerExtendedWriteMultipleBlocks( + uint8_t flags, + const uint8_t* uid, + uint16_t firstBlockNum, + uint16_t numOfBlocks, + uint8_t* txBuf, + uint16_t txBufLen, + uint8_t blockLen, + const uint8_t* wrData, + uint16_t wrDataLen) { + ReturnCode ret; + uint16_t rcvLen; + uint16_t reqLen; + rfalNfcvGenericRes res; + uint16_t msgIt; + uint16_t nBlocks; + + /* Calculate required buffer length */ + reqLen = + ((uid != NULL) ? (RFAL_NFCV_WR_MUL_REQ_HEADER_LEN + RFAL_NFCV_UID_LEN + wrDataLen) : + (RFAL_NFCV_WR_MUL_REQ_HEADER_LEN + wrDataLen)); + + if((reqLen > txBufLen) || (blockLen > (uint8_t)RFAL_NFCV_MAX_BLOCK_LEN) || + (((uint16_t)numOfBlocks * (uint16_t)blockLen) != wrDataLen) || (numOfBlocks == 0U)) { + return ERR_PARAM; + } + + msgIt = 0; + nBlocks = (numOfBlocks - 1U); + + /* Compute Request Command */ + txBuf[msgIt++] = (uint8_t)(flags & (~((uint32_t)RFAL_NFCV_REQ_FLAG_ADDRESS))); + txBuf[msgIt++] = RFAL_NFCV_CMD_EXTENDED_WRITE_MULTIPLE_BLOCK; + + /* Check if Request is to be sent in Addressed mode. Select mode flag shall be set by user */ + if(uid != NULL) { + txBuf[RFAL_NFCV_FLAG_POS] |= (uint8_t)RFAL_NFCV_REQ_FLAG_ADDRESS; + ST_MEMCPY(&txBuf[msgIt], uid, RFAL_NFCV_UID_LEN); + msgIt += (uint8_t)RFAL_NFCV_UID_LEN; + } + + txBuf[msgIt++] = (uint8_t)((firstBlockNum >> 0) & 0xFFU); + txBuf[msgIt++] = (uint8_t)((firstBlockNum >> 8) & 0xFFU); + txBuf[msgIt++] = (uint8_t)((nBlocks >> 0) & 0xFFU); + txBuf[msgIt++] = (uint8_t)((nBlocks >> 8) & 0xFFU); + + if(wrDataLen > 0U) /* MISRA 21.18 */ + { + ST_MEMCPY(&txBuf[msgIt], wrData, wrDataLen); + msgIt += wrDataLen; + } + + /* Transceive Command */ + ret = rfalTransceiveBlockingTxRx( + txBuf, + msgIt, + (uint8_t*)&res, + sizeof(rfalNfcvGenericRes), + &rcvLen, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_NFCV_FDT_MAX); + + if(ret != ERR_NONE) { + return ret; + } + + /* Check if the response minimum length has been received */ + if(rcvLen < (uint8_t)RFAL_NFCV_FLAG_LEN) { + return ERR_PROTO; + } + + /* Check if an error has been signalled */ + if((res.RES_FLAG & (uint8_t)RFAL_NFCV_RES_FLAG_ERROR) != 0U) { + return rfalNfcvParseError(*res.data); + } + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerGetSystemInformation( + uint8_t flags, + const uint8_t* uid, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvLen) { + return rfalNfcvPollerTransceiveReq( + RFAL_NFCV_CMD_GET_SYS_INFO, + flags, + RFAL_NFCV_PARAM_SKIP, + uid, + NULL, + 0U, + rxBuf, + rxBufLen, + rcvLen); +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerExtendedGetSystemInformation( + uint8_t flags, + const uint8_t* uid, + uint8_t requestField, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvLen) { + return rfalNfcvPollerTransceiveReq( + RFAL_NFCV_CMD_EXTENDED_GET_SYS_INFO, + flags, + requestField, + uid, + NULL, + 0U, + rxBuf, + rxBufLen, + rcvLen); +} + +/*******************************************************************************/ +ReturnCode rfalNfcvPollerTransceiveReq( + uint8_t cmd, + uint8_t flags, + uint8_t param, + const uint8_t* uid, + const uint8_t* data, + uint16_t dataLen, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvLen) { + ReturnCode ret; + rfalNfcvGenericReq req; + uint8_t msgIt; + rfalBitRate rxBR; + bool fastMode; + + msgIt = 0; + fastMode = false; + + /* Check for valid parameters */ + if((rxBuf == NULL) || (rcvLen == NULL) || ((dataLen > 0U) && (data == NULL)) || + (dataLen > ((uid != NULL) ? RFAL_NFCV_MAX_GEN_DATA_LEN : + (RFAL_NFCV_MAX_GEN_DATA_LEN - RFAL_NFCV_UID_LEN)))) { + return ERR_PARAM; + } + + /* Check if the command is an ST's Fast command */ + if((cmd == (uint8_t)RFAL_NFCV_CMD_FAST_READ_SINGLE_BLOCK) || + (cmd == (uint8_t)RFAL_NFCV_CMD_FAST_EXTENDED_READ_SINGLE_BLOCK) || + (cmd == (uint8_t)RFAL_NFCV_CMD_FAST_READ_MULTIPLE_BLOCKS) || + (cmd == (uint8_t)RFAL_NFCV_CMD_FAST_EXTENDED_READ_MULTIPLE_BLOCKS) || + (cmd == (uint8_t)RFAL_NFCV_CMD_FAST_WRITE_MESSAGE) || + (cmd == (uint8_t)RFAL_NFCV_CMD_FAST_READ_MESSAGE_LENGTH) || + (cmd == (uint8_t)RFAL_NFCV_CMD_FAST_READ_MESSAGE) || + (cmd == (uint8_t)RFAL_NFCV_CMD_FAST_READ_DYN_CONFIGURATION) || + (cmd == (uint8_t)RFAL_NFCV_CMD_FAST_WRITE_DYN_CONFIGURATION)) { + /* Store current Rx bit rate and move to fast mode */ + rfalGetBitRate(NULL, &rxBR); + rfalSetBitRate(RFAL_BR_KEEP, RFAL_BR_52p97); + + fastMode = true; + } + + /* Compute Request Command */ + req.REQ_FLAG = (uint8_t)(flags & (~((uint32_t)RFAL_NFCV_REQ_FLAG_ADDRESS))); + req.CMD = cmd; + + /* Prepend parameter on ceratin proprietary requests: IC Manuf, Parameters */ + if(param != RFAL_NFCV_PARAM_SKIP) { + req.payload.data[msgIt++] = param; + } + + /* Check if Request is to be sent in Addressed mode. Select mode flag shall be set by user */ + if(uid != NULL) { + req.REQ_FLAG |= (uint8_t)RFAL_NFCV_REQ_FLAG_ADDRESS; + ST_MEMCPY(&req.payload.data[msgIt], uid, RFAL_NFCV_UID_LEN); + msgIt += RFAL_NFCV_UID_LEN; + } + + if(dataLen > 0U) { + ST_MEMCPY(&req.payload.data[msgIt], data, dataLen); + msgIt += (uint8_t)dataLen; + } + + /* Transceive Command */ + ret = rfalTransceiveBlockingTxRx( + (uint8_t*)&req, + (RFAL_NFCV_CMD_LEN + RFAL_NFCV_FLAG_LEN + (uint16_t)msgIt), + rxBuf, + rxBufLen, + rcvLen, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_NFCV_FDT_MAX); + + /* If the Option Flag is set in certain commands an EOF needs to be sent after 20ms to retrieve the VICC response ISO15693-3 2009 10.4.2 & 10.4.3 & 10.4.5 */ + if(((flags & (uint8_t)RFAL_NFCV_REQ_FLAG_OPTION) != 0U) && + ((cmd == (uint8_t)RFAL_NFCV_CMD_WRITE_SINGLE_BLOCK) || + (cmd == (uint8_t)RFAL_NFCV_CMD_WRITE_MULTIPLE_BLOCKS) || + (cmd == (uint8_t)RFAL_NFCV_CMD_LOCK_BLOCK) || + (cmd == (uint8_t)RFAL_NFCV_CMD_EXTENDED_WRITE_SINGLE_BLOCK) || + (cmd == (uint8_t)RFAL_NFCV_CMD_EXTENDED_LOCK_SINGLE_BLOCK) || + (cmd == (uint8_t)RFAL_NFCV_CMD_EXTENDED_WRITE_MULTIPLE_BLOCK))) { + ret = rfalISO15693TransceiveEOF(rxBuf, (uint8_t)rxBufLen, rcvLen); + } + + /* Restore Rx BitRate */ + if(fastMode) { + rfalSetBitRate(RFAL_BR_KEEP, rxBR); + } + + if(ret != ERR_NONE) { + return ret; + } + + /* Check if the response minimum length has been received */ + if((*rcvLen) < (uint8_t)RFAL_NFCV_FLAG_LEN) { + return ERR_PROTO; + } + + /* Check if an error has been signalled */ + if((rxBuf[RFAL_NFCV_FLAG_POS] & (uint8_t)RFAL_NFCV_RES_FLAG_ERROR) != 0U) { + return rfalNfcvParseError(rxBuf[RFAL_NFCV_DATASTART_POS]); + } + + return ERR_NONE; +} + +#endif /* RFAL_FEATURE_NFCV */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_st25tb.c b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_st25tb.c new file mode 100644 index 00000000000..4210ab9989f --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_st25tb.c @@ -0,0 +1,563 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_st25tb.c + * + * \author Gustavo Patricio + * + * \brief Implementation of ST25TB interface + * + */ + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "../include/rfal_st25tb.h" +#include "../utils.h" + +/* + ****************************************************************************** + * ENABLE SWITCH + ****************************************************************************** + */ +#ifndef RFAL_FEATURE_ST25TB +#define RFAL_FEATURE_ST25TB false /* ST25TB module configuration missing. Disabled by default */ +#endif + +#if RFAL_FEATURE_ST25TB + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ + +#define RFAL_ST25TB_CMD_LEN 1U /*!< ST25TB length of a command */ +#define RFAL_ST25TB_SLOTS 16U /*!< ST25TB number of slots */ +#define RFAL_ST25TB_SLOTNUM_MASK 0x0FU /*!< ST25TB Slot Number bit mask on SlotMarker */ +#define RFAL_ST25TB_SLOTNUM_SHIFT 4U /*!< ST25TB Slot Number shift on SlotMarker */ + +#define RFAL_ST25TB_INITIATE_CMD1 0x06U /*!< ST25TB Initiate command byte1 */ +#define RFAL_ST25TB_INITIATE_CMD2 0x00U /*!< ST25TB Initiate command byte2 */ +#define RFAL_ST25TB_PCALL_CMD1 0x06U /*!< ST25TB Pcall16 command byte1 */ +#define RFAL_ST25TB_PCALL_CMD2 0x04U /*!< ST25TB Pcall16 command byte2 */ +#define RFAL_ST25TB_SELECT_CMD 0x0EU /*!< ST25TB Select command */ +#define RFAL_ST25TB_GET_UID_CMD 0x0BU /*!< ST25TB Get UID command */ +#define RFAL_ST25TB_COMPLETION_CMD 0x0FU /*!< ST25TB Completion command */ +#define RFAL_ST25TB_RESET_INV_CMD 0x0CU /*!< ST25TB Reset to Inventory command */ +#define RFAL_ST25TB_READ_BLOCK_CMD 0x08U /*!< ST25TB Read Block command */ +#define RFAL_ST25TB_WRITE_BLOCK_CMD 0x09U /*!< ST25TB Write Block command */ + +#define RFAL_ST25TB_T0 2157U /*!< ST25TB t0 159 us ST25TB RF characteristics */ +#define RFAL_ST25TB_T1 2048U /*!< ST25TB t1 151 us ST25TB RF characteristics */ + +#define RFAL_ST25TB_FWT \ + (RFAL_ST25TB_T0 + RFAL_ST25TB_T1) /*!< ST25TB FWT = T0 + T1 */ +#define RFAL_ST25TB_TW rfalConvMsTo1fc(7U) /*!< ST25TB TW : Programming time for write max 7ms */ + +/* + ****************************************************************************** + * GLOBAL MACROS + ****************************************************************************** + */ + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + +/*! Initiate Request */ +typedef struct { + uint8_t cmd1; /*!< Initiate Request cmd1: 0x06 */ + uint8_t cmd2; /*!< Initiate Request cmd2: 0x00 */ +} rfalSt25tbInitiateReq; + +/*! Pcall16 Request */ +typedef struct { + uint8_t cmd1; /*!< Pcal16 Request cmd1: 0x06 */ + uint8_t cmd2; /*!< Pcal16 Request cmd2: 0x04 */ +} rfalSt25tbPcallReq; + +/*! Select Request */ +typedef struct { + uint8_t cmd; /*!< Select Request cmd: 0x0E */ + uint8_t chipId; /*!< Chip ID */ +} rfalSt25tbSelectReq; + +/*! Read Block Request */ +typedef struct { + uint8_t cmd; /*!< Select Request cmd: 0x08 */ + uint8_t address; /*!< Block address */ +} rfalSt25tbReadBlockReq; + +/*! Write Block Request */ +typedef struct { + uint8_t cmd; /*!< Select Request cmd: 0x09 */ + uint8_t address; /*!< Block address */ + rfalSt25tbBlock data; /*!< Block Data */ +} rfalSt25tbWriteBlockReq; + +/* +****************************************************************************** +* LOCAL FUNCTION PROTOTYPES +****************************************************************************** +*/ +/*! + ***************************************************************************** + * \brief ST25TB Poller Do Collision Resolution + * + * This method performs ST25TB Collision resolution loop for each slot + * + * \param[in] devLimit : device limit value, and size st25tbDevList + * \param[out] st25tbDevList : ST35TB listener device info + * \param[out] devCnt : Devices found counter + * + * \return colPending : true if a collision was detected + ***************************************************************************** + */ +static bool rfalSt25tbPollerDoCollisionResolution( + uint8_t devLimit, + rfalSt25tbListenDevice* st25tbDevList, + uint8_t* devCnt); + +/* +****************************************************************************** +* LOCAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +static bool rfalSt25tbPollerDoCollisionResolution( + uint8_t devLimit, + rfalSt25tbListenDevice* st25tbDevList, + uint8_t* devCnt) { + uint8_t i; + uint8_t chipId; + ReturnCode ret; + bool col; + + col = false; + + for(i = 0; i < RFAL_ST25TB_SLOTS; i++) { + platformDelay(1); /* Wait t2: Answer to new request delay */ + + if(i == 0U) { + /* Step 2: Send Pcall16 */ + ret = rfalSt25tbPollerPcall(&chipId); + } else { + /* Step 3-17: Send Pcall16 */ + ret = rfalSt25tbPollerSlotMarker(i, &chipId); + } + + if(ret == ERR_NONE) { + /* Found another device */ + st25tbDevList[*devCnt].chipID = chipId; + st25tbDevList[*devCnt].isDeselected = false; + + /* Select Device, retrieve its UID */ + ret = rfalSt25tbPollerSelect(chipId); + + /* By Selecting this device, the previous gets Deselected */ + if((*devCnt) > 0U) { + st25tbDevList[(*devCnt) - 1U].isDeselected = true; + } + + if(ERR_NONE == ret) { + rfalSt25tbPollerGetUID(&st25tbDevList[*devCnt].UID); + } + + if(ERR_NONE == ret) { + (*devCnt)++; + } + } else if((ret == ERR_CRC) || (ret == ERR_FRAMING)) { + col = true; + } else { + /* MISRA 15.7 - Empty else */ + } + + if(*devCnt >= devLimit) { + break; + } + } + return col; +} + +/* +****************************************************************************** +* LOCAL VARIABLES +****************************************************************************** +*/ + +/* +****************************************************************************** +* GLOBAL FUNCTIONS +****************************************************************************** +*/ + +/*******************************************************************************/ +ReturnCode rfalSt25tbPollerInitialize(void) { + return rfalNfcbPollerInitialize(); +} + +/*******************************************************************************/ +ReturnCode rfalSt25tbPollerCheckPresence(uint8_t* chipId) { + ReturnCode ret; + uint8_t chipIdRes; + + chipIdRes = 0x00; + + /* Send Initiate Request */ + ret = rfalSt25tbPollerInitiate(&chipIdRes); + + /* Check if a transmission error was detected */ + if((ret == ERR_CRC) || (ret == ERR_FRAMING)) { + return ERR_NONE; + } + + /* Copy chip ID if requested */ + if(chipId != NULL) { + *chipId = chipIdRes; + } + + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalSt25tbPollerInitiate(uint8_t* chipId) { + ReturnCode ret; + uint16_t rxLen; + rfalSt25tbInitiateReq initiateReq; + uint8_t rxBuf + [RFAL_ST25TB_CHIP_ID_LEN + + RFAL_ST25TB_CRC_LEN]; /* In case we receive less data that CRC, RF layer will not remove the CRC from buffer */ + + /* Compute Initiate Request */ + initiateReq.cmd1 = RFAL_ST25TB_INITIATE_CMD1; + initiateReq.cmd2 = RFAL_ST25TB_INITIATE_CMD2; + + /* Send Initiate Request */ + ret = rfalTransceiveBlockingTxRx( + (uint8_t*)&initiateReq, + sizeof(rfalSt25tbInitiateReq), + (uint8_t*)rxBuf, + sizeof(rxBuf), + &rxLen, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_ST25TB_FWT); + + /* Check for valid Select Response */ + if((ret == ERR_NONE) && (rxLen != RFAL_ST25TB_CHIP_ID_LEN)) { + return ERR_PROTO; + } + + /* Copy chip ID if requested */ + if(chipId != NULL) { + *chipId = *rxBuf; + } + + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalSt25tbPollerPcall(uint8_t* chipId) { + ReturnCode ret; + uint16_t rxLen; + rfalSt25tbPcallReq pcallReq; + + /* Compute Pcal16 Request */ + pcallReq.cmd1 = RFAL_ST25TB_PCALL_CMD1; + pcallReq.cmd2 = RFAL_ST25TB_PCALL_CMD2; + + /* Send Pcal16 Request */ + ret = rfalTransceiveBlockingTxRx( + (uint8_t*)&pcallReq, + sizeof(rfalSt25tbPcallReq), + (uint8_t*)chipId, + RFAL_ST25TB_CHIP_ID_LEN, + &rxLen, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_ST25TB_FWT); + + /* Check for valid Select Response */ + if((ret == ERR_NONE) && (rxLen != RFAL_ST25TB_CHIP_ID_LEN)) { + return ERR_PROTO; + } + + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalSt25tbPollerSlotMarker(uint8_t slotNum, uint8_t* chipIdRes) { + ReturnCode ret; + uint16_t rxLen; + uint8_t slotMarker; + + if((slotNum == 0U) || (slotNum > 15U)) { + return ERR_PARAM; + } + + /* Compute SlotMarker */ + slotMarker = + (((slotNum & RFAL_ST25TB_SLOTNUM_MASK) << RFAL_ST25TB_SLOTNUM_SHIFT) | + RFAL_ST25TB_PCALL_CMD1); + + /* Send SlotMarker */ + ret = rfalTransceiveBlockingTxRx( + (uint8_t*)&slotMarker, + RFAL_ST25TB_CMD_LEN, + (uint8_t*)chipIdRes, + RFAL_ST25TB_CHIP_ID_LEN, + &rxLen, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_ST25TB_FWT); + + /* Check for valid ChipID Response */ + if((ret == ERR_NONE) && (rxLen != RFAL_ST25TB_CHIP_ID_LEN)) { + return ERR_PROTO; + } + + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalSt25tbPollerSelect(uint8_t chipId) { + ReturnCode ret; + uint16_t rxLen; + rfalSt25tbSelectReq selectReq; + uint8_t chipIdRes; + + /* Compute Select Request */ + selectReq.cmd = RFAL_ST25TB_SELECT_CMD; + selectReq.chipId = chipId; + + /* Send Select Request */ + ret = rfalTransceiveBlockingTxRx( + (uint8_t*)&selectReq, + sizeof(rfalSt25tbSelectReq), + (uint8_t*)&chipIdRes, + RFAL_ST25TB_CHIP_ID_LEN, + &rxLen, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_ST25TB_FWT); + + /* Check for valid Select Response */ + if((ret == ERR_NONE) && ((rxLen != RFAL_ST25TB_CHIP_ID_LEN) || (chipIdRes != chipId))) { + return ERR_PROTO; + } + + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalSt25tbPollerGetUID(rfalSt25tbUID* UID) { + ReturnCode ret; + uint16_t rxLen; + uint8_t getUidReq; + + /* Compute Get UID Request */ + getUidReq = RFAL_ST25TB_GET_UID_CMD; + + /* Send Select Request */ + ret = rfalTransceiveBlockingTxRx( + (uint8_t*)&getUidReq, + RFAL_ST25TB_CMD_LEN, + (uint8_t*)UID, + sizeof(rfalSt25tbUID), + &rxLen, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_ST25TB_FWT); + + /* Check for valid UID Response */ + if((ret == ERR_NONE) && (rxLen != RFAL_ST25TB_UID_LEN)) { + return ERR_PROTO; + } + + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalSt25tbPollerCollisionResolution( + uint8_t devLimit, + rfalSt25tbListenDevice* st25tbDevList, + uint8_t* devCnt) { + uint8_t chipId; + ReturnCode ret; + bool detected; /* collision or device was detected */ + + if((st25tbDevList == NULL) || (devCnt == NULL) || (devLimit == 0U)) { + return ERR_PARAM; + } + + *devCnt = 0; + + /* Step 1: Send Initiate */ + ret = rfalSt25tbPollerInitiate(&chipId); + if(ret == ERR_NONE) { + /* If only 1 answer is detected */ + st25tbDevList[*devCnt].chipID = chipId; + st25tbDevList[*devCnt].isDeselected = false; + + /* Retrieve its UID and keep it Selected*/ + ret = rfalSt25tbPollerSelect(chipId); + + if(ERR_NONE == ret) { + ret = rfalSt25tbPollerGetUID(&st25tbDevList[*devCnt].UID); + } + + if(ERR_NONE == ret) { + (*devCnt)++; + } + } + /* Always proceed to Pcall16 anticollision as phase differences of tags can lead to no tag recognized, even if there is one */ + if(*devCnt < devLimit) { + /* Multiple device responses */ + do { + detected = rfalSt25tbPollerDoCollisionResolution(devLimit, st25tbDevList, devCnt); + } while((detected == true) && (*devCnt < devLimit)); + } + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalSt25tbPollerReadBlock(uint8_t blockAddress, rfalSt25tbBlock* blockData) { + ReturnCode ret; + uint16_t rxLen; + rfalSt25tbReadBlockReq readBlockReq; + + /* Compute Read Block Request */ + readBlockReq.cmd = RFAL_ST25TB_READ_BLOCK_CMD; + readBlockReq.address = blockAddress; + + /* Send Read Block Request */ + ret = rfalTransceiveBlockingTxRx( + (uint8_t*)&readBlockReq, + sizeof(rfalSt25tbReadBlockReq), + (uint8_t*)blockData, + sizeof(rfalSt25tbBlock), + &rxLen, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_ST25TB_FWT); + + /* Check for valid UID Response */ + if((ret == ERR_NONE) && (rxLen != RFAL_ST25TB_BLOCK_LEN)) { + return ERR_PROTO; + } + + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalSt25tbPollerWriteBlock(uint8_t blockAddress, const rfalSt25tbBlock* blockData) { + ReturnCode ret; + uint16_t rxLen; + rfalSt25tbWriteBlockReq writeBlockReq; + rfalSt25tbBlock tmpBlockData; + + /* Compute Write Block Request */ + writeBlockReq.cmd = RFAL_ST25TB_WRITE_BLOCK_CMD; + writeBlockReq.address = blockAddress; + ST_MEMCPY(&writeBlockReq.data, blockData, RFAL_ST25TB_BLOCK_LEN); + + /* Send Write Block Request */ + ret = rfalTransceiveBlockingTxRx( + (uint8_t*)&writeBlockReq, + sizeof(rfalSt25tbWriteBlockReq), + tmpBlockData, + RFAL_ST25TB_BLOCK_LEN, + &rxLen, + RFAL_TXRX_FLAGS_DEFAULT, + (RFAL_ST25TB_FWT + RFAL_ST25TB_TW)); + + /* Check if there was any error besides timeout */ + if(ret != ERR_TIMEOUT) { + /* Check if an unexpected answer was received */ + if(ret == ERR_NONE) { + return ERR_PROTO; + } + + /* Check whether a transmission error occurred */ + if((ret != ERR_CRC) && (ret != ERR_FRAMING) && (ret != ERR_NOMEM) && + (ret != ERR_RF_COLLISION)) { + return ret; + } + + /* If a transmission error occurred (maybe noise while committing data) wait maximum programming time and verify data afterwards */ + rfalSetGT((RFAL_ST25TB_FWT + RFAL_ST25TB_TW)); + rfalFieldOnAndStartGT(); + } + + ret = rfalSt25tbPollerReadBlock(blockAddress, &tmpBlockData); + if(ret == ERR_NONE) { + if(ST_BYTECMP(&tmpBlockData, blockData, RFAL_ST25TB_BLOCK_LEN) == 0) { + return ERR_NONE; + } + return ERR_PROTO; + } + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalSt25tbPollerCompletion(void) { + uint8_t completionReq; + + /* Compute Completion Request */ + completionReq = RFAL_ST25TB_COMPLETION_CMD; + + /* Send Completion Request, no response is expected */ + return rfalTransceiveBlockingTxRx( + (uint8_t*)&completionReq, + RFAL_ST25TB_CMD_LEN, + NULL, + 0, + NULL, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_ST25TB_FWT); +} + +/*******************************************************************************/ +ReturnCode rfalSt25tbPollerResetToInventory(void) { + uint8_t resetInvReq; + + /* Compute Completion Request */ + resetInvReq = RFAL_ST25TB_RESET_INV_CMD; + + /* Send Completion Request, no response is expected */ + return rfalTransceiveBlockingTxRx( + (uint8_t*)&resetInvReq, + RFAL_ST25TB_CMD_LEN, + NULL, + 0, + NULL, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_ST25TB_FWT); +} + +#endif /* RFAL_FEATURE_ST25TB */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_st25xv.c b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_st25xv.c new file mode 100644 index 00000000000..d5d3373666d --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_st25xv.c @@ -0,0 +1,818 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_st25xv.c + * + * \author Gustavo Patricio + * + * \brief NFC-V ST25 NFC-V Tag specific features + * + * This module provides support for ST's specific features available on + * NFC-V (ISO15693) tag families: ST25D, ST25TV, M24LR + * + */ + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "../include/rfal_st25xv.h" +#include "../include/rfal_nfcv.h" +#include "../utils.h" + +/* + ****************************************************************************** + * ENABLE SWITCH + ****************************************************************************** + */ + +#ifndef RFAL_FEATURE_ST25xV +#define RFAL_FEATURE_ST25xV false /* ST25xV module configuration missing. Disabled by default */ +#endif + +#if RFAL_FEATURE_ST25xV + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ + +#define RFAL_ST25xV_READ_CONFIG_LEN \ + 2U /*!< READ CONFIGURATION length */ +#define RFAL_ST25xV_READ_MSG_LEN_LEN \ + 2U /*!< READ MESSAGE LENGTH length */ +#define RFAL_ST25xV_CONF_POINTER_LEN \ + 1U /*!< READ/WRITE CONFIGURATION Pointer length */ +#define RFAL_ST25xV_CONF_REGISTER_LEN \ + 1U /*!< READ/WRITE CONFIGURATION Register length */ +#define RFAL_ST25xV_PWDNUM_LEN \ + 1U /*!< Password Number length */ +#define RFAL_ST25xV_PWD_LEN \ + 8U /*!< Password length */ +#define RFAL_ST25xV_MBPOINTER_LEN \ + 1U /*!< Read Message MBPointer length */ +#define RFAL_ST25xV_NUMBYTES_LEN \ + 1U /*!< Read Message Number of Bytes length */ + +#define RFAL_ST25TV02K_TBOOT_RF \ + 1U /*!< RF Boot time (Minimum time from carrier generation to first data) */ +#define RFAL_ST25TV02K_TRF_OFF \ + 2U /*!< RF OFF time */ + +#define RFAL_ST25xV_FDT_POLL_MAX \ + rfalConvMsTo1fc(20) /*!< Maximum Wait time FDTV,EOF 20 ms Digital 2.1 B.5 */ +#define RFAL_NFCV_FLAG_POS \ + 0U /*!< Flag byte position */ +#define RFAL_NFCV_FLAG_LEN \ + 1U /*!< Flag byte length */ + +/* +****************************************************************************** +* LOCAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +static ReturnCode rfalST25xVPollerGenericReadConfiguration( + uint8_t cmd, + uint8_t flags, + const uint8_t* uid, + uint8_t pointer, + uint8_t* regValue); +static ReturnCode rfalST25xVPollerGenericWriteConfiguration( + uint8_t cmd, + uint8_t flags, + const uint8_t* uid, + uint8_t pointer, + uint8_t regValue); +static ReturnCode rfalST25xVPollerGenericReadMessageLength( + uint8_t cmd, + uint8_t flags, + const uint8_t* uid, + uint8_t* msgLen); +static ReturnCode rfalST25xVPollerGenericReadMessage( + uint8_t cmd, + uint8_t flags, + const uint8_t* uid, + uint8_t mbPointer, + uint8_t numBytes, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvLen); +static ReturnCode rfalST25xVPollerGenericWriteMessage( + uint8_t cmd, + uint8_t flags, + const uint8_t* uid, + uint8_t msgLen, + const uint8_t* msgData, + uint8_t* txBuf, + uint16_t txBufLen); +/* +****************************************************************************** +* LOCAL FUNCTIONS +****************************************************************************** +*/ + +/*******************************************************************************/ +static ReturnCode rfalST25xVPollerGenericReadConfiguration( + uint8_t cmd, + uint8_t flags, + const uint8_t* uid, + uint8_t pointer, + uint8_t* regValue) { + ReturnCode ret; + uint8_t p; + uint16_t rcvLen; + rfalNfcvGenericRes res; + + if(regValue == NULL) { + return ERR_PARAM; + } + + p = pointer; + + ret = rfalNfcvPollerTransceiveReq( + cmd, + flags, + RFAL_NFCV_ST_IC_MFG_CODE, + uid, + &p, + sizeof(uint8_t), + (uint8_t*)&res, + sizeof(rfalNfcvGenericRes), + &rcvLen); + if(ret == ERR_NONE) { + if(rcvLen < RFAL_ST25xV_READ_CONFIG_LEN) { + ret = ERR_PROTO; + } else { + *regValue = res.data[0]; + } + } + return ret; +} + +/*******************************************************************************/ +static ReturnCode rfalST25xVPollerGenericWriteConfiguration( + uint8_t cmd, + uint8_t flags, + const uint8_t* uid, + uint8_t pointer, + uint8_t regValue) { + uint8_t data[RFAL_ST25xV_CONF_POINTER_LEN + RFAL_ST25xV_CONF_REGISTER_LEN]; + uint8_t dataLen; + uint16_t rcvLen; + rfalNfcvGenericRes res; + + dataLen = 0U; + + data[dataLen++] = pointer; + data[dataLen++] = regValue; + + return rfalNfcvPollerTransceiveReq( + cmd, + flags, + RFAL_NFCV_ST_IC_MFG_CODE, + uid, + data, + dataLen, + (uint8_t*)&res, + sizeof(rfalNfcvGenericRes), + &rcvLen); +} + +/*******************************************************************************/ +static ReturnCode rfalST25xVPollerGenericReadMessageLength( + uint8_t cmd, + uint8_t flags, + const uint8_t* uid, + uint8_t* msgLen) { + ReturnCode ret; + uint16_t rcvLen; + rfalNfcvGenericRes res; + + if(msgLen == NULL) { + return ERR_PARAM; + } + + ret = rfalNfcvPollerTransceiveReq( + cmd, + flags, + RFAL_NFCV_ST_IC_MFG_CODE, + uid, + NULL, + 0, + (uint8_t*)&res, + sizeof(rfalNfcvGenericRes), + &rcvLen); + if(ret == ERR_NONE) { + if(rcvLen < RFAL_ST25xV_READ_MSG_LEN_LEN) { + ret = ERR_PROTO; + } else { + *msgLen = res.data[0]; + } + } + return ret; +} + +/*******************************************************************************/ +static ReturnCode rfalST25xVPollerGenericReadMessage( + uint8_t cmd, + uint8_t flags, + const uint8_t* uid, + uint8_t mbPointer, + uint8_t numBytes, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvLen) { + uint8_t data[RFAL_ST25xV_MBPOINTER_LEN + RFAL_ST25xV_NUMBYTES_LEN]; + uint8_t dataLen; + + dataLen = 0; + + /* Compute Request Data */ + data[dataLen++] = mbPointer; + data[dataLen++] = numBytes; + + return rfalNfcvPollerTransceiveReq( + cmd, flags, RFAL_NFCV_ST_IC_MFG_CODE, uid, data, dataLen, rxBuf, rxBufLen, rcvLen); +} + +/*******************************************************************************/ +static ReturnCode rfalST25xVPollerGenericWriteMessage( + uint8_t cmd, + uint8_t flags, + const uint8_t* uid, + uint8_t msgLen, + const uint8_t* msgData, + uint8_t* txBuf, + uint16_t txBufLen) { + ReturnCode ret; + uint8_t reqFlag; + uint16_t msgIt; + rfalBitRate rxBR; + bool fastMode; + rfalNfcvGenericRes res; + uint16_t rcvLen; + + /* Calculate required Tx buf length: Mfg Code UID MSGLen MSGLen+1 */ + msgIt = (uint16_t)(msgLen + sizeof(flags) + sizeof(cmd) + 1U + + ((uid != NULL) ? RFAL_NFCV_UID_LEN : 0U) + 1U + 1U); + /* Note: MSGlength parameter of the command is the number of Data bytes minus - 1 (00 for 1 byte of data, FFh for 256 bytes of data) */ + + /* Check for valid parameters */ + if((txBuf == NULL) || (msgData == NULL) || (txBufLen < msgIt)) { + return ERR_PARAM; + } + + msgIt = 0; + fastMode = false; + + /* Check if the command is an ST's Fast command */ + if(cmd == (uint8_t)RFAL_NFCV_CMD_FAST_WRITE_MESSAGE) { + /* Store current Rx bit rate and move to fast mode */ + rfalGetBitRate(NULL, &rxBR); + rfalSetBitRate(RFAL_BR_KEEP, RFAL_BR_52p97); + + fastMode = true; + } + + /* Compute Request Command */ + reqFlag = (uint8_t)(flags & (~((uint32_t)RFAL_NFCV_REQ_FLAG_ADDRESS) & + ~((uint32_t)RFAL_NFCV_REQ_FLAG_SELECT))); + reqFlag |= + ((uid != NULL) ? (uint8_t)RFAL_NFCV_REQ_FLAG_ADDRESS : (uint8_t)RFAL_NFCV_REQ_FLAG_SELECT); + + txBuf[msgIt++] = reqFlag; + txBuf[msgIt++] = cmd; + txBuf[msgIt++] = RFAL_NFCV_ST_IC_MFG_CODE; + + if(uid != NULL) { + ST_MEMCPY(&txBuf[msgIt], uid, RFAL_NFCV_UID_LEN); + msgIt += RFAL_NFCV_UID_LEN; + } + txBuf[msgIt++] = msgLen; + ST_MEMCPY( + &txBuf[msgIt], + msgData, + (uint16_t)(msgLen + (uint16_t)1U)); /* Message Data contains (MSGLength + 1) bytes */ + msgIt += (uint16_t)(msgLen + (uint16_t)1U); + + /* Transceive Command */ + ret = rfalTransceiveBlockingTxRx( + txBuf, + msgIt, + (uint8_t*)&res, + sizeof(rfalNfcvGenericRes), + &rcvLen, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_ST25xV_FDT_POLL_MAX); + + /* Restore Rx BitRate */ + if(fastMode) { + rfalSetBitRate(RFAL_BR_KEEP, rxBR); + } + + if(ret != ERR_NONE) { + return ret; + } + + /* Check if the response minimum length has been received */ + if(rcvLen < (uint8_t)RFAL_NFCV_FLAG_LEN) { + return ERR_PROTO; + } + + /* Check if an error has been signalled */ + if((res.RES_FLAG & (uint8_t)RFAL_NFCV_RES_FLAG_ERROR) != 0U) { + return ERR_PROTO; + } + + return ERR_NONE; +} + +/* +****************************************************************************** +* GLOBAL FUNCTIONS +****************************************************************************** +*/ + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerM24LRReadSingleBlock( + uint8_t flags, + const uint8_t* uid, + uint16_t blockNum, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvLen) { + uint8_t data[RFAL_NFCV_BLOCKNUM_M24LR_LEN]; + uint8_t dataLen; + + dataLen = 0; + + /* Compute Request Data */ + data[dataLen++] = (uint8_t)blockNum; /* Set M24LR Block Number (16 bits) LSB */ + data[dataLen++] = (uint8_t)(blockNum >> 8U); /* Set M24LR Block Number (16 bits) MSB */ + + return rfalNfcvPollerTransceiveReq( + RFAL_NFCV_CMD_READ_SINGLE_BLOCK, + (flags | (uint8_t)RFAL_NFCV_REQ_FLAG_PROTOCOL_EXT), + RFAL_NFCV_PARAM_SKIP, + uid, + data, + dataLen, + rxBuf, + rxBufLen, + rcvLen); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerM24LRWriteSingleBlock( + uint8_t flags, + const uint8_t* uid, + uint16_t blockNum, + const uint8_t* wrData, + uint8_t blockLen) { + uint8_t data[(RFAL_NFCV_BLOCKNUM_M24LR_LEN + RFAL_NFCV_MAX_BLOCK_LEN)]; + uint8_t dataLen; + uint16_t rcvLen; + rfalNfcvGenericRes res; + + /* Check for valid parameters */ + if((blockLen == 0U) || (blockLen > (uint8_t)RFAL_NFCV_MAX_BLOCK_LEN) || (wrData == NULL)) { + return ERR_PARAM; + } + + dataLen = 0U; + + /* Compute Request Data */ + data[dataLen++] = (uint8_t)blockNum; /* Set M24LR Block Number (16 bits) LSB */ + data[dataLen++] = (uint8_t)(blockNum >> 8U); /* Set M24LR Block Number (16 bits) MSB */ + ST_MEMCPY(&data[dataLen], wrData, blockLen); /* Append Block data to write */ + dataLen += blockLen; + + return rfalNfcvPollerTransceiveReq( + RFAL_NFCV_CMD_WRITE_SINGLE_BLOCK, + (flags | (uint8_t)RFAL_NFCV_REQ_FLAG_PROTOCOL_EXT), + RFAL_NFCV_PARAM_SKIP, + uid, + data, + dataLen, + (uint8_t*)&res, + sizeof(rfalNfcvGenericRes), + &rcvLen); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerM24LRReadMultipleBlocks( + uint8_t flags, + const uint8_t* uid, + uint16_t firstBlockNum, + uint8_t numOfBlocks, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvLen) { + uint8_t data[(RFAL_NFCV_BLOCKNUM_M24LR_LEN + RFAL_NFCV_BLOCKNUM_M24LR_LEN)]; + uint8_t dataLen; + + dataLen = 0U; + + /* Compute Request Data */ + data[dataLen++] = (uint8_t)firstBlockNum; /* Set M24LR Block Number (16 bits) LSB */ + data[dataLen++] = (uint8_t)(firstBlockNum >> 8U); /* Set M24LR Block Number (16 bits) MSB */ + data[dataLen++] = numOfBlocks; /* Set number of blocks to read */ + + return rfalNfcvPollerTransceiveReq( + RFAL_NFCV_CMD_READ_MULTIPLE_BLOCKS, + (flags | (uint8_t)RFAL_NFCV_REQ_FLAG_PROTOCOL_EXT), + RFAL_NFCV_PARAM_SKIP, + uid, + data, + dataLen, + rxBuf, + rxBufLen, + rcvLen); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerFastReadSingleBlock( + uint8_t flags, + const uint8_t* uid, + uint8_t blockNum, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvLen) { + uint8_t bn; + + bn = blockNum; + + return rfalNfcvPollerTransceiveReq( + RFAL_NFCV_CMD_FAST_READ_SINGLE_BLOCK, + flags, + RFAL_NFCV_ST_IC_MFG_CODE, + uid, + &bn, + sizeof(uint8_t), + rxBuf, + rxBufLen, + rcvLen); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerM24LRFastReadSingleBlock( + uint8_t flags, + const uint8_t* uid, + uint16_t blockNum, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvLen) { + uint8_t data[RFAL_NFCV_BLOCKNUM_M24LR_LEN]; + uint8_t dataLen; + + dataLen = 0; + + /* Compute Request Data */ + data[dataLen++] = (uint8_t)blockNum; /* Set M24LR Block Number (16 bits) LSB */ + data[dataLen++] = (uint8_t)(blockNum >> 8U); /* Set M24LR Block Number (16 bits) MSB */ + + return rfalNfcvPollerTransceiveReq( + RFAL_NFCV_CMD_FAST_READ_SINGLE_BLOCK, + (flags | (uint8_t)RFAL_NFCV_REQ_FLAG_PROTOCOL_EXT), + RFAL_NFCV_ST_IC_MFG_CODE, + uid, + data, + dataLen, + rxBuf, + rxBufLen, + rcvLen); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerM24LRFastReadMultipleBlocks( + uint8_t flags, + const uint8_t* uid, + uint16_t firstBlockNum, + uint8_t numOfBlocks, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvLen) { + uint8_t data[(RFAL_NFCV_BLOCKNUM_M24LR_LEN + RFAL_NFCV_BLOCKNUM_M24LR_LEN)]; + uint8_t dataLen; + + dataLen = 0U; + + /* Compute Request Data */ + data[dataLen++] = (uint8_t)firstBlockNum; /* Set M24LR Block Number (16 bits) LSB */ + data[dataLen++] = (uint8_t)(firstBlockNum >> 8U); /* Set M24LR Block Number (16 bits) MSB */ + data[dataLen++] = numOfBlocks; /* Set number of blocks to read */ + + return rfalNfcvPollerTransceiveReq( + RFAL_NFCV_CMD_FAST_READ_MULTIPLE_BLOCKS, + (flags | (uint8_t)RFAL_NFCV_REQ_FLAG_PROTOCOL_EXT), + RFAL_NFCV_ST_IC_MFG_CODE, + uid, + data, + dataLen, + rxBuf, + rxBufLen, + rcvLen); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerFastReadMultipleBlocks( + uint8_t flags, + const uint8_t* uid, + uint8_t firstBlockNum, + uint8_t numOfBlocks, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvLen) { + uint8_t data[(RFAL_NFCV_BLOCKNUM_LEN + RFAL_NFCV_BLOCKNUM_LEN)]; + uint8_t dataLen; + + dataLen = 0U; + + /* Compute Request Data */ + data[dataLen++] = firstBlockNum; /* Set first Block Number */ + data[dataLen++] = numOfBlocks; /* Set number of blocks to read */ + + return rfalNfcvPollerTransceiveReq( + RFAL_NFCV_CMD_FAST_READ_MULTIPLE_BLOCKS, + flags, + RFAL_NFCV_ST_IC_MFG_CODE, + uid, + data, + dataLen, + rxBuf, + rxBufLen, + rcvLen); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerFastExtendedReadSingleBlock( + uint8_t flags, + const uint8_t* uid, + uint16_t blockNum, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvLen) { + uint8_t data[RFAL_NFCV_BLOCKNUM_EXTENDED_LEN]; + uint8_t dataLen; + + dataLen = 0U; + + /* Compute Request Data */ + data[dataLen++] = (uint8_t) + blockNum; /* TS T5T 1.0 BNo is considered as a multi-byte field. TS T5T 1.0 5.1.1.13 multi-byte field follows [DIGITAL]. [DIGITAL] 9.3.1 A multiple byte field is transmitted LSB first. */ + data[dataLen++] = (uint8_t)((blockNum >> 8U) & 0xFFU); + + return rfalNfcvPollerTransceiveReq( + RFAL_NFCV_CMD_FAST_EXTENDED_READ_SINGLE_BLOCK, + flags, + RFAL_NFCV_ST_IC_MFG_CODE, + uid, + data, + dataLen, + rxBuf, + rxBufLen, + rcvLen); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerFastExtReadMultipleBlocks( + uint8_t flags, + const uint8_t* uid, + uint16_t firstBlockNum, + uint16_t numOfBlocks, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvLen) { + uint8_t data[(RFAL_NFCV_BLOCKNUM_EXTENDED_LEN + RFAL_NFCV_BLOCKNUM_EXTENDED_LEN)]; + uint8_t dataLen; + + dataLen = 0U; + + /* Compute Request Data */ + data[dataLen++] = (uint8_t)((firstBlockNum >> 0U) & 0xFFU); + data[dataLen++] = (uint8_t)((firstBlockNum >> 8U) & 0xFFU); + data[dataLen++] = (uint8_t)((numOfBlocks >> 0U) & 0xFFU); + data[dataLen++] = (uint8_t)((numOfBlocks >> 8U) & 0xFFU); + + return rfalNfcvPollerTransceiveReq( + RFAL_NFCV_CMD_FAST_EXTENDED_READ_MULTIPLE_BLOCKS, + flags, + RFAL_NFCV_ST_IC_MFG_CODE, + uid, + data, + dataLen, + rxBuf, + rxBufLen, + rcvLen); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerReadConfiguration( + uint8_t flags, + const uint8_t* uid, + uint8_t pointer, + uint8_t* regValue) { + return rfalST25xVPollerGenericReadConfiguration( + RFAL_NFCV_CMD_READ_CONFIGURATION, flags, uid, pointer, regValue); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerWriteConfiguration( + uint8_t flags, + const uint8_t* uid, + uint8_t pointer, + uint8_t regValue) { + return rfalST25xVPollerGenericWriteConfiguration( + RFAL_NFCV_CMD_WRITE_CONFIGURATION, flags, uid, pointer, regValue); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerReadDynamicConfiguration( + uint8_t flags, + const uint8_t* uid, + uint8_t pointer, + uint8_t* regValue) { + return rfalST25xVPollerGenericReadConfiguration( + RFAL_NFCV_CMD_READ_DYN_CONFIGURATION, flags, uid, pointer, regValue); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerWriteDynamicConfiguration( + uint8_t flags, + const uint8_t* uid, + uint8_t pointer, + uint8_t regValue) { + return rfalST25xVPollerGenericWriteConfiguration( + RFAL_NFCV_CMD_WRITE_DYN_CONFIGURATION, flags, uid, pointer, regValue); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerFastReadDynamicConfiguration( + uint8_t flags, + const uint8_t* uid, + uint8_t pointer, + uint8_t* regValue) { + return rfalST25xVPollerGenericReadConfiguration( + RFAL_NFCV_CMD_FAST_READ_DYN_CONFIGURATION, flags, uid, pointer, regValue); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerFastWriteDynamicConfiguration( + uint8_t flags, + const uint8_t* uid, + uint8_t pointer, + uint8_t regValue) { + return rfalST25xVPollerGenericWriteConfiguration( + RFAL_NFCV_CMD_FAST_WRITE_DYN_CONFIGURATION, flags, uid, pointer, regValue); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerPresentPassword( + uint8_t flags, + const uint8_t* uid, + uint8_t pwdNum, + const uint8_t* pwd, + uint8_t pwdLen) { + uint8_t data[RFAL_ST25xV_PWDNUM_LEN + RFAL_ST25xV_PWD_LEN]; + uint8_t dataLen; + uint16_t rcvLen; + rfalNfcvGenericRes res; + + if((pwdLen > RFAL_ST25xV_PWD_LEN) || (pwd == NULL)) { + return ERR_PARAM; + } + + dataLen = 0U; + data[dataLen++] = pwdNum; + if(pwdLen > 0U) { + ST_MEMCPY(&data[dataLen], pwd, pwdLen); + } + dataLen += pwdLen; + + return rfalNfcvPollerTransceiveReq( + RFAL_NFCV_CMD_PRESENT_PASSWORD, + flags, + RFAL_NFCV_ST_IC_MFG_CODE, + uid, + data, + dataLen, + (uint8_t*)&res, + sizeof(rfalNfcvGenericRes), + &rcvLen); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerGetRandomNumber( + uint8_t flags, + const uint8_t* uid, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvLen) { + rfalFieldOff(); + platformDelay(RFAL_ST25TV02K_TRF_OFF); + rfalNfcvPollerInitialize(); + rfalFieldOnAndStartGT(); + platformDelay(RFAL_ST25TV02K_TBOOT_RF); + return rfalNfcvPollerTransceiveReq( + RFAL_NFCV_CMD_GET_RANDOM_NUMBER, + flags, + RFAL_NFCV_ST_IC_MFG_CODE, + uid, + NULL, + 0U, + rxBuf, + rxBufLen, + rcvLen); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerWriteMessage( + uint8_t flags, + const uint8_t* uid, + uint8_t msgLen, + const uint8_t* msgData, + uint8_t* txBuf, + uint16_t txBufLen) { + return rfalST25xVPollerGenericWriteMessage( + RFAL_NFCV_CMD_WRITE_MESSAGE, flags, uid, msgLen, msgData, txBuf, txBufLen); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerFastWriteMessage( + uint8_t flags, + const uint8_t* uid, + uint8_t msgLen, + const uint8_t* msgData, + uint8_t* txBuf, + uint16_t txBufLen) { + return rfalST25xVPollerGenericWriteMessage( + RFAL_NFCV_CMD_FAST_WRITE_MESSAGE, flags, uid, msgLen, msgData, txBuf, txBufLen); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerReadMessageLength(uint8_t flags, const uint8_t* uid, uint8_t* msgLen) { + return rfalST25xVPollerGenericReadMessageLength( + RFAL_NFCV_CMD_READ_MESSAGE_LENGTH, flags, uid, msgLen); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerFastReadMsgLength(uint8_t flags, const uint8_t* uid, uint8_t* msgLen) { + return rfalST25xVPollerGenericReadMessageLength( + RFAL_NFCV_CMD_FAST_READ_MESSAGE_LENGTH, flags, uid, msgLen); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerReadMessage( + uint8_t flags, + const uint8_t* uid, + uint8_t mbPointer, + uint8_t numBytes, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvLen) { + return rfalST25xVPollerGenericReadMessage( + RFAL_NFCV_CMD_READ_MESSAGE, flags, uid, mbPointer, numBytes, rxBuf, rxBufLen, rcvLen); +} + +/*******************************************************************************/ +ReturnCode rfalST25xVPollerFastReadMessage( + uint8_t flags, + const uint8_t* uid, + uint8_t mbPointer, + uint8_t numBytes, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rcvLen) { + return rfalST25xVPollerGenericReadMessage( + RFAL_NFCV_CMD_FAST_READ_MESSAGE, flags, uid, mbPointer, numBytes, rxBuf, rxBufLen, rcvLen); +} + +#endif /* RFAL_FEATURE_ST25xV */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_t1t.c b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_t1t.c new file mode 100644 index 00000000000..52c3b96bccf --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_t1t.c @@ -0,0 +1,233 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_t1t.c + * + * \author Gustavo Patricio + * + * \brief Provides NFC-A T1T convenience methods and definitions + * + * This module provides an interface to perform as a NFC-A Reader/Writer + * to handle a Type 1 Tag T1T (Topaz) + * + */ + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "../include/rfal_t1t.h" +#include "../utils.h" + +/* + ****************************************************************************** + * ENABLE SWITCH + ****************************************************************************** + */ + +#ifndef RFAL_FEATURE_T1T +#define RFAL_FEATURE_T1T false /* T1T module configuration missing. Disabled by default */ +#endif + +#if RFAL_FEATURE_T1T + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ + +#define RFAL_T1T_DRD_READ \ + (1236U * 2U) /*!< DRD for Reads with n=9 => 1236/fc ~= 91 us T1T 1.2 4.4.2 */ +#define RFAL_T1T_DRD_WRITE \ + 36052U /*!< DRD for Write with n=281 => 36052/fc ~= 2659 us T1T 1.2 4.4.2 */ +#define RFAL_T1T_DRD_WRITE_E \ + 70996U /*!< DRD for Write/Erase with n=554 => 70996/fc ~= 5236 us T1T 1.2 4.4.2 */ + +#define RFAL_T1T_RID_RES_HR0_VAL \ + 0x10U /*!< HR0 indicating NDEF support Digital 2.0 (Candidate) 11.6.2.1 */ +#define RFAL_T1T_RID_RES_HR0_MASK \ + 0xF0U /*!< HR0 most significant nibble mask */ + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + +/*! NFC-A T1T (Topaz) RID_REQ Digital 1.1 10.6.1 & Table 49 */ +typedef struct { + uint8_t cmd; /*!< T1T cmd: RID */ + uint8_t add; /*!< ADD: undefined value */ + uint8_t data; /*!< DATA: undefined value */ + uint8_t uid[RFAL_T1T_UID_LEN]; /*!< UID-echo: undefined value */ +} rfalT1TRidReq; + +/*! NFC-A T1T (Topaz) RALL_REQ T1T 1.2 Table 4 */ +typedef struct { + uint8_t cmd; /*!< T1T cmd: RALL */ + uint8_t add1; /*!< ADD: 0x00 */ + uint8_t add0; /*!< ADD: 0x00 */ + uint8_t uid[RFAL_T1T_UID_LEN]; /*!< UID */ +} rfalT1TRallReq; + +/*! NFC-A T1T (Topaz) WRITE_REQ T1T 1.2 Table 4 */ +typedef struct { + uint8_t cmd; /*!< T1T cmd: RALL */ + uint8_t add; /*!< ADD */ + uint8_t data; /*!< DAT */ + uint8_t uid[RFAL_T1T_UID_LEN]; /*!< UID */ +} rfalT1TWriteReq; + +/*! NFC-A T1T (Topaz) WRITE_RES T1T 1.2 Table 4 */ +typedef struct { + uint8_t add; /*!< ADD */ + uint8_t data; /*!< DAT */ +} rfalT1TWriteRes; + +/* +****************************************************************************** +* LOCAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +/* +****************************************************************************** +* GLOBAL FUNCTIONS +****************************************************************************** +*/ + +ReturnCode rfalT1TPollerInitialize(void) { + ReturnCode ret; + + EXIT_ON_ERR(ret, rfalSetMode(RFAL_MODE_POLL_NFCA_T1T, RFAL_BR_106, RFAL_BR_106)); + rfalSetErrorHandling(RFAL_ERRORHANDLING_NFC); + + rfalSetGT( + RFAL_GT_NONE); /* T1T should only be initialized after NFC-A mode, therefore the GT has been fulfilled */ + rfalSetFDTListen( + RFAL_FDT_LISTEN_NFCA_POLLER); /* T1T uses NFC-A FDT Listen with n=9 Digital 1.1 10.7.2 */ + rfalSetFDTPoll(RFAL_FDT_POLL_NFCA_T1T_POLLER); + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalT1TPollerRid(rfalT1TRidRes* ridRes) { + ReturnCode ret; + rfalT1TRidReq ridReq; + uint16_t rcvdLen; + + if(ridRes == NULL) { + return ERR_PARAM; + } + + /* Compute RID command and set Undefined Values to 0x00 Digital 1.1 10.6.1 */ + ST_MEMSET(&ridReq, 0x00, sizeof(rfalT1TRidReq)); + ridReq.cmd = (uint8_t)RFAL_T1T_CMD_RID; + + EXIT_ON_ERR( + ret, + rfalTransceiveBlockingTxRx( + (uint8_t*)&ridReq, + sizeof(rfalT1TRidReq), + (uint8_t*)ridRes, + sizeof(rfalT1TRidRes), + &rcvdLen, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_T1T_DRD_READ)); + + /* Check expected RID response length and the HR0 Digital 2.0 (Candidate) 11.6.2.1 */ + if((rcvdLen != sizeof(rfalT1TRidRes)) || + ((ridRes->hr0 & RFAL_T1T_RID_RES_HR0_MASK) != RFAL_T1T_RID_RES_HR0_VAL)) { + return ERR_PROTO; + } + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode + rfalT1TPollerRall(const uint8_t* uid, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t* rxRcvdLen) { + rfalT1TRallReq rallReq; + + if((rxBuf == NULL) || (uid == NULL) || (rxRcvdLen == NULL)) { + return ERR_PARAM; + } + + /* Compute RALL command and set Add to 0x00 */ + ST_MEMSET(&rallReq, 0x00, sizeof(rfalT1TRallReq)); + rallReq.cmd = (uint8_t)RFAL_T1T_CMD_RALL; + ST_MEMCPY(rallReq.uid, uid, RFAL_T1T_UID_LEN); + + return rfalTransceiveBlockingTxRx( + (uint8_t*)&rallReq, + sizeof(rfalT1TRallReq), + (uint8_t*)rxBuf, + rxBufLen, + rxRcvdLen, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_T1T_DRD_READ); +} + +/*******************************************************************************/ +ReturnCode rfalT1TPollerWrite(const uint8_t* uid, uint8_t address, uint8_t data) { + rfalT1TWriteReq writeReq; + rfalT1TWriteRes writeRes; + uint16_t rxRcvdLen; + ReturnCode err; + + if(uid == NULL) { + return ERR_PARAM; + } + + writeReq.cmd = (uint8_t)RFAL_T1T_CMD_WRITE_E; + writeReq.add = address; + writeReq.data = data; + ST_MEMCPY(writeReq.uid, uid, RFAL_T1T_UID_LEN); + + err = rfalTransceiveBlockingTxRx( + (uint8_t*)&writeReq, + sizeof(rfalT1TWriteReq), + (uint8_t*)&writeRes, + sizeof(rfalT1TWriteRes), + &rxRcvdLen, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_T1T_DRD_WRITE_E); + + if(err == ERR_NONE) { + if((writeReq.add != writeRes.add) || (writeReq.data != writeRes.data) || + (rxRcvdLen != sizeof(rfalT1TWriteRes))) { + return ERR_PROTO; + } + } + return err; +} + +#endif /* RFAL_FEATURE_T1T */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_t2t.c b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_t2t.c new file mode 100644 index 00000000000..6a974224757 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_t2t.c @@ -0,0 +1,253 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_t2t.c + * + * \author + * + * \brief Provides NFC-A T2T convenience methods and definitions + * + * This module provides an interface to perform as a NFC-A Reader/Writer + * to handle a Type 2 Tag T2T + * + */ + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "../include/rfal_t2t.h" +#include "../utils.h" + +/* + ****************************************************************************** + * ENABLE SWITCH + ****************************************************************************** + */ + +#ifndef RFAL_FEATURE_T2T +#define RFAL_FEATURE_T2T false /* T2T module configuration missing. Disabled by default */ +#endif + +#if RFAL_FEATURE_T2T + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ +#define RFAL_FDT_POLL_READ_MAX \ + rfalConvMsTo1fc( \ + 5U) /*!< Maximum Wait time for Read command as defined in TS T2T 1.0 table 18 */ +#define RFAL_FDT_POLL_WRITE_MAX \ + rfalConvMsTo1fc( \ + 10U) /*!< Maximum Wait time for Write command as defined in TS T2T 1.0 table 18 */ +#define RFAL_FDT_POLL_SL_MAX \ + rfalConvMsTo1fc( \ + 1U) /*!< Maximum Wait time for Sector Select as defined in TS T2T 1.0 table 18 */ +#define RFAL_T2T_ACK_NACK_LEN \ + 1U /*!< Len of NACK in bytes (4 bits) */ +#define RFAL_T2T_ACK \ + 0x0AU /*!< ACK value */ +#define RFAL_T2T_ACK_MASK \ + 0x0FU /*!< ACK value */ + +#define RFAL_T2T_SECTOR_SELECT_P1_BYTE2 \ + 0xFFU /*!< Sector Select Packet 1 byte 2 */ +#define RFAL_T2T_SECTOR_SELECT_P2_RFU_LEN \ + 3U /*!< Sector Select RFU length */ + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + +/*! NFC-A T2T command set T2T 1.0 5.1 */ +typedef enum { + RFAL_T2T_CMD_READ = 0x30, /*!< T2T Read */ + RFAL_T2T_CMD_WRITE = 0xA2, /*!< T2T Write */ + RFAL_T2T_CMD_SECTOR_SELECT = 0xC2 /*!< T2T Sector Select */ +} rfalT2Tcmds; + +/*! NFC-A T2T READ T2T 1.0 5.2 and table 11 */ +typedef struct { + uint8_t code; /*!< Command code */ + uint8_t blNo; /*!< Block number */ +} rfalT2TReadReq; + +/*! NFC-A T2T WRITE T2T 1.0 5.3 and table 12 */ +typedef struct { + uint8_t code; /*!< Command code */ + uint8_t blNo; /*!< Block number */ + uint8_t data[RFAL_T2T_WRITE_DATA_LEN]; /*!< Data */ +} rfalT2TWriteReq; + +/*! NFC-A T2T SECTOR SELECT Packet 1 T2T 1.0 5.4 and table 13 */ +typedef struct { + uint8_t code; /*!< Command code */ + uint8_t byte2; /*!< Sector Select Packet 1 byte 2 */ +} rfalT2TSectorSelectP1Req; + +/*! NFC-A T2T SECTOR SELECT Packet 2 T2T 1.0 5.4 and table 13 */ +typedef struct { + uint8_t secNo; /*!< Block number */ + uint8_t rfu[RFAL_T2T_SECTOR_SELECT_P2_RFU_LEN]; /*!< Sector Select Packet RFU */ +} rfalT2TSectorSelectP2Req; + +/* + ****************************************************************************** + * GLOBAL FUNCTIONS + ****************************************************************************** + */ + +ReturnCode + rfalT2TPollerRead(uint8_t blockNum, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t* rcvLen) { + ReturnCode ret; + rfalT2TReadReq req; + + if((rxBuf == NULL) || (rcvLen == NULL)) { + return ERR_PARAM; + } + + req.code = (uint8_t)RFAL_T2T_CMD_READ; + req.blNo = blockNum; + + /* Transceive Command */ + ret = rfalTransceiveBlockingTxRx( + (uint8_t*)&req, + sizeof(rfalT2TReadReq), + rxBuf, + rxBufLen, + rcvLen, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_FDT_POLL_READ_MAX); + + /* T2T 1.0 5.2.1.7 The Reader/Writer SHALL treat a NACK in response to a READ Command as a Protocol Error */ + if((ret == ERR_INCOMPLETE_BYTE) && (*rcvLen == RFAL_T2T_ACK_NACK_LEN) && + ((*rxBuf & RFAL_T2T_ACK_MASK) != RFAL_T2T_ACK)) { + return ERR_PROTO; + } + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalT2TPollerWrite(uint8_t blockNum, const uint8_t* wrData) { + ReturnCode ret; + rfalT2TWriteReq req; + uint8_t res; + uint16_t rxLen; + + req.code = (uint8_t)RFAL_T2T_CMD_WRITE; + req.blNo = blockNum; + ST_MEMCPY(req.data, wrData, RFAL_T2T_WRITE_DATA_LEN); + + /* Transceive WRITE Command */ + ret = rfalTransceiveBlockingTxRx( + (uint8_t*)&req, + sizeof(rfalT2TWriteReq), + &res, + sizeof(uint8_t), + &rxLen, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_FDT_POLL_READ_MAX); + + /* Check for a valid ACK */ + if((ret == ERR_INCOMPLETE_BYTE) || (ret == ERR_NONE)) { + ret = ERR_PROTO; + + if((rxLen == RFAL_T2T_ACK_NACK_LEN) && ((res & RFAL_T2T_ACK_MASK) == RFAL_T2T_ACK)) { + ret = ERR_NONE; + } + } + + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalT2TPollerSectorSelect(uint8_t sectorNum) { + rfalT2TSectorSelectP1Req p1Req; + rfalT2TSectorSelectP2Req p2Req; + ReturnCode ret; + uint8_t res; + uint16_t rxLen; + + /* Compute SECTOR SELECT Packet 1 */ + p1Req.code = (uint8_t)RFAL_T2T_CMD_SECTOR_SELECT; + p1Req.byte2 = RFAL_T2T_SECTOR_SELECT_P1_BYTE2; + + /* Transceive SECTOR SELECT Packet 1 */ + ret = rfalTransceiveBlockingTxRx( + (uint8_t*)&p1Req, + sizeof(rfalT2TSectorSelectP1Req), + &res, + sizeof(uint8_t), + &rxLen, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_FDT_POLL_SL_MAX); + + /* Check and report any transmission error */ + if((ret != ERR_INCOMPLETE_BYTE) && (ret != ERR_NONE)) { + return ret; + } + + /* Ensure that an ACK was received */ + if((ret != ERR_INCOMPLETE_BYTE) || (rxLen != RFAL_T2T_ACK_NACK_LEN) || + ((res & RFAL_T2T_ACK_MASK) != RFAL_T2T_ACK)) { + return ERR_PROTO; + } + + /* Compute SECTOR SELECT Packet 2 */ + p2Req.secNo = sectorNum; + ST_MEMSET(&p2Req.rfu, 0x00, RFAL_T2T_SECTOR_SELECT_P2_RFU_LEN); + + /* Transceive SECTOR SELECT Packet 2 */ + ret = rfalTransceiveBlockingTxRx( + (uint8_t*)&p2Req, + sizeof(rfalT2TSectorSelectP2Req), + &res, + sizeof(uint8_t), + &rxLen, + RFAL_TXRX_FLAGS_DEFAULT, + RFAL_FDT_POLL_SL_MAX); + + /* T2T 1.0 5.4.1.14 The Reader/Writer SHALL treat any response received before the end of PATT2T,SL,MAX as a Protocol Error */ + if((ret == ERR_NONE) || (ret == ERR_INCOMPLETE_BYTE)) { + return ERR_PROTO; + } + + /* T2T 1.0 5.4.1.13 The Reader/Writer SHALL treat the transmission of the SECTOR SELECT Command Packet 2 as being successful when it receives no response until PATT2T,SL,MAX. */ + if(ret == ERR_TIMEOUT) { + return ERR_NONE; + } + + return ret; +} + +#endif /* RFAL_FEATURE_T2T */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_t4t.c b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_t4t.c new file mode 100644 index 00000000000..4dbead24fd3 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/rfal_t4t.c @@ -0,0 +1,397 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_t4t.h + * + * \author Gustavo Patricio + * + * \brief Provides convenience methods and definitions for T4T (ISO7816-4) + * + * This module provides an interface to exchange T4T APDUs according to + * NFC Forum T4T and ISO7816-4 + * + * This implementation was based on the following specs: + * - ISO/IEC 7816-4 3rd Edition 2013-04-15 + * - NFC Forum T4T Technical Specification 1.0 2017-08-28 + * + */ + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "../include/rfal_t4t.h" +#include "../utils.h" + +/* + ****************************************************************************** + * ENABLE SWITCH + ****************************************************************************** + */ + +#ifndef RFAL_FEATURE_T4T +#define RFAL_FEATURE_T4T false /* T4T module configuration missing. Disabled by default */ +#endif + +#if RFAL_FEATURE_T4T + +/* + ****************************************************************************** + * GLOBAL DEFINES + ****************************************************************************** + */ +#define RFAL_T4T_OFFSET_DO 0x54U /*!< Tag value for offset BER-TLV data object */ +#define RFAL_T4T_LENGTH_DO 0x03U /*!< Len value for offset BER-TLV data object */ +#define RFAL_T4T_DATA_DO 0x53U /*!< Tag value for data BER-TLV data object */ + +#define RFAL_T4T_MAX_LC 255U /*!< Maximum Lc value for short Lc coding */ +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + +/* +****************************************************************************** +* GLOBAL MACROS +****************************************************************************** +*/ + +/* + ****************************************************************************** + * LOCAL VARIABLES + ****************************************************************************** + */ + +/* + ****************************************************************************** + * GLOBAL FUNCTIONS + ****************************************************************************** + */ + +/*******************************************************************************/ +ReturnCode rfalT4TPollerComposeCAPDU(const rfalT4tCApduParam* apduParam) { + uint8_t hdrLen; + uint16_t msgIt; + + if((apduParam == NULL) || (apduParam->cApduBuf == NULL) || (apduParam->cApduLen == NULL)) { + return ERR_PARAM; + } + + msgIt = 0; + *(apduParam->cApduLen) = 0; + + /*******************************************************************************/ + /* Compute Command-APDU according to the format T4T 1.0 5.1.2 & ISO7816-4 2013 Table 1 */ + + /* Check if Data is present */ + if(apduParam->LcFlag) { + if(apduParam->Lc == 0U) { + /* Extended field coding not supported */ + return ERR_PARAM; + } + + /* Check whether requested Lc fits */ +#pragma GCC diagnostic ignored "-Wtype-limits" + if((uint16_t)apduParam->Lc > + (uint16_t)(RFAL_FEATURE_ISO_DEP_APDU_MAX_LEN - RFAL_T4T_LE_LEN)) { + return ERR_PARAM; /* PRQA S 2880 # MISRA 2.1 - Unreachable code due to configuration option being set/unset */ + } + + /* Calculate the header length a place the data/body where it should be */ + hdrLen = RFAL_T4T_MAX_CAPDU_PROLOGUE_LEN + RFAL_T4T_LC_LEN; + + /* make sure not to exceed buffer size */ + if(((uint16_t)hdrLen + (uint16_t)apduParam->Lc + + (apduParam->LeFlag ? RFAL_T4T_LC_LEN : 0U)) > RFAL_FEATURE_ISO_DEP_APDU_MAX_LEN) { + return ERR_NOMEM; /* PRQA S 2880 # MISRA 2.1 - Unreachable code due to configuration option being set/unset */ + } + ST_MEMMOVE(&apduParam->cApduBuf->apdu[hdrLen], apduParam->cApduBuf->apdu, apduParam->Lc); + } + + /* Prepend the ADPDU's header */ + apduParam->cApduBuf->apdu[msgIt++] = apduParam->CLA; + apduParam->cApduBuf->apdu[msgIt++] = apduParam->INS; + apduParam->cApduBuf->apdu[msgIt++] = apduParam->P1; + apduParam->cApduBuf->apdu[msgIt++] = apduParam->P2; + + /* Check if Data field length is to be added */ + if(apduParam->LcFlag) { + apduParam->cApduBuf->apdu[msgIt++] = apduParam->Lc; + msgIt += apduParam->Lc; + } + + /* Check if Expected Response Length is to be added */ + if(apduParam->LeFlag) { + apduParam->cApduBuf->apdu[msgIt++] = apduParam->Le; + } + + *(apduParam->cApduLen) = msgIt; + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalT4TPollerParseRAPDU(rfalT4tRApduParam* apduParam) { + if((apduParam == NULL) || (apduParam->rApduBuf == NULL)) { + return ERR_PARAM; + } + + if(apduParam->rcvdLen < RFAL_T4T_MAX_RAPDU_SW1SW2_LEN) { + return ERR_PROTO; + } + + apduParam->rApduBodyLen = (apduParam->rcvdLen - (uint16_t)RFAL_T4T_MAX_RAPDU_SW1SW2_LEN); + apduParam->statusWord = GETU16((&apduParam->rApduBuf->apdu[apduParam->rApduBodyLen])); + + /* Check SW1 SW2 T4T 1.0 5.1.3 NOTE */ + if(apduParam->statusWord == RFAL_T4T_ISO7816_STATUS_COMPLETE) { + return ERR_NONE; + } + + return ERR_REQUEST; +} + +/*******************************************************************************/ +ReturnCode rfalT4TPollerComposeSelectAppl( + rfalIsoDepApduBufFormat* cApduBuf, + const uint8_t* aid, + uint8_t aidLen, + uint16_t* cApduLen) { + rfalT4tCApduParam cAPDU; + + /* CLA INS P1 P2 Lc Data Le */ + /* 00h A4h 00h 00h 07h AID 00h */ + cAPDU.CLA = RFAL_T4T_CLA; + cAPDU.INS = (uint8_t)RFAL_T4T_INS_SELECT; + cAPDU.P1 = RFAL_T4T_ISO7816_P1_SELECT_BY_DF_NAME; + cAPDU.P2 = RFAL_T4T_ISO7816_P2_SELECT_FIRST_OR_ONLY_OCCURENCE | + RFAL_T4T_ISO7816_P2_SELECT_RETURN_FCI_TEMPLATE; + cAPDU.Lc = aidLen; + cAPDU.Le = 0x00; + cAPDU.LcFlag = true; + cAPDU.LeFlag = true; + cAPDU.cApduBuf = cApduBuf; + cAPDU.cApduLen = cApduLen; + + if(aidLen > 0U) { + ST_MEMCPY(cAPDU.cApduBuf->apdu, aid, aidLen); + } + + return rfalT4TPollerComposeCAPDU(&cAPDU); +} + +/*******************************************************************************/ +ReturnCode rfalT4TPollerComposeSelectFile( + rfalIsoDepApduBufFormat* cApduBuf, + const uint8_t* fid, + uint8_t fidLen, + uint16_t* cApduLen) { + rfalT4tCApduParam cAPDU; + + /* CLA INS P1 P2 Lc Data Le */ + /* 00h A4h 00h 0Ch 02h FID - */ + cAPDU.CLA = RFAL_T4T_CLA; + cAPDU.INS = (uint8_t)RFAL_T4T_INS_SELECT; + cAPDU.P1 = RFAL_T4T_ISO7816_P1_SELECT_BY_FILEID; + cAPDU.P2 = RFAL_T4T_ISO7816_P2_SELECT_FIRST_OR_ONLY_OCCURENCE | + RFAL_T4T_ISO7816_P2_SELECT_NO_RESPONSE_DATA; + cAPDU.Lc = fidLen; + cAPDU.Le = 0x00; + cAPDU.LcFlag = true; + cAPDU.LeFlag = false; + cAPDU.cApduBuf = cApduBuf; + cAPDU.cApduLen = cApduLen; + + if(fidLen > 0U) { + ST_MEMCPY(cAPDU.cApduBuf->apdu, fid, fidLen); + } + + return rfalT4TPollerComposeCAPDU(&cAPDU); +} + +/*******************************************************************************/ +ReturnCode rfalT4TPollerComposeSelectFileV1Mapping( + rfalIsoDepApduBufFormat* cApduBuf, + const uint8_t* fid, + uint8_t fidLen, + uint16_t* cApduLen) { + rfalT4tCApduParam cAPDU; + + /* CLA INS P1 P2 Lc Data Le */ + /* 00h A4h 00h 00h 02h FID - */ + cAPDU.CLA = RFAL_T4T_CLA; + cAPDU.INS = (uint8_t)RFAL_T4T_INS_SELECT; + cAPDU.P1 = RFAL_T4T_ISO7816_P1_SELECT_BY_FILEID; + cAPDU.P2 = RFAL_T4T_ISO7816_P2_SELECT_FIRST_OR_ONLY_OCCURENCE | + RFAL_T4T_ISO7816_P2_SELECT_RETURN_FCI_TEMPLATE; + cAPDU.Lc = fidLen; + cAPDU.Le = 0x00; + cAPDU.LcFlag = true; + cAPDU.LeFlag = false; + cAPDU.cApduBuf = cApduBuf; + cAPDU.cApduLen = cApduLen; + + if(fidLen > 0U) { + ST_MEMCPY(cAPDU.cApduBuf->apdu, fid, fidLen); + } + + return rfalT4TPollerComposeCAPDU(&cAPDU); +} + +/*******************************************************************************/ +ReturnCode rfalT4TPollerComposeReadData( + rfalIsoDepApduBufFormat* cApduBuf, + uint16_t offset, + uint8_t expLen, + uint16_t* cApduLen) { + rfalT4tCApduParam cAPDU; + + /* CLA INS P1 P2 Lc Data Le */ + /* 00h B0h [Offset] - - len */ + cAPDU.CLA = RFAL_T4T_CLA; + cAPDU.INS = (uint8_t)RFAL_T4T_INS_READBINARY; + cAPDU.P1 = (uint8_t)((offset >> 8U) & 0xFFU); + cAPDU.P2 = (uint8_t)((offset >> 0U) & 0xFFU); + cAPDU.Le = expLen; + cAPDU.LcFlag = false; + cAPDU.LeFlag = true; + cAPDU.cApduBuf = cApduBuf; + cAPDU.cApduLen = cApduLen; + + return rfalT4TPollerComposeCAPDU(&cAPDU); +} + +/*******************************************************************************/ +ReturnCode rfalT4TPollerComposeReadDataODO( + rfalIsoDepApduBufFormat* cApduBuf, + uint32_t offset, + uint8_t expLen, + uint16_t* cApduLen) { + rfalT4tCApduParam cAPDU; + uint8_t dataIt; + + /* CLA INS P1 P2 Lc Data Le */ + /* 00h B1h 00h 00h Lc 54 03 xxyyzz len */ + /* [Offset] */ + cAPDU.CLA = RFAL_T4T_CLA; + cAPDU.INS = (uint8_t)RFAL_T4T_INS_READBINARY_ODO; + cAPDU.P1 = 0x00U; + cAPDU.P2 = 0x00U; + cAPDU.Le = expLen; + cAPDU.LcFlag = true; + cAPDU.LeFlag = true; + cAPDU.cApduBuf = cApduBuf; + cAPDU.cApduLen = cApduLen; + + dataIt = 0U; + cApduBuf->apdu[dataIt++] = RFAL_T4T_OFFSET_DO; + cApduBuf->apdu[dataIt++] = RFAL_T4T_LENGTH_DO; + cApduBuf->apdu[dataIt++] = (uint8_t)(offset >> 16U); + cApduBuf->apdu[dataIt++] = (uint8_t)(offset >> 8U); + cApduBuf->apdu[dataIt++] = (uint8_t)(offset); + cAPDU.Lc = dataIt; + + return rfalT4TPollerComposeCAPDU(&cAPDU); +} + +/*******************************************************************************/ +ReturnCode rfalT4TPollerComposeWriteData( + rfalIsoDepApduBufFormat* cApduBuf, + uint16_t offset, + const uint8_t* data, + uint8_t dataLen, + uint16_t* cApduLen) { + rfalT4tCApduParam cAPDU; + + /* CLA INS P1 P2 Lc Data Le */ + /* 00h D6h [Offset] len Data - */ + cAPDU.CLA = RFAL_T4T_CLA; + cAPDU.INS = (uint8_t)RFAL_T4T_INS_UPDATEBINARY; + cAPDU.P1 = (uint8_t)((offset >> 8U) & 0xFFU); + cAPDU.P2 = (uint8_t)((offset >> 0U) & 0xFFU); + cAPDU.Lc = dataLen; + cAPDU.LcFlag = true; + cAPDU.LeFlag = false; + cAPDU.cApduBuf = cApduBuf; + cAPDU.cApduLen = cApduLen; + + if(dataLen > 0U) { + ST_MEMCPY(cAPDU.cApduBuf->apdu, data, dataLen); + } + + return rfalT4TPollerComposeCAPDU(&cAPDU); +} + +/*******************************************************************************/ +ReturnCode rfalT4TPollerComposeWriteDataODO( + rfalIsoDepApduBufFormat* cApduBuf, + uint32_t offset, + const uint8_t* data, + uint8_t dataLen, + uint16_t* cApduLen) { + rfalT4tCApduParam cAPDU; + uint8_t dataIt; + + /* CLA INS P1 P2 Lc Data Le */ + /* 00h D7h 00h 00h len 54 03 xxyyzz 53 Ld data - */ + /* [offset] [data] */ + cAPDU.CLA = RFAL_T4T_CLA; + cAPDU.INS = (uint8_t)RFAL_T4T_INS_UPDATEBINARY_ODO; + cAPDU.P1 = 0x00U; + cAPDU.P2 = 0x00U; + cAPDU.LcFlag = true; + cAPDU.LeFlag = false; + cAPDU.cApduBuf = cApduBuf; + cAPDU.cApduLen = cApduLen; + + dataIt = 0U; + cApduBuf->apdu[dataIt++] = RFAL_T4T_OFFSET_DO; + cApduBuf->apdu[dataIt++] = RFAL_T4T_LENGTH_DO; + cApduBuf->apdu[dataIt++] = (uint8_t)(offset >> 16U); + cApduBuf->apdu[dataIt++] = (uint8_t)(offset >> 8U); + cApduBuf->apdu[dataIt++] = (uint8_t)(offset); + cApduBuf->apdu[dataIt++] = RFAL_T4T_DATA_DO; + cApduBuf->apdu[dataIt++] = dataLen; + + if((((uint32_t)dataLen + (uint32_t)dataIt) >= RFAL_T4T_MAX_LC) || + (((uint32_t)dataLen + (uint32_t)dataIt) >= RFAL_FEATURE_ISO_DEP_APDU_MAX_LEN)) { + return (ERR_NOMEM); + } + + if(dataLen > 0U) { + ST_MEMCPY(&cAPDU.cApduBuf->apdu[dataIt], data, dataLen); + } + dataIt += dataLen; + cAPDU.Lc = dataIt; + + return rfalT4TPollerComposeCAPDU(&cAPDU); +} + +#endif /* RFAL_FEATURE_T4T */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/rfal_analogConfigTbl.h b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/rfal_analogConfigTbl.h new file mode 100644 index 00000000000..533e86592aa --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/rfal_analogConfigTbl.h @@ -0,0 +1,1487 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file rfal_analogConfig.h + * + * \author bkam + * + * \brief ST25R3916 Analog Configuration Settings + * + */ + +#ifndef ST25R3916_ANALOGCONFIG_H +#define ST25R3916_ANALOGCONFIG_H + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "../../include/rfal_analogConfig.h" +#include "st25r3916_com.h" + +/* + ****************************************************************************** + * DEFINES + ****************************************************************************** + */ + +/* + ****************************************************************************** + * GLOBAL MACROS + ****************************************************************************** + */ + +/*! Macro for Configuration Setting with only one register-mask-value set: + * - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1] */ +#define MODE_ENTRY_1_REG(MODE, R0, M0, V0) \ + (uint8_t)((uint16_t)(MODE) >> 8U), (uint8_t)((MODE) & 0xFFU), 1, \ + (uint8_t)((uint16_t)(R0) >> 8U), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0) + +/*! Macro for Configuration Setting with only two register-mask-value sets: + * - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1] */ +#define MODE_ENTRY_2_REG(MODE, R0, M0, V0, R1, M1, V1) \ + (uint8_t)((uint16_t)(MODE) >> 8U), (uint8_t)((MODE) & 0xFFU), 2, \ + (uint8_t)((uint16_t)(R0) >> 8U), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0), \ + (uint8_t)((uint16_t)(R1) >> 8U), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1) + +/*! Macro for Configuration Setting with only three register-mask-value sets: + * - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */ +#define MODE_ENTRY_3_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2) \ + (uint8_t)((uint16_t)(MODE) >> 8U), (uint8_t)((MODE) & 0xFFU), 3, \ + (uint8_t)((uint16_t)(R0) >> 8U), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0), \ + (uint8_t)((uint16_t)(R1) >> 8U), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1), \ + (uint8_t)((uint16_t)(R2) >> 8U), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2) + +/*! Macro for Configuration Setting with only four register-mask-value sets: + * - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */ +#define MODE_ENTRY_4_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3) \ + (uint8_t)((uint16_t)(MODE) >> 8U), (uint8_t)((MODE) & 0xFFU), 4, \ + (uint8_t)((uint16_t)(R0) >> 8U), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0), \ + (uint8_t)((uint16_t)(R1) >> 8U), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1), \ + (uint8_t)((uint16_t)(R2) >> 8U), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2), \ + (uint8_t)((uint16_t)(R3) >> 8U), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3) + +/*! Macro for Configuration Setting with only five register-mask-value sets: + * - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */ +#define MODE_ENTRY_5_REG(MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3, R4, M4, V4) \ + (uint8_t)((uint16_t)(MODE) >> 8U), (uint8_t)((MODE) & 0xFFU), 5, \ + (uint8_t)((uint16_t)(R0) >> 8U), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0), \ + (uint8_t)((uint16_t)(R1) >> 8U), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1), \ + (uint8_t)((uint16_t)(R2) >> 8U), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2), \ + (uint8_t)((uint16_t)(R3) >> 8U), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3), \ + (uint8_t)((uint16_t)(R4) >> 8U), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4) + +/*! Macro for Configuration Setting with only six register-mask-value sets: + * - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */ +#define MODE_ENTRY_6_REG( \ + MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3, R4, M4, V4, R5, M5, V5) \ + (uint8_t)((uint16_t)(MODE) >> 8U), (uint8_t)((MODE) & 0xFFU), 6, \ + (uint8_t)((uint16_t)(R0) >> 8U), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0), \ + (uint8_t)((uint16_t)(R1) >> 8U), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1), \ + (uint8_t)((uint16_t)(R2) >> 8U), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2), \ + (uint8_t)((uint16_t)(R3) >> 8U), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3), \ + (uint8_t)((uint16_t)(R4) >> 8U), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4), \ + (uint8_t)((uint16_t)(R5) >> 8U), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5) + +/*! Macro for Configuration Setting with only seven register-mask-value sets: + * - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */ +#define MODE_ENTRY_7_REG( \ + MODE, R0, M0, V0, R1, M1, V1, R2, M2, V2, R3, M3, V3, R4, M4, V4, R5, M5, V5, R6, M6, V6) \ + (uint8_t)((uint16_t)(MODE) >> 8U), (uint8_t)((MODE) & 0xFFU), 7, \ + (uint8_t)((uint16_t)(R0) >> 8U), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0), \ + (uint8_t)((uint16_t)(R1) >> 8U), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1), \ + (uint8_t)((uint16_t)(R2) >> 8U), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2), \ + (uint8_t)((uint16_t)(R3) >> 8U), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3), \ + (uint8_t)((uint16_t)(R4) >> 8U), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4), \ + (uint8_t)((uint16_t)(R5) >> 8U), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5), \ + (uint8_t)((uint16_t)(R6) >> 8U), (uint8_t)((R6) & 0xFFU), (uint8_t)(M6), (uint8_t)(V6) + +/*! Macro for Configuration Setting with only eight register-mask-value sets: + * - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */ +#define MODE_ENTRY_8_REG( \ + MODE, \ + R0, \ + M0, \ + V0, \ + R1, \ + M1, \ + V1, \ + R2, \ + M2, \ + V2, \ + R3, \ + M3, \ + V3, \ + R4, \ + M4, \ + V4, \ + R5, \ + M5, \ + V5, \ + R6, \ + M6, \ + V6, \ + R7, \ + M7, \ + V7) \ + (uint8_t)((uint16_t)(MODE) >> 8U), (uint8_t)((MODE) & 0xFFU), 8, \ + (uint8_t)((uint16_t)(R0) >> 8U), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0), \ + (uint8_t)((uint16_t)(R1) >> 8U), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1), \ + (uint8_t)((uint16_t)(R2) >> 8U), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2), \ + (uint8_t)((uint16_t)(R3) >> 8U), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3), \ + (uint8_t)((uint16_t)(R4) >> 8U), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4), \ + (uint8_t)((uint16_t)(R5) >> 8U), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5), \ + (uint8_t)((uint16_t)(R6) >> 8U), (uint8_t)((R6) & 0xFFU), (uint8_t)(M6), (uint8_t)(V6), \ + (uint8_t)((uint16_t)(R7) >> 8U), (uint8_t)((R7) & 0xFFU), (uint8_t)(M7), (uint8_t)(V7) + +/*! Macro for Configuration Setting with only nine register-mask-value sets: + * - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */ +#define MODE_ENTRY_9_REG( \ + MODE, \ + R0, \ + M0, \ + V0, \ + R1, \ + M1, \ + V1, \ + R2, \ + M2, \ + V2, \ + R3, \ + M3, \ + V3, \ + R4, \ + M4, \ + V4, \ + R5, \ + M5, \ + V5, \ + R6, \ + M6, \ + V6, \ + R7, \ + M7, \ + V7, \ + R8, \ + M8, \ + V8) \ + (uint8_t)((uint16_t)(MODE) >> 8U), (uint8_t)((MODE) & 0xFFU), 9, \ + (uint8_t)((uint16_t)(R0) >> 8U), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0), \ + (uint8_t)((uint16_t)(R1) >> 8U), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1), \ + (uint8_t)((uint16_t)(R2) >> 8U), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2), \ + (uint8_t)((uint16_t)(R3) >> 8U), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3), \ + (uint8_t)((uint16_t)(R4) >> 8U), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4), \ + (uint8_t)((uint16_t)(R5) >> 8U), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5), \ + (uint8_t)((uint16_t)(R6) >> 8U), (uint8_t)((R6) & 0xFFU), (uint8_t)(M6), (uint8_t)(V6), \ + (uint8_t)((uint16_t)(R7) >> 8U), (uint8_t)((R7) & 0xFFU), (uint8_t)(M7), (uint8_t)(V7), \ + (uint8_t)((uint16_t)(R8) >> 8U), (uint8_t)((R8) & 0xFFU), (uint8_t)(M8), (uint8_t)(V8) + +/*! Macro for Configuration Setting with only ten register-mask-value sets: + * - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */ +#define MODE_ENTRY_10_REG( \ + MODE, \ + R0, \ + M0, \ + V0, \ + R1, \ + M1, \ + V1, \ + R2, \ + M2, \ + V2, \ + R3, \ + M3, \ + V3, \ + R4, \ + M4, \ + V4, \ + R5, \ + M5, \ + V5, \ + R6, \ + M6, \ + V6, \ + R7, \ + M7, \ + V7, \ + R8, \ + M8, \ + V8, \ + R9, \ + M9, \ + V9) \ + (uint8_t)((uint16_t)(MODE) >> 8U), (uint8_t)((MODE) & 0xFFU), 10, \ + (uint8_t)((uint16_t)(R0) >> 8U), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0), \ + (uint8_t)((uint16_t)(R1) >> 8U), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1), \ + (uint8_t)((uint16_t)(R2) >> 8U), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2), \ + (uint8_t)((uint16_t)(R3) >> 8U), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3), \ + (uint8_t)((uint16_t)(R4) >> 8U), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4), \ + (uint8_t)((uint16_t)(R5) >> 8U), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5), \ + (uint8_t)((uint16_t)(R6) >> 8U), (uint8_t)((R6) & 0xFFU), (uint8_t)(M6), (uint8_t)(V6), \ + (uint8_t)((uint16_t)(R7) >> 8U), (uint8_t)((R7) & 0xFFU), (uint8_t)(M7), (uint8_t)(V7), \ + (uint8_t)((uint16_t)(R8) >> 8U), (uint8_t)((R8) & 0xFFU), (uint8_t)(M8), (uint8_t)(V8), \ + (uint8_t)((uint16_t)(R9) >> 8U), (uint8_t)((R9) & 0xFFU), (uint8_t)(M9), (uint8_t)(V9) + +/*! Macro for Configuration Setting with eleven register-mask-value sets: + * - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */ +#define MODE_ENTRY_11_REG( \ + MODE, \ + R0, \ + M0, \ + V0, \ + R1, \ + M1, \ + V1, \ + R2, \ + M2, \ + V2, \ + R3, \ + M3, \ + V3, \ + R4, \ + M4, \ + V4, \ + R5, \ + M5, \ + V5, \ + R6, \ + M6, \ + V6, \ + R7, \ + M7, \ + V7, \ + R8, \ + M8, \ + V8, \ + R9, \ + M9, \ + V9, \ + R10, \ + M10, \ + V10) \ + (uint8_t)((uint16_t)(MODE) >> 8U), (uint8_t)((MODE) & 0xFFU), 11, \ + (uint8_t)((uint16_t)(R0) >> 8U), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0), \ + (uint8_t)((uint16_t)(R1) >> 8U), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1), \ + (uint8_t)((uint16_t)(R2) >> 8U), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2), \ + (uint8_t)((uint16_t)(R3) >> 8U), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3), \ + (uint8_t)((uint16_t)(R4) >> 8U), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4), \ + (uint8_t)((uint16_t)(R5) >> 8U), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5), \ + (uint8_t)((uint16_t)(R6) >> 8U), (uint8_t)((R6) & 0xFFU), (uint8_t)(M6), (uint8_t)(V6), \ + (uint8_t)((uint16_t)(R7) >> 8U), (uint8_t)((R7) & 0xFFU), (uint8_t)(M7), (uint8_t)(V7), \ + (uint8_t)((uint16_t)(R8) >> 8U), (uint8_t)((R8) & 0xFFU), (uint8_t)(M8), (uint8_t)(V8), \ + (uint8_t)((uint16_t)(R9) >> 8U), (uint8_t)((R9) & 0xFFU), (uint8_t)(M9), (uint8_t)(V9), \ + (uint8_t)((uint16_t)(R10) >> 8U), (uint8_t)((R10) & 0xFFU), (uint8_t)(M10), \ + (uint8_t)(V10) + +/*! Macro for Configuration Setting with twelve register-mask-value sets: + * - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */ +#define MODE_ENTRY_12_REG( \ + MODE, \ + R0, \ + M0, \ + V0, \ + R1, \ + M1, \ + V1, \ + R2, \ + M2, \ + V2, \ + R3, \ + M3, \ + V3, \ + R4, \ + M4, \ + V4, \ + R5, \ + M5, \ + V5, \ + R6, \ + M6, \ + V6, \ + R7, \ + M7, \ + V7, \ + R8, \ + M8, \ + V8, \ + R9, \ + M9, \ + V9, \ + R10, \ + M10, \ + V10, \ + R11, \ + M11, \ + V11) \ + (uint8_t)((uint16_t)(MODE) >> 8U), (uint8_t)((MODE) & 0xFFU), 12, \ + (uint8_t)((uint16_t)(R0) >> 8U), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0), \ + (uint8_t)((uint16_t)(R1) >> 8U), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1), \ + (uint8_t)((uint16_t)(R2) >> 8U), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2), \ + (uint8_t)((uint16_t)(R3) >> 8U), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3), \ + (uint8_t)((uint16_t)(R4) >> 8U), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4), \ + (uint8_t)((uint16_t)(R5) >> 8U), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5), \ + (uint8_t)((uint16_t)(R6) >> 8U), (uint8_t)((R6) & 0xFFU), (uint8_t)(M6), (uint8_t)(V6), \ + (uint8_t)((uint16_t)(R7) >> 8U), (uint8_t)((R7) & 0xFFU), (uint8_t)(M7), (uint8_t)(V7), \ + (uint8_t)((uint16_t)(R8) >> 8U), (uint8_t)((R8) & 0xFFU), (uint8_t)(M8), (uint8_t)(V8), \ + (uint8_t)((uint16_t)(R9) >> 8U), (uint8_t)((R9) & 0xFFU), (uint8_t)(M9), (uint8_t)(V9), \ + (uint8_t)((uint16_t)(R10) >> 8U), (uint8_t)((R10) & 0xFFU), (uint8_t)(M10), \ + (uint8_t)(V10), (uint8_t)((uint16_t)(R11) >> 8U), (uint8_t)((R11) & 0xFFU), \ + (uint8_t)(M11), (uint8_t)(V11) + +/*! Macro for Configuration Setting with thirteen register-mask-value sets: + * - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */ +#define MODE_ENTRY_13_REG( \ + MODE, \ + R0, \ + M0, \ + V0, \ + R1, \ + M1, \ + V1, \ + R2, \ + M2, \ + V2, \ + R3, \ + M3, \ + V3, \ + R4, \ + M4, \ + V4, \ + R5, \ + M5, \ + V5, \ + R6, \ + M6, \ + V6, \ + R7, \ + M7, \ + V7, \ + R8, \ + M8, \ + V8, \ + R9, \ + M9, \ + V9, \ + R10, \ + M10, \ + V10, \ + R11, \ + M11, \ + V11, \ + R12, \ + M12, \ + V12) \ + (uint8_t)((uint16_t)(MODE) >> 8U), (uint8_t)((MODE) & 0xFFU), 13, \ + (uint8_t)((uint16_t)(R0) >> 8U), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0), \ + (uint8_t)((uint16_t)(R1) >> 8U), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1), \ + (uint8_t)((uint16_t)(R2) >> 8U), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2), \ + (uint8_t)((uint16_t)(R3) >> 8U), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3), \ + (uint8_t)((uint16_t)(R4) >> 8U), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4), \ + (uint8_t)((uint16_t)(R5) >> 8U), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5), \ + (uint8_t)((uint16_t)(R6) >> 8U), (uint8_t)((R6) & 0xFFU), (uint8_t)(M6), (uint8_t)(V6), \ + (uint8_t)((uint16_t)(R7) >> 8U), (uint8_t)((R7) & 0xFFU), (uint8_t)(M7), (uint8_t)(V7), \ + (uint8_t)((uint16_t)(R8) >> 8U), (uint8_t)((R8) & 0xFFU), (uint8_t)(M8), (uint8_t)(V8), \ + (uint8_t)((uint16_t)(R9) >> 8U), (uint8_t)((R9) & 0xFFU), (uint8_t)(M9), (uint8_t)(V9), \ + (uint8_t)((uint16_t)(R10) >> 8U), (uint8_t)((R10) & 0xFFU), (uint8_t)(M10), \ + (uint8_t)(V10), (uint8_t)((uint16_t)(R11) >> 8U), (uint8_t)((R11) & 0xFFU), \ + (uint8_t)(M11), (uint8_t)(V11), (uint8_t)((uint16_t)(R12) >> 8U), \ + (uint8_t)((R12) & 0xFFU), (uint8_t)(M12), (uint8_t)(V12) + +/*! Macro for Configuration Setting with fourteen register-mask-value sets: + * - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */ +#define MODE_ENTRY_14_REG( \ + MODE, \ + R0, \ + M0, \ + V0, \ + R1, \ + M1, \ + V1, \ + R2, \ + M2, \ + V2, \ + R3, \ + M3, \ + V3, \ + R4, \ + M4, \ + V4, \ + R5, \ + M5, \ + V5, \ + R6, \ + M6, \ + V6, \ + R7, \ + M7, \ + V7, \ + R8, \ + M8, \ + V8, \ + R9, \ + M9, \ + V9, \ + R10, \ + M10, \ + V10, \ + R11, \ + M11, \ + V11, \ + R12, \ + M12, \ + V12, \ + R13, \ + M13, \ + V13, \ + R14, \ + M14, \ + V14, \ + R15, \ + M15, \ + V15) \ + (uint8_t)((uint16_t)(MODE) >> 8), (uint8_t)((MODE) & 0xFFU), 14, \ + (uint8_t)((uint16_t)(R0) >> 8), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0), \ + (uint8_t)((uint16_t)(R1) >> 8), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1), \ + (uint8_t)((uint16_t)(R2) >> 8), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2), \ + (uint8_t)((uint16_t)(R3) >> 8), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3), \ + (uint8_t)((uint16_t)(R4) >> 8), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4), \ + (uint8_t)((uint16_t)(R5) >> 8), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5), \ + (uint8_t)((uint16_t)(R6) >> 8), (uint8_t)((R6) & 0xFFU), (uint8_t)(M6), (uint8_t)(V6), \ + (uint8_t)((uint16_t)(R7) >> 8), (uint8_t)((R7) & 0xFFU), (uint8_t)(M7), (uint8_t)(V7), \ + (uint8_t)((uint16_t)(R8) >> 8), (uint8_t)((R8) & 0xFFU), (uint8_t)(M8), (uint8_t)(V8), \ + (uint8_t)((uint16_t)(R9) >> 8), (uint8_t)((R9) & 0xFFU), (uint8_t)(M9), (uint8_t)(V9), \ + (uint8_t)((uint16_t)(R10) >> 8), (uint8_t)((R10) & 0xFFU), (uint8_t)(M10), \ + (uint8_t)(V10), (uint8_t)((uint16_t)(R11) >> 8), (uint8_t)((R11) & 0xFFU), \ + (uint8_t)(M11), (uint8_t)(V11), (uint8_t)((uint16_t)(R12) >> 8), \ + (uint8_t)((R12) & 0xFFU), (uint8_t)(M12), (uint8_t)(V12), \ + (uint8_t)((uint16_t)(R13) >> 8), (uint8_t)((R13) & 0xFFU), (uint8_t)(M13), (uint8_t)(V13) + +/*! Macro for Configuration Setting with fifteen register-mask-value sets: + * - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */ +#define MODE_ENTRY_15_REG( \ + MODE, \ + R0, \ + M0, \ + V0, \ + R1, \ + M1, \ + V1, \ + R2, \ + M2, \ + V2, \ + R3, \ + M3, \ + V3, \ + R4, \ + M4, \ + V4, \ + R5, \ + M5, \ + V5, \ + R6, \ + M6, \ + V6, \ + R7, \ + M7, \ + V7, \ + R8, \ + M8, \ + V8, \ + R9, \ + M9, \ + V9, \ + R10, \ + M10, \ + V10, \ + R11, \ + M11, \ + V11, \ + R12, \ + M12, \ + V12, \ + R13, \ + M13, \ + V13, \ + R14, \ + M14, \ + V14, \ + R15, \ + M15, \ + V15) \ + (uint8_t)((uint16_t)(MODE) >> 8), (uint8_t)((MODE) & 0xFFU), 15, \ + (uint8_t)((uint16_t)(R0) >> 8), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0), \ + (uint8_t)((uint16_t)(R1) >> 8), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1), \ + (uint8_t)((uint16_t)(R2) >> 8), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2), \ + (uint8_t)((uint16_t)(R3) >> 8), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3), \ + (uint8_t)((uint16_t)(R4) >> 8), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4), \ + (uint8_t)((uint16_t)(R5) >> 8), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5), \ + (uint8_t)((uint16_t)(R6) >> 8), (uint8_t)((R6) & 0xFFU), (uint8_t)(M6), (uint8_t)(V6), \ + (uint8_t)((uint16_t)(R7) >> 8), (uint8_t)((R7) & 0xFFU), (uint8_t)(M7), (uint8_t)(V7), \ + (uint8_t)((uint16_t)(R8) >> 8), (uint8_t)((R8) & 0xFFU), (uint8_t)(M8), (uint8_t)(V8), \ + (uint8_t)((uint16_t)(R9) >> 8), (uint8_t)((R9) & 0xFFU), (uint8_t)(M9), (uint8_t)(V9), \ + (uint8_t)((uint16_t)(R10) >> 8), (uint8_t)((R10) & 0xFFU), (uint8_t)(M10), \ + (uint8_t)(V10), (uint8_t)((uint16_t)(R11) >> 8), (uint8_t)((R11) & 0xFFU), \ + (uint8_t)(M11), (uint8_t)(V11), (uint8_t)((uint16_t)(R12) >> 8), \ + (uint8_t)((R12) & 0xFFU), (uint8_t)(M12), (uint8_t)(V12), \ + (uint8_t)((uint16_t)(R13) >> 8), (uint8_t)((R13) & 0xFFU), (uint8_t)(M13), \ + (uint8_t)(V13), (uint8_t)((uint16_t)(R14) >> 8), (uint8_t)((R14) & 0xFFU), \ + (uint8_t)(M14), (uint8_t)(V14) + +/*! Macro for Configuration Setting with sixteen register-mask-value sets: + * - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */ +#define MODE_ENTRY_16_REG( \ + MODE, \ + R0, \ + M0, \ + V0, \ + R1, \ + M1, \ + V1, \ + R2, \ + M2, \ + V2, \ + R3, \ + M3, \ + V3, \ + R4, \ + M4, \ + V4, \ + R5, \ + M5, \ + V5, \ + R6, \ + M6, \ + V6, \ + R7, \ + M7, \ + V7, \ + R8, \ + M8, \ + V8, \ + R9, \ + M9, \ + V9, \ + R10, \ + M10, \ + V10, \ + R11, \ + M11, \ + V11, \ + R12, \ + M12, \ + V12, \ + R13, \ + M13, \ + V13, \ + R14, \ + M14, \ + V14, \ + R15, \ + M15, \ + V15) \ + (uint8_t)((uint16_t)(MODE) >> 8), (uint8_t)((MODE) & 0xFFU), 16, \ + (uint8_t)((uint16_t)(R0) >> 8), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0), \ + (uint8_t)((uint16_t)(R1) >> 8), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1), \ + (uint8_t)((uint16_t)(R2) >> 8), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2), \ + (uint8_t)((uint16_t)(R3) >> 8), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3), \ + (uint8_t)((uint16_t)(R4) >> 8), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4), \ + (uint8_t)((uint16_t)(R5) >> 8), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5), \ + (uint8_t)((uint16_t)(R6) >> 8), (uint8_t)((R6) & 0xFFU), (uint8_t)(M6), (uint8_t)(V6), \ + (uint8_t)((uint16_t)(R7) >> 8), (uint8_t)((R7) & 0xFFU), (uint8_t)(M7), (uint8_t)(V7), \ + (uint8_t)((uint16_t)(R8) >> 8), (uint8_t)((R8) & 0xFFU), (uint8_t)(M8), (uint8_t)(V8), \ + (uint8_t)((uint16_t)(R9) >> 8), (uint8_t)((R9) & 0xFFU), (uint8_t)(M9), (uint8_t)(V9), \ + (uint8_t)((uint16_t)(R10) >> 8), (uint8_t)((R10) & 0xFFU), (uint8_t)(M10), \ + (uint8_t)(V10), (uint8_t)((uint16_t)(R11) >> 8), (uint8_t)((R11) & 0xFFU), \ + (uint8_t)(M11), (uint8_t)(V11), (uint8_t)((uint16_t)(R12) >> 8), \ + (uint8_t)((R12) & 0xFFU), (uint8_t)(M12), (uint8_t)(V12), \ + (uint8_t)((uint16_t)(R13) >> 8), (uint8_t)((R13) & 0xFFU), (uint8_t)(M13), \ + (uint8_t)(V13), (uint8_t)((uint16_t)(R14) >> 8), (uint8_t)((R14) & 0xFFU), \ + (uint8_t)(M14), (uint8_t)(V14), (uint8_t)((uint16_t)(R15) >> 8), \ + (uint8_t)((R15) & 0xFFU), (uint8_t)(M15), (uint8_t)(V15) + +/*! Macro for Configuration Setting with seventeen register-mask-value sets: + * - Configuration ID[2], Number of Register sets to follow[1], Register[2], Mask[1], Value[1], Register[2], Mask[1], Value[1], Register[2]... */ +#define MODE_ENTRY_17_REG( \ + MODE, \ + R0, \ + M0, \ + V0, \ + R1, \ + M1, \ + V1, \ + R2, \ + M2, \ + V2, \ + R3, \ + M3, \ + V3, \ + R4, \ + M4, \ + V4, \ + R5, \ + M5, \ + V5, \ + R6, \ + M6, \ + V6, \ + R7, \ + M7, \ + V7, \ + R8, \ + M8, \ + V8, \ + R9, \ + M9, \ + V9, \ + R10, \ + M10, \ + V10, \ + R11, \ + M11, \ + V11, \ + R12, \ + M12, \ + V12, \ + R13, \ + M13, \ + V13, \ + R14, \ + M14, \ + V14, \ + R15, \ + M15, \ + V15, \ + R16, \ + M16, \ + V16) \ + (uint8_t)((uint16_t)(MODE) >> 8), (uint8_t)((MODE) & 0xFFU), 17, \ + (uint8_t)((uint16_t)(R0) >> 8), (uint8_t)((R0) & 0xFFU), (uint8_t)(M0), (uint8_t)(V0), \ + (uint8_t)((uint16_t)(R1) >> 8), (uint8_t)((R1) & 0xFFU), (uint8_t)(M1), (uint8_t)(V1), \ + (uint8_t)((uint16_t)(R2) >> 8), (uint8_t)((R2) & 0xFFU), (uint8_t)(M2), (uint8_t)(V2), \ + (uint8_t)((uint16_t)(R3) >> 8), (uint8_t)((R3) & 0xFFU), (uint8_t)(M3), (uint8_t)(V3), \ + (uint8_t)((uint16_t)(R4) >> 8), (uint8_t)((R4) & 0xFFU), (uint8_t)(M4), (uint8_t)(V4), \ + (uint8_t)((uint16_t)(R5) >> 8), (uint8_t)((R5) & 0xFFU), (uint8_t)(M5), (uint8_t)(V5), \ + (uint8_t)((uint16_t)(R6) >> 8), (uint8_t)((R6) & 0xFFU), (uint8_t)(M6), (uint8_t)(V6), \ + (uint8_t)((uint16_t)(R7) >> 8), (uint8_t)((R7) & 0xFFU), (uint8_t)(M7), (uint8_t)(V7), \ + (uint8_t)((uint16_t)(R8) >> 8), (uint8_t)((R8) & 0xFFU), (uint8_t)(M8), (uint8_t)(V8), \ + (uint8_t)((uint16_t)(R9) >> 8), (uint8_t)((R9) & 0xFFU), (uint8_t)(M9), (uint8_t)(V9), \ + (uint8_t)((uint16_t)(R10) >> 8), (uint8_t)((R10) & 0xFFU), (uint8_t)(M10), \ + (uint8_t)(V10), (uint8_t)((uint16_t)(R11) >> 8), (uint8_t)((R11) & 0xFFU), \ + (uint8_t)(M11), (uint8_t)(V11), (uint8_t)((uint16_t)(R12) >> 8), \ + (uint8_t)((R12) & 0xFFU), (uint8_t)(M12), (uint8_t)(V12), \ + (uint8_t)((uint16_t)(R13) >> 8), (uint8_t)((R13) & 0xFFU), (uint8_t)(M13), \ + (uint8_t)(V13), (uint8_t)((uint16_t)(R14) >> 8), (uint8_t)((R14) & 0xFFU), \ + (uint8_t)(M14), (uint8_t)(V14), (uint8_t)((uint16_t)(R15) >> 8), \ + (uint8_t)((R15) & 0xFFU), (uint8_t)(M15), (uint8_t)(V15), \ + (uint8_t)((uint16_t)(R16) >> 8), (uint8_t)((R16) & 0xFFU), (uint8_t)(M16), (uint8_t)(V16) +/* + ****************************************************************************** + * GLOBAL DATA TYPES + ****************************************************************************** + */ +/* PRQA S 3406 1 # MISRA 8.6 - Externally generated table included by the library */ /* PRQA S 1514 1 # MISRA 8.9 - Externally generated table included by the library */ +const uint8_t rfalAnalogConfigDefaultSettings[] = { + + /****** Default Analog Configuration for Chip-Specific Reset ******/ + MODE_ENTRY_17_REG( + (RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_INIT), + ST25R3916_REG_IO_CONF1, + (ST25R3916_REG_IO_CONF1_out_cl_mask | ST25R3916_REG_IO_CONF1_lf_clk_off), + 0x07 /* Disable MCU_CLK */ + , + ST25R3916_REG_IO_CONF2, + (ST25R3916_REG_IO_CONF2_miso_pd1 | ST25R3916_REG_IO_CONF2_miso_pd2), + 0x18 /* SPI Pull downs */ + , + ST25R3916_REG_IO_CONF2, + ST25R3916_REG_IO_CONF2_aat_en, + ST25R3916_REG_IO_CONF2_aat_en /* Enable AAT */ + , + ST25R3916_REG_TX_DRIVER, + ST25R3916_REG_TX_DRIVER_d_res_mask, + 0x00 /* Set RFO resistance Active Tx */ + , + ST25R3916_REG_RES_AM_MOD, + 0xFF, + 0x80 /* Use minimum non-overlap */ + , + ST25R3916_REG_FIELD_THRESHOLD_ACTV, + ST25R3916_REG_FIELD_THRESHOLD_ACTV_trg_mask, + ST25R3916_REG_FIELD_THRESHOLD_ACTV_trg_105mV /* Lower activation threshold (higher than deactivation)*/ + , + ST25R3916_REG_FIELD_THRESHOLD_ACTV, + ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_mask, + ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_105mV /* Lower activation threshold (higher than deactivation)*/ + , + ST25R3916_REG_FIELD_THRESHOLD_DEACTV, + ST25R3916_REG_FIELD_THRESHOLD_DEACTV_trg_mask, + ST25R3916_REG_FIELD_THRESHOLD_DEACTV_trg_75mV /* Lower deactivation threshold */ + , + ST25R3916_REG_FIELD_THRESHOLD_DEACTV, + ST25R3916_REG_FIELD_THRESHOLD_DEACTV_rfe_mask, + ST25R3916_REG_FIELD_THRESHOLD_DEACTV_rfe_75mV /* Lower deactivation threshold */ + , + ST25R3916_REG_AUX_MOD, + ST25R3916_REG_AUX_MOD_lm_ext, + 0x00 /* Disable External Load Modulation */ + , + ST25R3916_REG_AUX_MOD, + ST25R3916_REG_AUX_MOD_lm_dri, + ST25R3916_REG_AUX_MOD_lm_dri /* Use internal Load Modulation */ + , + ST25R3916_REG_PASSIVE_TARGET, + ST25R3916_REG_PASSIVE_TARGET_fdel_mask, + (5U + << ST25R3916_REG_PASSIVE_TARGET_fdel_shift) /* Adjust the FDT to be aligned with the bitgrid */ + , + ST25R3916_REG_PT_MOD, + (ST25R3916_REG_PT_MOD_ptm_res_mask | ST25R3916_REG_PT_MOD_pt_res_mask), + 0x5f /* Reduce RFO resistance in Modulated state */ + , + ST25R3916_REG_EMD_SUP_CONF, + ST25R3916_REG_EMD_SUP_CONF_rx_start_emv, + ST25R3916_REG_EMD_SUP_CONF_rx_start_emv_on /* Enable start on first 4 bits */ + , + ST25R3916_REG_ANT_TUNE_A, + 0xFF, + 0x82 /* Set Antenna Tuning (Poller): ANTL */ + , + ST25R3916_REG_ANT_TUNE_B, + 0xFF, + 0x82 /* Set Antenna Tuning (Poller): ANTL */ + , + 0x84U, + 0x10, + 0x10 /* Avoid chip internal overheat protection */ + ) + + /****** Default Analog Configuration for Chip-Specific Poll Common ******/ + , + MODE_ENTRY_9_REG( + (RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_POLL_COMMON), + ST25R3916_REG_MODE, + ST25R3916_REG_MODE_tr_am, + ST25R3916_REG_MODE_tr_am_am /* Use AM modulation */ + , + ST25R3916_REG_TX_DRIVER, + ST25R3916_REG_TX_DRIVER_am_mod_mask, + ST25R3916_REG_TX_DRIVER_am_mod_12percent /* Set Modulation index */ + , + ST25R3916_REG_AUX_MOD, + (ST25R3916_REG_AUX_MOD_dis_reg_am | ST25R3916_REG_AUX_MOD_res_am), + 0x00 /* Use AM via regulator */ + , + ST25R3916_REG_ANT_TUNE_A, + 0xFF, + 0x82 /* Set Antenna Tuning (Poller): ANTL */ + , + ST25R3916_REG_ANT_TUNE_B, + 0xFF, + 0x82 /* Set Antenna Tuning (Poller): ANTL */ + , + ST25R3916_REG_OVERSHOOT_CONF1, + 0xFF, + 0x00 /* Disable Overshoot Protection */ + , + ST25R3916_REG_OVERSHOOT_CONF2, + 0xFF, + 0x00 /* Disable Overshoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF1, + 0xFF, + 0x00 /* Disable Undershoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF2, + 0xFF, + 0x00 /* Disable Undershoot Protection */ + ) + + /****** Default Analog Configuration for Poll NFC-A Rx Common ******/ + , + MODE_ENTRY_1_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_AUX, + ST25R3916_REG_AUX_dis_corr, + ST25R3916_REG_AUX_dis_corr_correlator /* Use Correlator Receiver */ + ) + + /****** Default Analog Configuration for Poll NFC-A Tx 106 ******/ + , + MODE_ENTRY_5_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | RFAL_ANALOG_CONFIG_BITRATE_106 | + RFAL_ANALOG_CONFIG_TX), + ST25R3916_REG_MODE, + ST25R3916_REG_MODE_tr_am, + ST25R3916_REG_MODE_tr_am_ook /* Use OOK */ + , + ST25R3916_REG_OVERSHOOT_CONF1, + 0xFF, + 0x40 /* Set default Overshoot Protection */ + , + ST25R3916_REG_OVERSHOOT_CONF2, + 0xFF, + 0x03 /* Set default Overshoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF1, + 0xFF, + 0x40 /* Set default Undershoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF2, + 0xFF, + 0x03 /* Set default Undershoot Protection */ + ) + + /****** Default Analog Configuration for Poll NFC-A Rx 106 ******/ + , + MODE_ENTRY_6_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | RFAL_ANALOG_CONFIG_BITRATE_106 | + RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_RX_CONF1, + 0xFF, + 0x08, + ST25R3916_REG_RX_CONF2, + 0xFF, + 0x2D, + ST25R3916_REG_RX_CONF3, + 0xFF, + 0x00, + ST25R3916_REG_RX_CONF4, + 0xFF, + 0x00, + ST25R3916_REG_CORR_CONF1, + 0xFF, + 0x51, + ST25R3916_REG_CORR_CONF2, + 0xFF, + 0x00) + + /****** Default Analog Configuration for Poll NFC-A Tx 212 ******/ + , + MODE_ENTRY_7_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | RFAL_ANALOG_CONFIG_BITRATE_212 | + RFAL_ANALOG_CONFIG_TX), + ST25R3916_REG_MODE, + ST25R3916_REG_MODE_tr_am, + ST25R3916_REG_MODE_tr_am_am /* Use AM modulation */ + , + ST25R3916_REG_AUX_MOD, + (ST25R3916_REG_AUX_MOD_dis_reg_am | ST25R3916_REG_AUX_MOD_res_am), + 0x88 /* Use Resistive AM */ + , + ST25R3916_REG_RES_AM_MOD, + ST25R3916_REG_RES_AM_MOD_md_res_mask, + 0x7F /* Set Resistive modulation */ + , + ST25R3916_REG_OVERSHOOT_CONF1, + 0xFF, + 0x40 /* Set default Overshoot Protection */ + , + ST25R3916_REG_OVERSHOOT_CONF2, + 0xFF, + 0x03 /* Set default Overshoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF1, + 0xFF, + 0x40 /* Set default Undershoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF2, + 0xFF, + 0x03 /* Set default Undershoot Protection */ + ) + + /****** Default Analog Configuration for Poll NFC-A Rx 212 ******/ + , + MODE_ENTRY_6_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | RFAL_ANALOG_CONFIG_BITRATE_212 | + RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_RX_CONF1, + 0xFF, + 0x02, + ST25R3916_REG_RX_CONF2, + 0xFF, + 0x3D, + ST25R3916_REG_RX_CONF3, + 0xFF, + 0x00, + ST25R3916_REG_RX_CONF4, + 0xFF, + 0x00, + ST25R3916_REG_CORR_CONF1, + 0xFF, + 0x14, + ST25R3916_REG_CORR_CONF2, + 0xFF, + 0x00) + + /****** Default Analog Configuration for Poll NFC-A Tx 424 ******/ + , + MODE_ENTRY_7_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | RFAL_ANALOG_CONFIG_BITRATE_424 | + RFAL_ANALOG_CONFIG_TX), + ST25R3916_REG_MODE, + ST25R3916_REG_MODE_tr_am, + ST25R3916_REG_MODE_tr_am_am /* Use AM modulation */ + , + ST25R3916_REG_AUX_MOD, + (ST25R3916_REG_AUX_MOD_dis_reg_am | ST25R3916_REG_AUX_MOD_res_am), + 0x88 /* Use Resistive AM */ + , + ST25R3916_REG_RES_AM_MOD, + ST25R3916_REG_RES_AM_MOD_md_res_mask, + 0x7F /* Set Resistive modulation */ + , + ST25R3916_REG_OVERSHOOT_CONF1, + 0xFF, + 0x40 /* Set default Overshoot Protection */ + , + ST25R3916_REG_OVERSHOOT_CONF2, + 0xFF, + 0x03 /* Set default Overshoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF1, + 0xFF, + 0x40 /* Set default Undershoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF2, + 0xFF, + 0x03 /* Set default Undershoot Protection */ + ) + + /****** Default Analog Configuration for Poll NFC-A Rx 424 ******/ + , + MODE_ENTRY_6_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | RFAL_ANALOG_CONFIG_BITRATE_424 | + RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_RX_CONF1, + 0xFF, + 0x42, + ST25R3916_REG_RX_CONF2, + 0xFF, + 0x3D, + ST25R3916_REG_RX_CONF3, + 0xFF, + 0x00, + ST25R3916_REG_RX_CONF4, + 0xFF, + 0x00, + ST25R3916_REG_CORR_CONF1, + 0xFF, + 0x54, + ST25R3916_REG_CORR_CONF2, + 0xFF, + 0x00) + + /****** Default Analog Configuration for Poll NFC-A Tx 848 ******/ + , + MODE_ENTRY_7_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | RFAL_ANALOG_CONFIG_BITRATE_848 | + RFAL_ANALOG_CONFIG_TX), + ST25R3916_REG_MODE, + ST25R3916_REG_MODE_tr_am, + ST25R3916_REG_MODE_tr_am_am /* Use AM modulation */ + , + ST25R3916_REG_TX_DRIVER, + ST25R3916_REG_TX_DRIVER_am_mod_mask, + ST25R3916_REG_TX_DRIVER_am_mod_40percent /* Set Modulation index */ + , + ST25R3916_REG_AUX_MOD, + (ST25R3916_REG_AUX_MOD_dis_reg_am | ST25R3916_REG_AUX_MOD_res_am), + 0x00 /* Use AM via regulator */ + , + ST25R3916_REG_OVERSHOOT_CONF1, + 0xFF, + 0x00 /* Disable Overshoot Protection */ + , + ST25R3916_REG_OVERSHOOT_CONF2, + 0xFF, + 0x00 /* Disable Overshoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF1, + 0xFF, + 0x00 /* Disable Undershoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF2, + 0xFF, + 0x00 /* Disable Undershoot Protection */ + ) + + /****** Default Analog Configuration for Poll NFC-A Rx 848 ******/ + , + MODE_ENTRY_6_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | RFAL_ANALOG_CONFIG_BITRATE_848 | + RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_RX_CONF1, + 0xFF, + 0x42, + ST25R3916_REG_RX_CONF2, + 0xFF, + 0x3D, + ST25R3916_REG_RX_CONF3, + 0xFF, + 0x00, + ST25R3916_REG_RX_CONF4, + 0xFF, + 0x00, + ST25R3916_REG_CORR_CONF1, + 0xFF, + 0x44, + ST25R3916_REG_CORR_CONF2, + 0xFF, + 0x00) + + /****** Default Analog Configuration for Poll NFC-A Anticolision setting ******/ + , + MODE_ENTRY_1_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_ANTICOL), + ST25R3916_REG_CORR_CONF1, + ST25R3916_REG_CORR_CONF1_corr_s6, + 0x00 /* Set collision detection level different from data */ + ) + +#ifdef RFAL_USE_COHE + /****** Default Analog Configuration for Poll NFC-B Rx Common ******/ + , + MODE_ENTRY_1_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCB | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_AUX, + ST25R3916_REG_AUX_dis_corr, + ST25R3916_REG_AUX_dis_corr_coherent /* Use Coherent Receiver */ + ) +#else + /****** Default Analog Configuration for Poll NFC-B Rx Common ******/ + , + MODE_ENTRY_1_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCB | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_AUX, + ST25R3916_REG_AUX_dis_corr, + ST25R3916_REG_AUX_dis_corr_correlator /* Use Correlator Receiver */ + ) +#endif /*RFAL_USE_COHE*/ + + /****** Default Analog Configuration for Poll NFC-B Rx 106 ******/ + , + MODE_ENTRY_6_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCB | RFAL_ANALOG_CONFIG_BITRATE_106 | + RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_RX_CONF1, + 0xFF, + 0x04, + ST25R3916_REG_RX_CONF2, + 0xFF, + 0x3D, + ST25R3916_REG_RX_CONF3, + 0xFF, + 0x00, + ST25R3916_REG_RX_CONF4, + 0xFF, + 0x00, + ST25R3916_REG_CORR_CONF1, + 0xFF, + 0x1B, + ST25R3916_REG_CORR_CONF2, + 0xFF, + 0x00) + + /****** Default Analog Configuration for Poll NFC-B Rx 212 ******/ + , + MODE_ENTRY_6_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCB | RFAL_ANALOG_CONFIG_BITRATE_212 | + RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_RX_CONF1, + 0xFF, + 0x02, + ST25R3916_REG_RX_CONF2, + 0xFF, + 0x3D, + ST25R3916_REG_RX_CONF3, + 0xFF, + 0x00, + ST25R3916_REG_RX_CONF4, + 0xFF, + 0x00, + ST25R3916_REG_CORR_CONF1, + 0xFF, + 0x14, + ST25R3916_REG_CORR_CONF2, + 0xFF, + 0x00) + + /****** Default Analog Configuration for Poll NFC-B Rx 424 ******/ + , + MODE_ENTRY_6_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCB | RFAL_ANALOG_CONFIG_BITRATE_424 | + RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_RX_CONF1, + 0xFF, + 0x42, + ST25R3916_REG_RX_CONF2, + 0xFF, + 0x3D, + ST25R3916_REG_RX_CONF3, + 0xFF, + 0x00, + ST25R3916_REG_RX_CONF4, + 0xFF, + 0x00, + ST25R3916_REG_CORR_CONF1, + 0xFF, + 0x54, + ST25R3916_REG_CORR_CONF2, + 0xFF, + 0x00) + + /****** Default Analog Configuration for Poll NFC-B Rx 848 ******/ + , + MODE_ENTRY_6_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCB | RFAL_ANALOG_CONFIG_BITRATE_848 | + RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_RX_CONF1, + 0xFF, + 0x42, + ST25R3916_REG_RX_CONF2, + 0xFF, + 0x3D, + ST25R3916_REG_RX_CONF3, + 0xFF, + 0x00, + ST25R3916_REG_RX_CONF4, + 0xFF, + 0x00, + ST25R3916_REG_CORR_CONF1, + 0xFF, + 0x44, + ST25R3916_REG_CORR_CONF2, + 0xFF, + 0x00) +#ifdef RFAL_USE_COHE + + /****** Default Analog Configuration for Poll NFC-F Rx Common ******/ + , + MODE_ENTRY_7_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCF | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_AUX, + ST25R3916_REG_AUX_dis_corr, + ST25R3916_REG_AUX_dis_corr_coherent /* Use Pulse Receiver */ + , + ST25R3916_REG_RX_CONF1, + 0xFF, + 0x13, + ST25R3916_REG_RX_CONF2, + 0xFF, + 0x3D, + ST25R3916_REG_RX_CONF3, + 0xFF, + 0x00, + ST25R3916_REG_RX_CONF4, + 0xFF, + 0x00, + ST25R3916_REG_CORR_CONF1, + 0xFF, + 0x54, + ST25R3916_REG_CORR_CONF2, + 0xFF, + 0x00) +#else + /****** Default Analog Configuration for Poll NFC-F Rx Common ******/ + , + MODE_ENTRY_7_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCF | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_AUX, + ST25R3916_REG_AUX_dis_corr, + ST25R3916_REG_AUX_dis_corr_correlator /* Use Correlator Receiver */ + , + ST25R3916_REG_RX_CONF1, + 0xFF, + 0x13, + ST25R3916_REG_RX_CONF2, + 0xFF, + 0x3D, + ST25R3916_REG_RX_CONF3, + 0xFF, + 0x00, + ST25R3916_REG_RX_CONF4, + 0xFF, + 0x00, + ST25R3916_REG_CORR_CONF1, + 0xFF, + 0x54, + ST25R3916_REG_CORR_CONF2, + 0xFF, + 0x00) +#endif /*RFAL_USE_COHE*/ + + , + MODE_ENTRY_1_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCV | RFAL_ANALOG_CONFIG_BITRATE_1OF4 | + RFAL_ANALOG_CONFIG_TX), + ST25R3916_REG_MODE, + ST25R3916_REG_MODE_tr_am, + ST25R3916_REG_MODE_tr_am_ook /* Use OOK */ + ) + +#ifdef RFAL_USE_COHE + /****** Default Analog Configuration for Poll NFC-V Rx Common ******/ + , + MODE_ENTRY_7_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCV | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_AUX, + ST25R3916_REG_AUX_dis_corr, + ST25R3916_REG_AUX_dis_corr_coherent /* Use Pulse Receiver */ + , + ST25R3916_REG_RX_CONF1, + 0xFF, + 0x13, + ST25R3916_REG_RX_CONF2, + 0xFF, + 0x2D, + ST25R3916_REG_RX_CONF3, + 0xFF, + 0x00, + ST25R3916_REG_RX_CONF4, + 0xFF, + 0x00, + ST25R3916_REG_CORR_CONF1, + 0xFF, + 0x13, + ST25R3916_REG_CORR_CONF2, + 0xFF, + 0x01) +#else + /****** Default Analog Configuration for Poll NFC-V Rx Common ******/ + , + MODE_ENTRY_7_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCV | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_AUX, + ST25R3916_REG_AUX_dis_corr, + ST25R3916_REG_AUX_dis_corr_correlator /* Use Correlator Receiver */ + , + ST25R3916_REG_RX_CONF1, + 0xFF, + 0x13, + ST25R3916_REG_RX_CONF2, + 0xFF, + 0x2D, + ST25R3916_REG_RX_CONF3, + 0xFF, + 0x00, + ST25R3916_REG_RX_CONF4, + 0xFF, + 0x00, + ST25R3916_REG_CORR_CONF1, + 0xFF, + 0x13, + ST25R3916_REG_CORR_CONF2, + 0xFF, + 0x01) +#endif /*RFAL_USE_COHE*/ + + /****** Default Analog Configuration for Poll AP2P Tx 106 ******/ + , + MODE_ENTRY_5_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_AP2P | RFAL_ANALOG_CONFIG_BITRATE_106 | + RFAL_ANALOG_CONFIG_TX), + ST25R3916_REG_MODE, + ST25R3916_REG_MODE_tr_am, + ST25R3916_REG_MODE_tr_am_ook /* Use OOK modulation */ + , + ST25R3916_REG_OVERSHOOT_CONF1, + 0xFF, + 0x40 /* Set default Overshoot Protection */ + , + ST25R3916_REG_OVERSHOOT_CONF2, + 0xFF, + 0x03 /* Set default Overshoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF1, + 0xFF, + 0x40 /* Set default Undershoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF2, + 0xFF, + 0x03 /* Set default Undershoot Protection */ + ) + + /****** Default Analog Configuration for Poll AP2P Tx 212 ******/ + , + MODE_ENTRY_1_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_AP2P | RFAL_ANALOG_CONFIG_BITRATE_212 | + RFAL_ANALOG_CONFIG_TX), + ST25R3916_REG_MODE, + ST25R3916_REG_MODE_tr_am, + ST25R3916_REG_MODE_tr_am_am /* Use AM modulation */ + ) + + /****** Default Analog Configuration for Poll AP2P Tx 424 ******/ + , + MODE_ENTRY_1_REG( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_AP2P | RFAL_ANALOG_CONFIG_BITRATE_424 | + RFAL_ANALOG_CONFIG_TX), + ST25R3916_REG_MODE, + ST25R3916_REG_MODE_tr_am, + ST25R3916_REG_MODE_tr_am_am /* Use AM modulation */ + ) + + /****** Default Analog Configuration for Chip-Specific Listen On ******/ + , + MODE_ENTRY_6_REG( + (RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_LISTEN_ON), + ST25R3916_REG_ANT_TUNE_A, + 0xFF, + 0x00 /* Set Antenna Tuning (Listener): ANTL */ + , + ST25R3916_REG_ANT_TUNE_B, + 0xFF, + 0xff /* Set Antenna Tuning (Listener): ANTL */ + , + ST25R3916_REG_OVERSHOOT_CONF1, + 0xFF, + 0x00 /* Disable Overshoot Protection */ + , + ST25R3916_REG_OVERSHOOT_CONF2, + 0xFF, + 0x00 /* Disable Overshoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF1, + 0xFF, + 0x00 /* Disable Undershoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF2, + 0xFF, + 0x00 /* Disable Undershoot Protection */ + ) + + /****** Default Analog Configuration for Listen AP2P Tx Common ******/ + , + MODE_ENTRY_7_REG( + (RFAL_ANALOG_CONFIG_LISTEN | RFAL_ANALOG_CONFIG_TECH_AP2P | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_TX), + ST25R3916_REG_ANT_TUNE_A, + 0xFF, + 0x82 /* Set Antenna Tuning (Poller): ANTL */ + , + ST25R3916_REG_ANT_TUNE_B, + 0xFF, + 0x82 /* Set Antenna Tuning (Poller): ANTL */ + , + ST25R3916_REG_TX_DRIVER, + ST25R3916_REG_TX_DRIVER_am_mod_mask, + ST25R3916_REG_TX_DRIVER_am_mod_12percent /* Set Modulation index */ + , + ST25R3916_REG_OVERSHOOT_CONF1, + 0xFF, + 0x00 /* Disable Overshoot Protection */ + , + ST25R3916_REG_OVERSHOOT_CONF2, + 0xFF, + 0x00 /* Disable Overshoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF1, + 0xFF, + 0x00 /* Disable Undershoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF2, + 0xFF, + 0x00 /* Disable Undershoot Protection */ + ) + + /****** Default Analog Configuration for Listen AP2P Rx Common ******/ + , + MODE_ENTRY_3_REG( + (RFAL_ANALOG_CONFIG_LISTEN | RFAL_ANALOG_CONFIG_TECH_AP2P | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX), + ST25R3916_REG_RX_CONF1, + ST25R3916_REG_RX_CONF1_lp_mask, + ST25R3916_REG_RX_CONF1_lp_1200khz /* Set Rx filter configuration */ + , + ST25R3916_REG_RX_CONF1, + ST25R3916_REG_RX_CONF1_hz_mask, + ST25R3916_REG_RX_CONF1_hz_12_200khz /* Set Rx filter configuration */ + , + ST25R3916_REG_RX_CONF2, + ST25R3916_REG_RX_CONF2_amd_sel, + ST25R3916_REG_RX_CONF2_amd_sel_mixer /* AM demodulator: mixer */ + ) + + /****** Default Analog Configuration for Listen AP2P Tx 106 ******/ + , + MODE_ENTRY_5_REG( + (RFAL_ANALOG_CONFIG_LISTEN | RFAL_ANALOG_CONFIG_TECH_AP2P | + RFAL_ANALOG_CONFIG_BITRATE_106 | RFAL_ANALOG_CONFIG_TX), + ST25R3916_REG_MODE, + ST25R3916_REG_MODE_tr_am, + ST25R3916_REG_MODE_tr_am_ook /* Use OOK modulation */ + , + ST25R3916_REG_OVERSHOOT_CONF1, + 0xFF, + 0x40 /* Set default Overshoot Protection */ + , + ST25R3916_REG_OVERSHOOT_CONF2, + 0xFF, + 0x03 /* Set default Overshoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF1, + 0xFF, + 0x40 /* Set default Undershoot Protection */ + , + ST25R3916_REG_UNDERSHOOT_CONF2, + 0xFF, + 0x03 /* Set default Undershoot Protection */ + ) + + /****** Default Analog Configuration for Listen AP2P Tx 212 ******/ + , + MODE_ENTRY_1_REG( + (RFAL_ANALOG_CONFIG_LISTEN | RFAL_ANALOG_CONFIG_TECH_AP2P | + RFAL_ANALOG_CONFIG_BITRATE_212 | RFAL_ANALOG_CONFIG_TX), + ST25R3916_REG_MODE, + ST25R3916_REG_MODE_tr_am, + ST25R3916_REG_MODE_tr_am_am /* Use AM modulation */ + ) + + /****** Default Analog Configuration for Listen AP2P Tx 424 ******/ + , + MODE_ENTRY_1_REG( + (RFAL_ANALOG_CONFIG_LISTEN | RFAL_ANALOG_CONFIG_TECH_AP2P | + RFAL_ANALOG_CONFIG_BITRATE_424 | RFAL_ANALOG_CONFIG_TX), + ST25R3916_REG_MODE, + ST25R3916_REG_MODE_tr_am, + ST25R3916_REG_MODE_tr_am_am /* Use AM modulation */ + ) + +}; + +#endif /* ST25R3916_ANALOGCONFIG_H */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/rfal_dpoTbl.h b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/rfal_dpoTbl.h new file mode 100644 index 00000000000..6d782be2bd9 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/rfal_dpoTbl.h @@ -0,0 +1,68 @@ + +/****************************************************************************** + * @attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * $Revision: $ + * LANGUAGE: ISO C99 + */ + +/*! \file + * + * \author Martin Zechleitner + * + * \brief RF Dynamic Power Table default values + */ + +#ifndef ST25R3916_DPO_H +#define ST25R3916_DPO_H + +/* + ****************************************************************************** + * INCLUDES + ****************************************************************************** + */ +#include "../../include/rfal_dpo.h" + +/* + ****************************************************************************** + * GLOBAL DATA TYPES + ****************************************************************************** + */ + +/*! Default DPO table */ +const uint8_t rfalDpoDefaultSettings[] = { + 0x00, + 255, + 200, + 0x01, + 210, + 150, + 0x02, + 160, + 100, + 0x03, + 110, + 50, +}; + +#endif /* ST25R3916_DPO_H */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/rfal_features.h b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/rfal_features.h new file mode 100644 index 00000000000..3c432a0bc76 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/rfal_features.h @@ -0,0 +1,109 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R391x firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file + * + * \author Gustavo Patricio + * + * \brief RFAL Features/Capabilities Definition for ST25R3916 + */ + +#ifndef RFAL_FEATURES_H +#define RFAL_FEATURES_H + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ +#include "../../platform.h" + +/* +****************************************************************************** +* GLOBAL DEFINES +****************************************************************************** +*/ + +#define RFAL_SUPPORT_MODE_POLL_NFCA true /*!< RFAL Poll NFCA mode support switch */ +#define RFAL_SUPPORT_MODE_POLL_NFCB true /*!< RFAL Poll NFCB mode support switch */ +#define RFAL_SUPPORT_MODE_POLL_NFCF true /*!< RFAL Poll NFCF mode support switch */ +#define RFAL_SUPPORT_MODE_POLL_NFCV true /*!< RFAL Poll NFCV mode support switch */ +#define RFAL_SUPPORT_MODE_POLL_ACTIVE_P2P true /*!< RFAL Poll AP2P mode support switch */ +#define RFAL_SUPPORT_MODE_LISTEN_NFCA true /*!< RFAL Listen NFCA mode support switch */ +#define RFAL_SUPPORT_MODE_LISTEN_NFCB false /*!< RFAL Listen NFCB mode support switch */ +#define RFAL_SUPPORT_MODE_LISTEN_NFCF true /*!< RFAL Listen NFCF mode support switch */ +#define RFAL_SUPPORT_MODE_LISTEN_ACTIVE_P2P true /*!< RFAL Listen AP2P mode support switch */ + +/*******************************************************************************/ +/*! RFAL supported Card Emulation (CE) */ +#define RFAL_SUPPORT_CE \ + (RFAL_SUPPORT_MODE_LISTEN_NFCA || RFAL_SUPPORT_MODE_LISTEN_NFCB || \ + RFAL_SUPPORT_MODE_LISTEN_NFCF) + +/*! RFAL supported Reader/Writer (RW) */ +#define RFAL_SUPPORT_RW \ + (RFAL_SUPPORT_MODE_POLL_NFCA || RFAL_SUPPORT_MODE_POLL_NFCB || RFAL_SUPPORT_MODE_POLL_NFCF || \ + RFAL_SUPPORT_MODE_POLL_NFCV) + +/*! RFAL support for Active P2P (AP2P) */ +#define RFAL_SUPPORT_AP2P \ + (RFAL_SUPPORT_MODE_POLL_ACTIVE_P2P || RFAL_SUPPORT_MODE_LISTEN_ACTIVE_P2P) + +/*******************************************************************************/ +#define RFAL_SUPPORT_BR_RW_106 true /*!< RFAL RW 106 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_RW_212 true /*!< RFAL RW 212 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_RW_424 true /*!< RFAL RW 424 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_RW_848 true /*!< RFAL RW 848 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_RW_1695 false /*!< RFAL RW 1695 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_RW_3390 false /*!< RFAL RW 3390 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_RW_6780 false /*!< RFAL RW 6780 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_RW_13560 false /*!< RFAL RW 6780 Bit Rate support switch */ + +/*******************************************************************************/ +#define RFAL_SUPPORT_BR_AP2P_106 true /*!< RFAL AP2P 106 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_AP2P_212 true /*!< RFAL AP2P 212 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_AP2P_424 true /*!< RFAL AP2P 424 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_AP2P_848 false /*!< RFAL AP2P 848 Bit Rate support switch */ + +/*******************************************************************************/ +#define RFAL_SUPPORT_BR_CE_A_106 true /*!< RFAL CE A 106 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_CE_A_212 false /*!< RFAL CE A 212 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_CE_A_424 false /*!< RFAL CE A 424 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_CE_A_848 false /*!< RFAL CE A 848 Bit Rate support switch */ + +/*******************************************************************************/ +#define RFAL_SUPPORT_BR_CE_B_106 false /*!< RFAL CE B 106 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_CE_B_212 false /*!< RFAL CE B 212 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_CE_B_424 false /*!< RFAL CE B 424 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_CE_B_848 false /*!< RFAL CE B 848 Bit Rate support switch */ + +/*******************************************************************************/ +#define RFAL_SUPPORT_BR_CE_F_212 true /*!< RFAL CE F 212 Bit Rate support switch */ +#define RFAL_SUPPORT_BR_CE_F_424 true /*!< RFAL CE F 424 Bit Rate support switch */ + +#endif /* RFAL_FEATURES_H */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/rfal_rfst25r3916.c b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/rfal_rfst25r3916.c new file mode 100644 index 00000000000..43f1826ce03 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/rfal_rfst25r3916.c @@ -0,0 +1,4857 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R3916 firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file + * + * \author Gustavo Patricio + * + * \brief RF Abstraction Layer (RFAL) + * + * RFAL implementation for ST25R3916 + */ + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ + +#include "../../include/rfal_chip.h" +#include "../../utils.h" +#include "st25r3916.h" +#include "st25r3916_com.h" +#include "st25r3916_irq.h" +#include "../../include/rfal_analogConfig.h" +#include "../../include/rfal_iso15693_2.h" +#include "../../include/rfal_crc.h" + +/* + ****************************************************************************** + * ENABLE SWITCHES + ****************************************************************************** + */ + +#ifndef RFAL_FEATURE_LISTEN_MODE +#define RFAL_FEATURE_LISTEN_MODE false /* Listen Mode configuration missing. Disabled by default */ +#endif /* RFAL_FEATURE_LISTEN_MODE */ + +#ifndef RFAL_FEATURE_WAKEUP_MODE +#define RFAL_FEATURE_WAKEUP_MODE \ + false /* Wake-Up mode configuration missing. Disabled by default */ +#endif /* RFAL_FEATURE_WAKEUP_MODE */ + +#ifndef RFAL_FEATURE_LOWPOWER_MODE +#define RFAL_FEATURE_LOWPOWER_MODE \ + false /* Low Power mode configuration missing. Disabled by default */ +#endif /* RFAL_FEATURE_LOWPOWER_MODE */ + +/* +****************************************************************************** +* GLOBAL TYPES +****************************************************************************** +*/ + +/*! Struct that holds all involved on a Transceive including the context passed by the caller */ +typedef struct { + rfalTransceiveState state; /*!< Current transceive state */ + rfalTransceiveState lastState; /*!< Last transceive state (debug purposes) */ + ReturnCode status; /*!< Current status/error of the transceive */ + + rfalTransceiveContext ctx; /*!< The transceive context given by the caller */ +} rfalTxRx; + +/*! Struct that holds all context for the Listen Mode */ +typedef struct { + rfalLmState state; /*!< Current Listen Mode state */ + uint32_t mdMask; /*!< Listen Mode mask used */ + uint32_t mdReg; /*!< Listen Mode register value used */ + uint32_t mdIrqs; /*!< Listen Mode IRQs used */ + rfalBitRate brDetected; /*!< Last bit rate detected */ + + uint8_t* rxBuf; /*!< Location to store incoming data in Listen Mode */ + uint16_t rxBufLen; /*!< Length of rxBuf */ + uint16_t* rxLen; /*!< Pointer to write the data length placed into rxBuf */ + bool dataFlag; /*!< Listen Mode current Data Flag */ + bool iniFlag; /*!< Listen Mode initialized Flag (FeliCa slots) */ +} rfalLm; + +/*! Struct that holds all context for the Wake-Up Mode */ +typedef struct { + rfalWumState state; /*!< Current Wake-Up Mode state */ + rfalWakeUpConfig cfg; /*!< Current Wake-Up Mode context */ +} rfalWum; + +/*! Struct that holds all context for the Low Power Mode */ +typedef struct { + bool isRunning; +} rfalLpm; + +/*! Struct that holds the timings GT and FDTs */ +typedef struct { + uint32_t GT; /*!< GT in 1/fc */ + uint32_t FDTListen; /*!< FDTListen in 1/fc */ + uint32_t FDTPoll; /*!< FDTPoll in 1/fc */ + uint8_t nTRFW; /*!< n*TRFW used during RF CA */ +} rfalTimings; + +/*! Struct that holds the software timers */ +typedef struct { + uint32_t GT; /*!< RFAL's GT timer */ + uint32_t RXE; /*!< Timer between RXS and RXE */ + uint32_t txRx; /*!< Transceive sanity timer */ +} rfalTimers; + +/*! Struct that holds the RFAL's callbacks */ +typedef struct { + rfalPreTxRxCallback preTxRx; /*!< RFAL's Pre TxRx callback */ + rfalPostTxRxCallback postTxRx; /*!< RFAL's Post TxRx callback */ + RfalStateChangedCallback state_changed_cb; + void* ctx; +} rfalCallbacks; + +/*! Struct that holds counters to control the FIFO on Tx and Rx */ +typedef struct { + uint16_t + expWL; /*!< The amount of bytes expected to be Tx when a WL interrupt occurs */ + uint16_t + bytesTotal; /*!< Total bytes to be transmitted OR the total bytes received */ + uint16_t + bytesWritten; /*!< Amount of bytes already written on FIFO (Tx) OR read (RX) from FIFO and written on rxBuffer*/ + uint8_t status + [ST25R3916_FIFO_STATUS_LEN]; /*!< FIFO Status Registers */ +} rfalFIFO; + +/*! Struct that holds RFAL's configuration settings */ +typedef struct { + uint8_t obsvModeTx; /*!< RFAL's config of the ST25R3916's observation mode while Tx */ + uint8_t obsvModeRx; /*!< RFAL's config of the ST25R3916's observation mode while Rx */ + rfalEHandling eHandling; /*!< RFAL's error handling config/mode */ +} rfalConfigs; + +/*! Struct that holds NFC-F data - Used only inside rfalFelicaPoll() (static to avoid adding it into stack) */ +typedef struct { + rfalFeliCaPollRes + pollResponses[RFAL_FELICA_POLL_MAX_SLOTS]; /* FeliCa Poll response container for 16 slots */ +} rfalNfcfWorkingData; + +/*! Struct that holds NFC-V current context + * + * This buffer has to be big enough for coping with maximum response size (hamming coded) + * - inventory requests responses: 14*2+2 bytes + * - read single block responses: (32+4)*2+2 bytes + * - read multiple block could be very long... -> not supported + * - current implementation expects it be written in one bulk into FIFO + * - needs to be above FIFO water level of ST25R3916 (200) + * - the coding function needs to be able to + * put more than FIFO water level bytes into it (n*64+1)>200 */ +typedef struct { + uint8_t codingBuffer[( + (2 + 255 + 3) * 2)]; /*!< Coding buffer, length MUST be above 257: [257; ...] */ + uint16_t + nfcvOffset; /*!< Offset needed for ISO15693 coding function */ + rfalTransceiveContext + origCtx; /*!< context provided by user */ + uint16_t + ignoreBits; /*!< Number of bits at the beginning of a frame to be ignored when decoding */ +} rfalNfcvWorkingData; + +/*! RFAL instance */ +typedef struct { + rfalState state; /*!< RFAL's current state */ + rfalMode mode; /*!< RFAL's current mode */ + rfalBitRate txBR; /*!< RFAL's current Tx Bit Rate */ + rfalBitRate rxBR; /*!< RFAL's current Rx Bit Rate */ + bool field; /*!< Current field state (On / Off) */ + + rfalConfigs conf; /*!< RFAL's configuration settings */ + rfalTimings timings; /*!< RFAL's timing setting */ + rfalTxRx TxRx; /*!< RFAL's transceive management */ + rfalFIFO fifo; /*!< RFAL's FIFO management */ + rfalTimers tmr; /*!< RFAL's Software timers */ + rfalCallbacks callbacks; /*!< RFAL's callbacks */ + +#if RFAL_FEATURE_LISTEN_MODE + rfalLm Lm; /*!< RFAL's listen mode management */ +#endif /* RFAL_FEATURE_LISTEN_MODE */ + +#if RFAL_FEATURE_WAKEUP_MODE + rfalWum wum; /*!< RFAL's Wake-up mode management */ +#endif /* RFAL_FEATURE_WAKEUP_MODE */ + +#if RFAL_FEATURE_LOWPOWER_MODE + rfalLpm lpm; /*!< RFAL's Low power mode management */ +#endif /* RFAL_FEATURE_LOWPOWER_MODE */ + +#if RFAL_FEATURE_NFCF + rfalNfcfWorkingData nfcfData; /*!< RFAL's working data when supporting NFC-F */ +#endif /* RFAL_FEATURE_NFCF */ + +#if RFAL_FEATURE_NFCV + rfalNfcvWorkingData nfcvData; /*!< RFAL's working data when performing NFC-V */ +#endif /* RFAL_FEATURE_NFCV */ + +} rfal; + +/*! Felica's command set */ +typedef enum { + FELICA_CMD_POLLING = + 0x00, /*!< Felica Poll/REQC command (aka SENSF_REQ) to identify a card */ + FELICA_CMD_POLLING_RES = + 0x01, /*!< Felica Poll/REQC command (aka SENSF_RES) response */ + FELICA_CMD_REQUEST_SERVICE = + 0x02, /*!< verify the existence of Area and Service */ + FELICA_CMD_REQUEST_RESPONSE = + 0x04, /*!< verify the existence of a card */ + FELICA_CMD_READ_WITHOUT_ENCRYPTION = + 0x06, /*!< read Block Data from a Service that requires no authentication */ + FELICA_CMD_WRITE_WITHOUT_ENCRYPTION = + 0x08, /*!< write Block Data to a Service that requires no authentication */ + FELICA_CMD_REQUEST_SYSTEM_CODE = + 0x0C, /*!< acquire the System Code registered to a card */ + FELICA_CMD_AUTHENTICATION1 = + 0x10, /*!< authenticate a card */ + FELICA_CMD_AUTHENTICATION2 = + 0x12, /*!< allow a card to authenticate a Reader/Writer */ + FELICA_CMD_READ = 0x14, /*!< read Block Data from a Service that requires authentication */ + FELICA_CMD_WRITE = 0x16, /*!< write Block Data to a Service that requires authentication */ +} t_rfalFeliCaCmd; + +/*! Union representing all PTMem sections */ +typedef union { /* PRQA S 0750 # MISRA 19.2 - Both members are of the same type, just different names. Thus no problem can occur. */ + uint8_t PTMem_A + [ST25R3916_PTM_A_LEN]; /*!< PT_Memory area allocated for NFC-A configuration */ + uint8_t PTMem_F + [ST25R3916_PTM_F_LEN]; /*!< PT_Memory area allocated for NFC-F configuration */ + uint8_t + TSN[ST25R3916_PTM_TSN_LEN]; /*!< PT_Memory area allocated for TSN - Random numbers */ +} t_rfalPTMem; + +/* +****************************************************************************** +* GLOBAL DEFINES +****************************************************************************** +*/ + +#define RFAL_FIFO_IN_WL \ + 200U /*!< Number of bytes in the FIFO when WL interrupt occurs while Tx */ +#define RFAL_FIFO_OUT_WL \ + (ST25R3916_FIFO_DEPTH - \ + RFAL_FIFO_IN_WL) /*!< Number of bytes sent/out of the FIFO when WL interrupt occurs while Tx */ + +#define RFAL_FIFO_STATUS_REG1 \ + 0U /*!< Location of FIFO status register 1 in local copy */ +#define RFAL_FIFO_STATUS_REG2 \ + 1U /*!< Location of FIFO status register 2 in local copy */ +#define RFAL_FIFO_STATUS_INVALID \ + 0xFFU /*!< Value indicating that the local FIFO status in invalid|cleared */ + +#define RFAL_ST25R3916_GPT_MAX_1FC \ + rfalConv8fcTo1fc( \ + 0xFFFFU) /*!< Max GPT steps in 1fc (0xFFFF steps of 8/fc => 0xFFFF * 590ns = 38,7ms) */ +#define RFAL_ST25R3916_NRT_MAX_1FC \ + rfalConv4096fcTo1fc( \ + 0xFFFFU) /*!< Max NRT steps in 1fc (0xFFFF steps of 4096/fc => 0xFFFF * 302us = 19.8s ) */ +#define RFAL_ST25R3916_NRT_DISABLED \ + 0U /*!< NRT Disabled: All 0 No-response timer is not started, wait forever */ +#define RFAL_ST25R3916_MRT_MAX_1FC \ + rfalConv64fcTo1fc( \ + 0x00FFU) /*!< Max MRT steps in 1fc (0x00FF steps of 64/fc => 0x00FF * 4.72us = 1.2ms ) */ +#define RFAL_ST25R3916_MRT_MIN_1FC \ + rfalConv64fcTo1fc( \ + 0x0004U) /*!< Min MRT steps in 1fc ( 0<=mrt<=4 ; 4 (64/fc) => 0x0004 * 4.72us = 18.88us ) */ +#define RFAL_ST25R3916_GT_MAX_1FC \ + rfalConvMsTo1fc( \ + 6000U) /*!< Max GT value allowed in 1/fc (SFGI=14 => SFGT + dSFGT = 5.4s) */ +#define RFAL_ST25R3916_GT_MIN_1FC \ + rfalConvMsTo1fc( \ + RFAL_ST25R3916_SW_TMR_MIN_1MS) /*!< Min GT value allowed in 1/fc */ +#define RFAL_ST25R3916_SW_TMR_MIN_1MS \ + 1U /*!< Min value of a SW timer in ms */ + +#define RFAL_OBSMODE_DISABLE \ + 0x00U /*!< Observation Mode disabled */ + +#define RFAL_RX_INCOMPLETE_MAXLEN \ + (uint8_t)1U /*!< Threshold value where incoming rx may be considered as incomplete */ +#define RFAL_EMVCO_RX_MAXLEN \ + (uint8_t)4U /*!< Maximum value where EMVCo to apply special error handling */ + +#define RFAL_NORXE_TOUT \ + 50U /*!< Timeout to be used on a potential missing RXE - Silicon ST25R3916 Errata #TBD */ + +#define RFAL_ISO14443A_SDD_RES_LEN \ + 5U /*!< SDD_RES | Anticollision (UID CLn) length - rfalNfcaSddRes */ +#define RFAL_ISO14443A_CRC_INTVAL \ + 0x6363 /*!< ISO14443 CRC Initial Value|Register */ + +#define RFAL_FELICA_POLL_DELAY_TIME \ + 512U /*!< FeliCa Poll Processing time is 2.417 ms ~512*64/fc Digital 1.1 A4 */ +#define RFAL_FELICA_POLL_SLOT_TIME \ + 256U /*!< FeliCa Poll Time Slot duration is 1.208 ms ~256*64/fc Digital 1.1 A4 */ + +#define RFAL_LM_SENSF_RD0_POS \ + 17U /*!< FeliCa SENSF_RES Request Data RD0 position */ +#define RFAL_LM_SENSF_RD1_POS \ + 18U /*!< FeliCa SENSF_RES Request Data RD1 position */ + +#define RFAL_LM_NFCID_INCOMPLETE \ + 0x04U /*!< NFCA NFCID not complete bit in SEL_RES (SAK) */ + +#define RFAL_ISO15693_IGNORE_BITS \ + rfalConvBytesToBits( \ + 2U) /*!< Ignore collisions before the UID (RES_FLAG + DSFID) */ +#define RFAL_ISO15693_INV_RES_LEN \ + 12U /*!< ISO15693 Inventory response length with CRC (bytes) */ +#define RFAL_ISO15693_INV_RES_DUR \ + 4U /*!< ISO15693 Inventory response duration @ 26 kbps (ms) */ + +#define RFAL_WU_MIN_WEIGHT_VAL \ + 4U /*!< ST25R3916 minimum Wake-up weight value */ + +/*******************************************************************************/ + +#define RFAL_LM_GT \ + rfalConvUsTo1fc( \ + 100U) /*!< Listen Mode Guard Time enforced (GT - Passive; TIRFG - Active) */ +#define RFAL_FDT_POLL_ADJUSTMENT \ + rfalConvUsTo1fc( \ + 80U) /*!< FDT Poll adjustment: Time between the expiration of GPT to the actual Tx */ +#define RFAL_FDT_LISTEN_MRT_ADJUSTMENT \ + 64U /*!< MRT jitter adjustment: timeout will be between [ tout ; tout + 64 cycles ] */ +#define RFAL_AP2P_FIELDOFF_TRFW \ + rfalConv8fcTo1fc( \ + 64U) /*!< Time after TXE and Field Off in AP2P Trfw: 37.76us -> 64 (8/fc) */ + +#ifndef RFAL_ST25R3916_AAT_SETTLE +#define RFAL_ST25R3916_AAT_SETTLE \ + 5U /*!< Time in ms required for AAT pins and Osc to settle after en bit set */ +#endif /* RFAL_ST25R3916_AAT_SETTLE */ + +/*! FWT adjustment: + * 64 : NRT jitter between TXE and NRT start */ +#define RFAL_FWT_ADJUSTMENT 64U + +/*! FWT ISO14443A adjustment: + * 512 : 4bit length + * 64 : Half a bit duration due to ST25R3916 Coherent receiver (1/fc) */ +#define RFAL_FWT_A_ADJUSTMENT (512U + 64U) + +/*! FWT ISO14443B adjustment: + * SOF (14etu) + 1Byte (10etu) + 1etu (IRQ comes 1etu after first byte) - 3etu (ST25R3916 sends TXE 3etu after) */ +#define RFAL_FWT_B_ADJUSTMENT ((14U + 10U + 1U - 3U) * 128U) + +/*! FWT FeliCa 212 adjustment: + * 1024 : Length of the two Sync bytes at 212kbps */ +#define RFAL_FWT_F_212_ADJUSTMENT 1024U + +/*! FWT FeliCa 424 adjustment: + * 512 : Length of the two Sync bytes at 424kbps */ +#define RFAL_FWT_F_424_ADJUSTMENT 512U + +/*! Time between our field Off and other peer field On : Tadt + (n x Trfw) + * Ecma 340 11.1.2 - Tadt: [56.64 , 188.72] us ; n: [0 , 3] ; Trfw = 37.76 us + * Should be: 189 + (3*38) = 303us ; we'll use a more relaxed setting: 605 us */ +#define RFAL_AP2P_FIELDON_TADTTRFW rfalConvUsTo1fc(605U) + +/*! FDT Listen adjustment for ISO14443A EMVCo 2.6 4.8.1.3 ; Digital 1.1 6.10 + * + * 276: Time from the rising pulse of the pause of the logic '1' (i.e. the time point to measure the deaftime from), + * to the actual end of the EOF sequence (the point where the MRT starts). Please note that the ST25R391x uses the + * ISO14443-2 definition where the EOF consists of logic '0' followed by sequence Y. + * -64: Further adjustment for receiver to be ready just before first bit + */ +#define RFAL_FDT_LISTEN_A_ADJUSTMENT (276U - 64U) + +/*! FDT Listen adjustment for ISO14443B EMVCo 2.6 4.8.1.6 ; Digital 1.1 7.9 + * + * 340: Time from the rising edge of the EoS to the starting point of the MRT timer (sometime after the final high + * part of the EoS is completed) + */ +#define RFAL_FDT_LISTEN_B_ADJUSTMENT 340U + +/*! FDT Listen adjustment for ISO15693 + * ISO15693 2000 8.4 t1 MIN = 4192/fc + * ISO15693 2009 9.1 t1 MIN = 4320/fc + * Digital 2.1 B.5 FDTV,LISTEN,MIN = 4310/fc + * Set FDT Listen one step earlier than on the more recent spec versions for greater interoperability + */ +#define RFAL_FDT_LISTEN_V_ADJUSTMENT 64U + +/*! FDT Poll adjustment for ISO14443B Correlator - sst 5 etu */ +#define RFAL_FDT_LISTEN_B_ADJT_CORR 128U + +/*! FDT Poll adjustment for ISO14443B Correlator sst window - 5 etu */ +#define RFAL_FDT_LISTEN_B_ADJT_CORR_SST 20U + +/* +****************************************************************************** +* GLOBAL MACROS +****************************************************************************** +*/ + +/*! Calculates Transceive Sanity Timer. It accounts for the slowest bit rate and the longest data format + * 1s for transmission and reception of a 4K message at 106kpbs (~425ms each direction) + * plus TxRx preparation and FIFO load over Serial Interface */ +#define rfalCalcSanityTmr(fwt) (uint16_t)(1000U + rfalConv1fcToMs((fwt))) + +#define rfalGennTRFW(n) \ + (((n) + 1U) & \ + ST25R3916_REG_AUX_nfc_n_mask) /*!< Generates the next n*TRRW used for RFCA */ + +#define rfalCalcNumBytes(nBits) \ + (((uint32_t)(nBits) + 7U) / \ + 8U) /*!< Returns the number of bytes required to fit given the number of bits */ + +#define rfalTimerStart(timer, time_ms) \ + do { \ + platformTimerDestroy(timer); \ + (timer) = platformTimerCreate((uint16_t)(time_ms)); \ + } while(0) /*!< Configures and starts timer */ +#define rfalTimerisExpired(timer) \ + platformTimerIsExpired( \ + timer) /*!< Checks if timer has expired */ +#define rfalTimerDestroy(timer) \ + platformTimerDestroy( \ + timer) /*!< Destroys timer */ + +#define rfalST25R3916ObsModeDisable() \ + st25r3916WriteTestRegister( \ + 0x01U, \ + (0x40U)) /*!< Disable ST25R3916 Observation mode */ +#define rfalST25R3916ObsModeTx() \ + st25r3916WriteTestRegister( \ + 0x01U, \ + (0x40U | \ + gRFAL.conf \ + .obsvModeTx)) /*!< Enable Tx Observation mode */ +#define rfalST25R3916ObsModeRx() \ + st25r3916WriteTestRegister( \ + 0x01U, \ + (0x40U | \ + gRFAL.conf \ + .obsvModeRx)) /*!< Enable Rx Observation mode */ + +#define rfalCheckDisableObsMode() \ + if(gRFAL.conf.obsvModeRx != 0U) { \ + rfalST25R3916ObsModeDisable(); \ + } /*!< Checks if the observation mode is enabled, and applies on ST25R3916 */ +#define rfalCheckEnableObsModeTx() \ + if(gRFAL.conf.obsvModeTx != 0U) { \ + rfalST25R3916ObsModeTx(); \ + } /*!< Checks if the observation mode is enabled, and applies on ST25R3916 */ +#define rfalCheckEnableObsModeRx() \ + if(gRFAL.conf.obsvModeRx != 0U) { \ + rfalST25R3916ObsModeRx(); \ + } /*!< Checks if the observation mode is enabled, and applies on ST25R3916 */ + +#define rfalGetIncmplBits(FIFOStatus2) \ + (((FIFOStatus2) >> 1) & \ + 0x07U) /*!< Returns the number of bits from fifo status */ +#define rfalIsIncompleteByteError(error) \ + (((error) >= ERR_INCOMPLETE_BYTE) && \ + ((error) <= \ + ERR_INCOMPLETE_BYTE_07)) /*!< Checks if given error is a Incomplete error */ + +#define rfalAdjACBR(b) \ + (((uint16_t)(b) >= (uint16_t)RFAL_BR_52p97) ? \ + (uint16_t)(b) : \ + ((uint16_t)(b) + \ + 1U)) /*!< Adjusts ST25R391x Bit rate to Analog Configuration */ +#define rfalConvBR2ACBR(b) \ + (((rfalAdjACBR((b))) << RFAL_ANALOG_CONFIG_BITRATE_SHIFT) & \ + RFAL_ANALOG_CONFIG_BITRATE_MASK) /*!< Converts ST25R391x Bit rate to Analog Configuration bit rate id */ + +#define rfalConvTDFormat(v) \ + ((uint16_t)(v) << 8U) /*!< Converts a uint8_t to the format used in SW Tag Detection */ + +/* + ****************************************************************************** + * LOCAL VARIABLES + ****************************************************************************** + */ + +static rfal gRFAL; /*!< RFAL module instance */ + +/* +****************************************************************************** +* LOCAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +static void rfalTransceiveTx(void); +static void rfalTransceiveRx(void); +static ReturnCode rfalTransceiveRunBlockingTx(void); +static void rfalPrepareTransceive(void); +static void rfalCleanupTransceive(void); +static void rfalErrorHandling(void); + +static ReturnCode rfalRunTransceiveWorker(void); +#if RFAL_FEATURE_LISTEN_MODE +static ReturnCode rfalRunListenModeWorker(void); +#endif /* RFAL_FEATURE_LISTEN_MODE */ +#if RFAL_FEATURE_WAKEUP_MODE +static void rfalRunWakeUpModeWorker(void); +static uint16_t rfalWakeUpModeFilter(uint16_t curRef, uint16_t curVal, uint8_t weight); +#endif /* RFAL_FEATURE_WAKEUP_MODE */ + +static void rfalFIFOStatusUpdate(void); +static void rfalFIFOStatusClear(void); +static bool rfalFIFOStatusIsMissingPar(void); +static bool rfalFIFOStatusIsIncompleteByte(void); +static uint16_t rfalFIFOStatusGetNumBytes(void); +static uint8_t rfalFIFOGetNumIncompleteBits(void); + +/* +****************************************************************************** +* GLOBAL FUNCTIONS +****************************************************************************** +*/ + +/*******************************************************************************/ +ReturnCode rfalInitialize(void) { + ReturnCode err; + + EXIT_ON_ERR(err, st25r3916Initialize()); + + st25r3916ClearInterrupts(); + + /* Disable any previous observation mode */ + rfalST25R3916ObsModeDisable(); + + /*******************************************************************************/ + /* Apply RF Chip generic initialization */ + rfalSetAnalogConfig((RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_INIT)); + + // TODO: + // I don't want to mess with config table ("Default Analog Configuration for Chip-Specific Reset", rfal_analogConfigTbl.h) + // so with every rfalSetAnalogConfig((RFAL_ANALOG_CONFIG_CHIP_INIT)) currently we need to clear pulldown bits + // luckily for us this is done only here + + // disable pulldowns + st25r3916ClrRegisterBits( + ST25R3916_REG_IO_CONF2, + (ST25R3916_REG_IO_CONF2_miso_pd1 | ST25R3916_REG_IO_CONF2_miso_pd2)); + + /*******************************************************************************/ + /* Enable External Field Detector as: Automatics */ + st25r3916ChangeRegisterBits( + ST25R3916_REG_OP_CONTROL, + ST25R3916_REG_OP_CONTROL_en_fd_mask, + ST25R3916_REG_OP_CONTROL_en_fd_auto_efd); + + /* Clear FIFO status local copy */ + rfalFIFOStatusClear(); + + /*******************************************************************************/ + gRFAL.state = RFAL_STATE_INIT; + gRFAL.mode = RFAL_MODE_NONE; + gRFAL.field = false; + + /* Set RFAL default configs */ + gRFAL.conf.obsvModeRx = RFAL_OBSMODE_DISABLE; + gRFAL.conf.obsvModeTx = RFAL_OBSMODE_DISABLE; + gRFAL.conf.eHandling = RFAL_ERRORHANDLING_NONE; + + /* Transceive set to IDLE */ + gRFAL.TxRx.lastState = RFAL_TXRX_STATE_IDLE; + gRFAL.TxRx.state = RFAL_TXRX_STATE_IDLE; + + /* Disable all timings */ + gRFAL.timings.FDTListen = RFAL_TIMING_NONE; + gRFAL.timings.FDTPoll = RFAL_TIMING_NONE; + gRFAL.timings.GT = RFAL_TIMING_NONE; + gRFAL.timings.nTRFW = 0U; + + /* Destroy any previous pending timers */ + rfalTimerDestroy(gRFAL.tmr.GT); + rfalTimerDestroy(gRFAL.tmr.txRx); + rfalTimerDestroy(gRFAL.tmr.RXE); + gRFAL.tmr.GT = RFAL_TIMING_NONE; + gRFAL.tmr.txRx = RFAL_TIMING_NONE; + gRFAL.tmr.RXE = RFAL_TIMING_NONE; + + gRFAL.callbacks.preTxRx = NULL; + gRFAL.callbacks.postTxRx = NULL; + gRFAL.callbacks.state_changed_cb = NULL; + gRFAL.callbacks.ctx = NULL; + +#if RFAL_FEATURE_NFCV + /* Initialize NFC-V Data */ + gRFAL.nfcvData.ignoreBits = 0; +#endif /* RFAL_FEATURE_NFCV */ + +#if RFAL_FEATURE_LISTEN_MODE + /* Initialize Listen Mode */ + gRFAL.Lm.state = RFAL_LM_STATE_NOT_INIT; + gRFAL.Lm.brDetected = RFAL_BR_KEEP; + gRFAL.Lm.iniFlag = false; +#endif /* RFAL_FEATURE_LISTEN_MODE */ + +#if RFAL_FEATURE_WAKEUP_MODE + /* Initialize Wake-Up Mode */ + gRFAL.wum.state = RFAL_WUM_STATE_NOT_INIT; +#endif /* RFAL_FEATURE_WAKEUP_MODE */ + +#if RFAL_FEATURE_LOWPOWER_MODE + /* Initialize Low Power Mode */ + gRFAL.lpm.isRunning = false; +#endif /* RFAL_FEATURE_LOWPOWER_MODE */ + + /*******************************************************************************/ + /* Perform Automatic Calibration (if configured to do so). * + * Registers set by rfalSetAnalogConfig will tell rfalCalibrate what to perform*/ + rfalCalibrate(); + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalCalibrate(void) { + uint16_t resValue; + + /* Check if RFAL is not initialized */ + if(gRFAL.state == RFAL_STATE_IDLE) { + return ERR_WRONG_STATE; + } + + /*******************************************************************************/ + /* Perform ST25R3916 regulators and antenna calibration */ + /*******************************************************************************/ + + /* Automatic regulator adjustment only performed if not set manually on Analog Configs */ + if(st25r3916CheckReg( + ST25R3916_REG_REGULATOR_CONTROL, ST25R3916_REG_REGULATOR_CONTROL_reg_s, 0x00)) { + /* Adjust the regulators so that Antenna Calibrate has better Regulator values */ + st25r3916AdjustRegulators(&resValue); + } + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalAdjustRegulators(uint16_t* result) { + return st25r3916AdjustRegulators(result); +} + +/*******************************************************************************/ +void rfalSetUpperLayerCallback(rfalUpperLayerCallback pFunc) { + st25r3916IRQCallbackSet(pFunc); +} + +/*******************************************************************************/ +void rfalSetPreTxRxCallback(rfalPreTxRxCallback pFunc) { + gRFAL.callbacks.preTxRx = pFunc; +} + +/*******************************************************************************/ +void rfalSetPostTxRxCallback(rfalPostTxRxCallback pFunc) { + gRFAL.callbacks.postTxRx = pFunc; +} + +void rfal_set_state_changed_callback(RfalStateChangedCallback callback) { + gRFAL.callbacks.state_changed_cb = callback; +} + +void rfal_set_callback_context(void* context) { + gRFAL.callbacks.ctx = context; +} + +/*******************************************************************************/ +ReturnCode rfalDeinitialize(void) { + /* Deinitialize chip */ + st25r3916Deinitialize(); + + /* Set Analog configurations for deinitialization */ + rfalSetAnalogConfig((RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_DEINIT)); + + gRFAL.state = RFAL_STATE_IDLE; + return ERR_NONE; +} + +/*******************************************************************************/ +void rfalSetObsvMode(uint8_t txMode, uint8_t rxMode) { + gRFAL.conf.obsvModeTx = txMode; + gRFAL.conf.obsvModeRx = rxMode; +} + +/*******************************************************************************/ +void rfalGetObsvMode(uint8_t* txMode, uint8_t* rxMode) { + if(txMode != NULL) { + *txMode = gRFAL.conf.obsvModeTx; + } + + if(rxMode != NULL) { + *rxMode = gRFAL.conf.obsvModeRx; + } +} + +/*******************************************************************************/ +void rfalDisableObsvMode(void) { + gRFAL.conf.obsvModeTx = RFAL_OBSMODE_DISABLE; + gRFAL.conf.obsvModeRx = RFAL_OBSMODE_DISABLE; +} + +/*******************************************************************************/ +ReturnCode rfalSetMode(rfalMode mode, rfalBitRate txBR, rfalBitRate rxBR) { + /* Check if RFAL is not initialized */ + if(gRFAL.state == RFAL_STATE_IDLE) { + return ERR_WRONG_STATE; + } + + /* Check allowed bit rate value */ + if((txBR == RFAL_BR_KEEP) || (rxBR == RFAL_BR_KEEP)) { + return ERR_PARAM; + } + + switch(mode) { + /*******************************************************************************/ + case RFAL_MODE_POLL_NFCA: + + /* Disable wake up mode, if set */ + st25r3916ClrRegisterBits(ST25R3916_REG_OP_CONTROL, ST25R3916_REG_OP_CONTROL_wu); + + /* Enable ISO14443A mode */ + st25r3916WriteRegister(ST25R3916_REG_MODE, ST25R3916_REG_MODE_om_iso14443a); + + /* Set Analog configurations for this mode and bit rate */ + rfalSetAnalogConfig( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_TX)); + rfalSetAnalogConfig( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX)); + break; + + /*******************************************************************************/ + case RFAL_MODE_POLL_NFCA_T1T: + /* Disable wake up mode, if set */ + st25r3916ClrRegisterBits(ST25R3916_REG_OP_CONTROL, ST25R3916_REG_OP_CONTROL_wu); + + /* Enable Topaz mode */ + st25r3916WriteRegister(ST25R3916_REG_MODE, ST25R3916_REG_MODE_om_topaz); + + /* Set Analog configurations for this mode and bit rate */ + rfalSetAnalogConfig( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_TX)); + rfalSetAnalogConfig( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX)); + break; + + /*******************************************************************************/ + case RFAL_MODE_POLL_NFCB: + + /* Disable wake up mode, if set */ + st25r3916ClrRegisterBits(ST25R3916_REG_OP_CONTROL, ST25R3916_REG_OP_CONTROL_wu); + + /* Enable ISO14443B mode */ + st25r3916WriteRegister(ST25R3916_REG_MODE, ST25R3916_REG_MODE_om_iso14443b); + + /* Set the EGT, SOF, EOF and EOF */ + st25r3916ChangeRegisterBits( + ST25R3916_REG_ISO14443B_1, + (ST25R3916_REG_ISO14443B_1_egt_mask | ST25R3916_REG_ISO14443B_1_sof_mask | + ST25R3916_REG_ISO14443B_1_eof), + ((0U << ST25R3916_REG_ISO14443B_1_egt_shift) | ST25R3916_REG_ISO14443B_1_sof_0_10etu | + ST25R3916_REG_ISO14443B_1_sof_1_2etu | ST25R3916_REG_ISO14443B_1_eof_10etu)); + + /* Set the minimum TR1, SOF, EOF and EOF12 */ + st25r3916ChangeRegisterBits( + ST25R3916_REG_ISO14443B_2, + (ST25R3916_REG_ISO14443B_2_tr1_mask | ST25R3916_REG_ISO14443B_2_no_sof | + ST25R3916_REG_ISO14443B_2_no_eof), + (ST25R3916_REG_ISO14443B_2_tr1_80fs80fs)); + + /* Set Analog configurations for this mode and bit rate */ + rfalSetAnalogConfig( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCB | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_TX)); + rfalSetAnalogConfig( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCB | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX)); + break; + + /*******************************************************************************/ + case RFAL_MODE_POLL_B_PRIME: + + /* Disable wake up mode, if set */ + st25r3916ClrRegisterBits(ST25R3916_REG_OP_CONTROL, ST25R3916_REG_OP_CONTROL_wu); + + /* Enable ISO14443B mode */ + st25r3916WriteRegister(ST25R3916_REG_MODE, ST25R3916_REG_MODE_om_iso14443b); + + /* Set the EGT, SOF, EOF and EOF */ + st25r3916ChangeRegisterBits( + ST25R3916_REG_ISO14443B_1, + (ST25R3916_REG_ISO14443B_1_egt_mask | ST25R3916_REG_ISO14443B_1_sof_mask | + ST25R3916_REG_ISO14443B_1_eof), + ((0U << ST25R3916_REG_ISO14443B_1_egt_shift) | ST25R3916_REG_ISO14443B_1_sof_0_10etu | + ST25R3916_REG_ISO14443B_1_sof_1_2etu | ST25R3916_REG_ISO14443B_1_eof_10etu)); + + /* Set the minimum TR1, EOF and EOF12 */ + st25r3916ChangeRegisterBits( + ST25R3916_REG_ISO14443B_2, + (ST25R3916_REG_ISO14443B_2_tr1_mask | ST25R3916_REG_ISO14443B_2_no_sof | + ST25R3916_REG_ISO14443B_2_no_eof), + (ST25R3916_REG_ISO14443B_2_tr1_80fs80fs | ST25R3916_REG_ISO14443B_2_no_sof)); + + /* Set Analog configurations for this mode and bit rate */ + rfalSetAnalogConfig( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCB | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_TX)); + rfalSetAnalogConfig( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCB | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX)); + break; + + /*******************************************************************************/ + case RFAL_MODE_POLL_B_CTS: + + /* Disable wake up mode, if set */ + st25r3916ClrRegisterBits(ST25R3916_REG_OP_CONTROL, ST25R3916_REG_OP_CONTROL_wu); + + /* Enable ISO14443B mode */ + st25r3916WriteRegister(ST25R3916_REG_MODE, ST25R3916_REG_MODE_om_iso14443b); + + /* Set the EGT, SOF, EOF and EOF */ + st25r3916ChangeRegisterBits( + ST25R3916_REG_ISO14443B_1, + (ST25R3916_REG_ISO14443B_1_egt_mask | ST25R3916_REG_ISO14443B_1_sof_mask | + ST25R3916_REG_ISO14443B_1_eof), + ((0U << ST25R3916_REG_ISO14443B_1_egt_shift) | ST25R3916_REG_ISO14443B_1_sof_0_10etu | + ST25R3916_REG_ISO14443B_1_sof_1_2etu | ST25R3916_REG_ISO14443B_1_eof_10etu)); + + /* Set the minimum TR1, clear SOF, EOF and EOF12 */ + st25r3916ChangeRegisterBits( + ST25R3916_REG_ISO14443B_2, + (ST25R3916_REG_ISO14443B_2_tr1_mask | ST25R3916_REG_ISO14443B_2_no_sof | + ST25R3916_REG_ISO14443B_2_no_eof), + (ST25R3916_REG_ISO14443B_2_tr1_80fs80fs | ST25R3916_REG_ISO14443B_2_no_sof | + ST25R3916_REG_ISO14443B_2_no_eof)); + + /* Set Analog configurations for this mode and bit rate */ + rfalSetAnalogConfig( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCB | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_TX)); + rfalSetAnalogConfig( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCB | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX)); + break; + + /*******************************************************************************/ + case RFAL_MODE_POLL_NFCF: + + /* Disable wake up mode, if set */ + st25r3916ClrRegisterBits(ST25R3916_REG_OP_CONTROL, ST25R3916_REG_OP_CONTROL_wu); + + /* Enable FeliCa mode */ + st25r3916WriteRegister(ST25R3916_REG_MODE, ST25R3916_REG_MODE_om_felica); + + /* Set Analog configurations for this mode and bit rate */ + rfalSetAnalogConfig( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCF | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_TX)); + rfalSetAnalogConfig( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCF | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX)); + break; + + /*******************************************************************************/ + case RFAL_MODE_POLL_NFCV: + case RFAL_MODE_POLL_PICOPASS: + +#if !RFAL_FEATURE_NFCV + return ERR_DISABLED; +#else + + /* Disable wake up mode, if set */ + st25r3916ClrRegisterBits(ST25R3916_REG_OP_CONTROL, ST25R3916_REG_OP_CONTROL_wu); + + /* Set Analog configurations for this mode and bit rate */ + rfalSetAnalogConfig( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCV | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_TX)); + rfalSetAnalogConfig( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCV | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX)); + break; + +#endif /* RFAL_FEATURE_NFCV */ + + /*******************************************************************************/ + case RFAL_MODE_POLL_ACTIVE_P2P: + + /* Set NFCIP1 active communication Initiator mode and Automatic Response RF Collision Avoidance to always after EOF */ + st25r3916WriteRegister( + ST25R3916_REG_MODE, + (ST25R3916_REG_MODE_targ_init | ST25R3916_REG_MODE_om_nfc | + ST25R3916_REG_MODE_nfc_ar_eof)); + + /* External Field Detector enabled as Automatics on rfalInitialize() */ + + /* Set NRT to start at end of TX (own) field */ + st25r3916ChangeRegisterBits( + ST25R3916_REG_TIMER_EMV_CONTROL, + ST25R3916_REG_TIMER_EMV_CONTROL_nrt_nfc, + ST25R3916_REG_TIMER_EMV_CONTROL_nrt_nfc_off); + + /* Set GPT to start after end of TX, as GPT is used in active communication mode to timeout the field switching off */ + /* The field is turned off 37.76us after the end of the transmission Trfw */ + st25r3916SetStartGPTimer( + (uint16_t)rfalConv1fcTo8fc(RFAL_AP2P_FIELDOFF_TRFW), + ST25R3916_REG_TIMER_EMV_CONTROL_gptc_etx_nfc); + + /* Set PPon2 timer with the max time between our field Off and other peer field On : Tadt + (n x Trfw) */ + st25r3916WriteRegister( + ST25R3916_REG_PPON2, (uint8_t)rfalConv1fcTo64fc(RFAL_AP2P_FIELDON_TADTTRFW)); + + /* Set Analog configurations for this mode and bit rate */ + rfalSetAnalogConfig( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_AP2P | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_TX)); + rfalSetAnalogConfig( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_AP2P | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX)); + break; + + /*******************************************************************************/ + case RFAL_MODE_LISTEN_ACTIVE_P2P: + + /* Set NFCIP1 active communication Target mode and Automatic Response RF Collision Avoidance to always after EOF */ + st25r3916WriteRegister( + ST25R3916_REG_MODE, + (ST25R3916_REG_MODE_targ_targ | ST25R3916_REG_MODE_om_targ_nfcip | + ST25R3916_REG_MODE_nfc_ar_eof)); + + /* Set TARFG: 0 (75us+0ms=75us), as Target no Guard time needed */ + st25r3916WriteRegister(ST25R3916_REG_FIELD_ON_GT, 0U); + + /* External Field Detector enabled as Automatics on rfalInitialize() */ + + /* Set NRT to start at end of TX (own) field */ + st25r3916ChangeRegisterBits( + ST25R3916_REG_TIMER_EMV_CONTROL, + ST25R3916_REG_TIMER_EMV_CONTROL_nrt_nfc, + ST25R3916_REG_TIMER_EMV_CONTROL_nrt_nfc_off); + + /* Set GPT to start after end of TX, as GPT is used in active communication mode to timeout the field switching off */ + /* The field is turned off 37.76us after the end of the transmission Trfw */ + st25r3916SetStartGPTimer( + (uint16_t)rfalConv1fcTo8fc(RFAL_AP2P_FIELDOFF_TRFW), + ST25R3916_REG_TIMER_EMV_CONTROL_gptc_etx_nfc); + + /* Set PPon2 timer with the max time between our field Off and other peer field On : Tadt + (n x Trfw) */ + st25r3916WriteRegister( + ST25R3916_REG_PPON2, (uint8_t)rfalConv1fcTo64fc(RFAL_AP2P_FIELDON_TADTTRFW)); + + /* Set Analog configurations for this mode and bit rate */ + rfalSetAnalogConfig( + (RFAL_ANALOG_CONFIG_LISTEN | RFAL_ANALOG_CONFIG_TECH_AP2P | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_TX)); + rfalSetAnalogConfig( + (RFAL_ANALOG_CONFIG_LISTEN | RFAL_ANALOG_CONFIG_TECH_AP2P | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX)); + break; + + /*******************************************************************************/ + case RFAL_MODE_LISTEN_NFCA: + + /* Disable wake up mode, if set */ + st25r3916ClrRegisterBits(ST25R3916_REG_OP_CONTROL, ST25R3916_REG_OP_CONTROL_wu); + + /* Enable Passive Target NFC-A mode, disable any Collision Avoidance */ + st25r3916WriteRegister( + ST25R3916_REG_MODE, + (ST25R3916_REG_MODE_targ | ST25R3916_REG_MODE_om_targ_nfca | + ST25R3916_REG_MODE_nfc_ar_off)); + + /* Set Analog configurations for this mode */ + rfalSetAnalogConfig( + (RFAL_ANALOG_CONFIG_LISTEN | RFAL_ANALOG_CONFIG_TECH_NFCA | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_TX)); + rfalSetAnalogConfig( + (RFAL_ANALOG_CONFIG_LISTEN | RFAL_ANALOG_CONFIG_TECH_NFCA | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX)); + break; + + /*******************************************************************************/ + case RFAL_MODE_LISTEN_NFCF: + + /* Disable wake up mode, if set */ + st25r3916ClrRegisterBits(ST25R3916_REG_OP_CONTROL, ST25R3916_REG_OP_CONTROL_wu); + + /* Enable Passive Target NFC-F mode, disable any Collision Avoidance */ + st25r3916WriteRegister( + ST25R3916_REG_MODE, + (ST25R3916_REG_MODE_targ | ST25R3916_REG_MODE_om_targ_nfcf | + ST25R3916_REG_MODE_nfc_ar_off)); + + /* Set Analog configurations for this mode */ + rfalSetAnalogConfig( + (RFAL_ANALOG_CONFIG_LISTEN | RFAL_ANALOG_CONFIG_TECH_NFCF | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_TX)); + rfalSetAnalogConfig( + (RFAL_ANALOG_CONFIG_LISTEN | RFAL_ANALOG_CONFIG_TECH_NFCF | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_RX)); + break; + + /*******************************************************************************/ + case RFAL_MODE_LISTEN_NFCB: + return ERR_NOTSUPP; + + /*******************************************************************************/ + default: + return ERR_NOT_IMPLEMENTED; + } + + /* Set state as STATE_MODE_SET only if not initialized yet (PSL) */ + gRFAL.state = ((gRFAL.state < RFAL_STATE_MODE_SET) ? RFAL_STATE_MODE_SET : gRFAL.state); + gRFAL.mode = mode; + + /* Apply the given bit rate */ + return rfalSetBitRate(txBR, rxBR); +} + +/*******************************************************************************/ +rfalMode rfalGetMode(void) { + return gRFAL.mode; +} + +/*******************************************************************************/ +ReturnCode rfalSetBitRate(rfalBitRate txBR, rfalBitRate rxBR) { + ReturnCode ret; + + /* Check if RFAL is not initialized */ + if(gRFAL.state == RFAL_STATE_IDLE) { + return ERR_WRONG_STATE; + } + + /* Store the new Bit Rates */ + gRFAL.txBR = ((txBR == RFAL_BR_KEEP) ? gRFAL.txBR : txBR); + gRFAL.rxBR = ((rxBR == RFAL_BR_KEEP) ? gRFAL.rxBR : rxBR); + + /* Update the bitrate reg if not in NFCV mode (streaming) */ + if((RFAL_MODE_POLL_NFCV != gRFAL.mode) && (RFAL_MODE_POLL_PICOPASS != gRFAL.mode)) { + /* Set bit rate register */ + EXIT_ON_ERR(ret, st25r3916SetBitrate((uint8_t)gRFAL.txBR, (uint8_t)gRFAL.rxBR)); + } + + switch(gRFAL.mode) { + /*******************************************************************************/ + case RFAL_MODE_POLL_NFCA: + case RFAL_MODE_POLL_NFCA_T1T: + + /* Set Analog configurations for this bit rate */ + rfalSetAnalogConfig((RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_POLL_COMMON)); + rfalSetAnalogConfig( + (rfalAnalogConfigId)(RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | + rfalConvBR2ACBR(gRFAL.txBR) | RFAL_ANALOG_CONFIG_TX)); + rfalSetAnalogConfig( + (rfalAnalogConfigId)(RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | + rfalConvBR2ACBR(gRFAL.rxBR) | RFAL_ANALOG_CONFIG_RX)); + break; + + /*******************************************************************************/ + case RFAL_MODE_POLL_NFCB: + case RFAL_MODE_POLL_B_PRIME: + case RFAL_MODE_POLL_B_CTS: + + /* Set Analog configurations for this bit rate */ + rfalSetAnalogConfig((RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_POLL_COMMON)); + rfalSetAnalogConfig( + (rfalAnalogConfigId)(RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCB | + rfalConvBR2ACBR(gRFAL.txBR) | RFAL_ANALOG_CONFIG_TX)); + rfalSetAnalogConfig( + (rfalAnalogConfigId)(RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCB | + rfalConvBR2ACBR(gRFAL.rxBR) | RFAL_ANALOG_CONFIG_RX)); + break; + + /*******************************************************************************/ + case RFAL_MODE_POLL_NFCF: + + /* Set Analog configurations for this bit rate */ + rfalSetAnalogConfig((RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_POLL_COMMON)); + rfalSetAnalogConfig( + (rfalAnalogConfigId)(RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCF | + rfalConvBR2ACBR(gRFAL.txBR) | RFAL_ANALOG_CONFIG_TX)); + rfalSetAnalogConfig( + (rfalAnalogConfigId)(RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCF | + rfalConvBR2ACBR(gRFAL.rxBR) | RFAL_ANALOG_CONFIG_RX)); + break; + + /*******************************************************************************/ + case RFAL_MODE_POLL_NFCV: + case RFAL_MODE_POLL_PICOPASS: + +#if !RFAL_FEATURE_NFCV + return ERR_DISABLED; +#else + + if(((gRFAL.rxBR != RFAL_BR_26p48) && (gRFAL.rxBR != RFAL_BR_52p97)) || + ((gRFAL.txBR != RFAL_BR_1p66) && (gRFAL.txBR != RFAL_BR_26p48))) { + return ERR_PARAM; + } + + { + const struct iso15693StreamConfig* isoStreamConfig; + struct st25r3916StreamConfig streamConf; + iso15693PhyConfig_t config; + + config.coding = + ((gRFAL.txBR == RFAL_BR_1p66) ? ISO15693_VCD_CODING_1_256 : + ISO15693_VCD_CODING_1_4); + switch(gRFAL.rxBR) { + case RFAL_BR_52p97: + config.speedMode = 1; + break; + default: + config.speedMode = 0; + break; + } + + iso15693PhyConfigure(&config, &isoStreamConfig); + + /* MISRA 11.3 - Cannot point directly into different object type, copy to local var */ + streamConf.din = isoStreamConfig->din; + streamConf.dout = isoStreamConfig->dout; + streamConf.report_period_length = isoStreamConfig->report_period_length; + streamConf.useBPSK = isoStreamConfig->useBPSK; + st25r3916StreamConfigure(&streamConf); + } + + /* Set Analog configurations for this bit rate */ + rfalSetAnalogConfig((RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_POLL_COMMON)); + rfalSetAnalogConfig( + (rfalAnalogConfigId)(RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCV | + rfalConvBR2ACBR(gRFAL.txBR) | RFAL_ANALOG_CONFIG_TX)); + rfalSetAnalogConfig( + (rfalAnalogConfigId)(RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCV | + rfalConvBR2ACBR(gRFAL.rxBR) | RFAL_ANALOG_CONFIG_RX)); + break; + +#endif /* RFAL_FEATURE_NFCV */ + + /*******************************************************************************/ + case RFAL_MODE_POLL_ACTIVE_P2P: + + /* Set Analog configurations for this bit rate */ + rfalSetAnalogConfig((RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_POLL_COMMON)); + rfalSetAnalogConfig( + (rfalAnalogConfigId)(RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_AP2P | + rfalConvBR2ACBR(gRFAL.txBR) | RFAL_ANALOG_CONFIG_TX)); + rfalSetAnalogConfig( + (rfalAnalogConfigId)(RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_AP2P | + rfalConvBR2ACBR(gRFAL.rxBR) | RFAL_ANALOG_CONFIG_RX)); + break; + + /*******************************************************************************/ + case RFAL_MODE_LISTEN_ACTIVE_P2P: + + /* Set Analog configurations for this bit rate */ + rfalSetAnalogConfig( + (RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_LISTEN_COMMON)); + rfalSetAnalogConfig( + (rfalAnalogConfigId)(RFAL_ANALOG_CONFIG_LISTEN | RFAL_ANALOG_CONFIG_TECH_AP2P | + rfalConvBR2ACBR(gRFAL.txBR) | RFAL_ANALOG_CONFIG_TX)); + rfalSetAnalogConfig( + (rfalAnalogConfigId)(RFAL_ANALOG_CONFIG_LISTEN | RFAL_ANALOG_CONFIG_TECH_AP2P | + rfalConvBR2ACBR(gRFAL.rxBR) | RFAL_ANALOG_CONFIG_RX)); + break; + + /*******************************************************************************/ + case RFAL_MODE_LISTEN_NFCA: + + /* Set Analog configurations for this bit rate */ + rfalSetAnalogConfig( + (RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_LISTEN_COMMON)); + rfalSetAnalogConfig( + (rfalAnalogConfigId)(RFAL_ANALOG_CONFIG_LISTEN | RFAL_ANALOG_CONFIG_TECH_NFCA | + rfalConvBR2ACBR(gRFAL.txBR) | RFAL_ANALOG_CONFIG_TX)); + rfalSetAnalogConfig( + (rfalAnalogConfigId)(RFAL_ANALOG_CONFIG_LISTEN | RFAL_ANALOG_CONFIG_TECH_NFCA | + rfalConvBR2ACBR(gRFAL.rxBR) | RFAL_ANALOG_CONFIG_RX)); + break; + + /*******************************************************************************/ + case RFAL_MODE_LISTEN_NFCF: + + /* Set Analog configurations for this bit rate */ + rfalSetAnalogConfig( + (RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_LISTEN_COMMON)); + rfalSetAnalogConfig( + (rfalAnalogConfigId)(RFAL_ANALOG_CONFIG_LISTEN | RFAL_ANALOG_CONFIG_TECH_NFCF | + rfalConvBR2ACBR(gRFAL.txBR) | RFAL_ANALOG_CONFIG_TX)); + rfalSetAnalogConfig( + (rfalAnalogConfigId)(RFAL_ANALOG_CONFIG_LISTEN | RFAL_ANALOG_CONFIG_TECH_NFCF | + rfalConvBR2ACBR(gRFAL.rxBR) | RFAL_ANALOG_CONFIG_RX)); + break; + + /*******************************************************************************/ + case RFAL_MODE_LISTEN_NFCB: + case RFAL_MODE_NONE: + return ERR_WRONG_STATE; + + /*******************************************************************************/ + default: + return ERR_NOT_IMPLEMENTED; + } + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalGetBitRate(rfalBitRate* txBR, rfalBitRate* rxBR) { + if((gRFAL.state == RFAL_STATE_IDLE) || (gRFAL.mode == RFAL_MODE_NONE)) { + return ERR_WRONG_STATE; + } + + if(txBR != NULL) { + *txBR = gRFAL.txBR; + } + + if(rxBR != NULL) { + *rxBR = gRFAL.rxBR; + } + + return ERR_NONE; +} + +/*******************************************************************************/ +void rfalSetErrorHandling(rfalEHandling eHandling) { + switch(eHandling) { + case RFAL_ERRORHANDLING_NFC: + case RFAL_ERRORHANDLING_NONE: + st25r3916ClrRegisterBits(ST25R3916_REG_EMD_SUP_CONF, ST25R3916_REG_EMD_SUP_CONF_emd_emv); + break; + + case RFAL_ERRORHANDLING_EMVCO: + /* MISRA 16.4: no empty default statement (in case RFAL_SW_EMD is defined) */ +#ifndef RFAL_SW_EMD + st25r3916ModifyRegister( + ST25R3916_REG_EMD_SUP_CONF, + (ST25R3916_REG_EMD_SUP_CONF_emd_emv | ST25R3916_REG_EMD_SUP_CONF_emd_thld_mask), + (ST25R3916_REG_EMD_SUP_CONF_emd_emv_on | RFAL_EMVCO_RX_MAXLEN)); +#endif /* RFAL_SW_EMD */ + break; + default: + /* MISRA 16.4: no empty default statement (a comment being enough) */ + break; + } + + gRFAL.conf.eHandling = eHandling; +} + +/*******************************************************************************/ +rfalEHandling rfalGetErrorHandling(void) { + return gRFAL.conf.eHandling; +} + +/*******************************************************************************/ +void rfalSetFDTPoll(uint32_t FDTPoll) { + gRFAL.timings.FDTPoll = MIN(FDTPoll, RFAL_ST25R3916_GPT_MAX_1FC); +} + +/*******************************************************************************/ +uint32_t rfalGetFDTPoll(void) { + return gRFAL.timings.FDTPoll; +} + +/*******************************************************************************/ +void rfalSetFDTListen(uint32_t FDTListen) { + gRFAL.timings.FDTListen = MIN(FDTListen, RFAL_ST25R3916_MRT_MAX_1FC); +} + +/*******************************************************************************/ +uint32_t rfalGetFDTListen(void) { + return gRFAL.timings.FDTListen; +} + +/*******************************************************************************/ +void rfalSetGT(uint32_t GT) { + gRFAL.timings.GT = MIN(GT, RFAL_ST25R3916_GT_MAX_1FC); +} + +/*******************************************************************************/ +uint32_t rfalGetGT(void) { + return gRFAL.timings.GT; +} + +/*******************************************************************************/ +bool rfalIsGTExpired(void) { + if(gRFAL.tmr.GT != RFAL_TIMING_NONE) { + if(!rfalTimerisExpired(gRFAL.tmr.GT)) { + return false; + } + } + return true; +} + +/*******************************************************************************/ +ReturnCode rfalFieldOnAndStartGT(void) { + ReturnCode ret; + + /* Check if RFAL has been initialized (Oscillator should be running) and also + * if a direct register access has been performed and left the Oscillator Off */ + if(!st25r3916IsOscOn() || (gRFAL.state < RFAL_STATE_INIT)) { + return ERR_WRONG_STATE; + } + + ret = ERR_NONE; + + /* Set Analog configurations for Field On event */ + rfalSetAnalogConfig((RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_FIELD_ON)); + + /*******************************************************************************/ + /* Perform collision avoidance and turn field On if not already On */ + if(!st25r3916IsTxEnabled() || !gRFAL.field) { + /* Set TARFG: 0 (75us+0ms=75us), GT is fulfilled using a SW timer */ + st25r3916WriteRegister(ST25R3916_REG_FIELD_ON_GT, 0U); + + /* Use Thresholds set by AnalogConfig */ + ret = st25r3916PerformCollisionAvoidance( + ST25R3916_CMD_INITIAL_RF_COLLISION, + ST25R3916_THRESHOLD_DO_NOT_SET, + ST25R3916_THRESHOLD_DO_NOT_SET, + gRFAL.timings.nTRFW); + + /* n * TRFW timing shall vary Activity 2.1 3.3.1.1 */ + gRFAL.timings.nTRFW = rfalGennTRFW(gRFAL.timings.nTRFW); + + gRFAL.field = st25r3916IsTxEnabled(); //(ret == ERR_NONE); + + /* Only turn on Receiver and Transmitter if field was successfully turned On */ + if(gRFAL.field) { + st25r3916TxRxOn(); /* Enable Tx and Rx (Tx is already On)*/ + } + } + + /*******************************************************************************/ + /* Start GT timer in case the GT value is set */ + if((gRFAL.timings.GT != RFAL_TIMING_NONE)) { + /* Ensure that a SW timer doesn't have a lower value then the minimum */ + rfalTimerStart( + gRFAL.tmr.GT, rfalConv1fcToMs(MAX((gRFAL.timings.GT), RFAL_ST25R3916_GT_MIN_1FC))); + } + + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalFieldOff(void) { + /* Check whether a TxRx is not yet finished */ + if(gRFAL.TxRx.state != RFAL_TXRX_STATE_IDLE) { + rfalCleanupTransceive(); + } + + /* Disable Tx and Rx */ + st25r3916TxRxOff(); + + /* Set Analog configurations for Field Off event */ + rfalSetAnalogConfig((RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_FIELD_OFF)); + gRFAL.field = false; + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalStartTransceive(const rfalTransceiveContext* ctx) { + uint32_t FxTAdj; /* FWT or FDT adjustment calculation */ + + /* Check for valid parameters */ + if(ctx == NULL) { + return ERR_PARAM; + } + + /* Ensure that RFAL is already Initialized and the mode has been set */ + if((gRFAL.state >= RFAL_STATE_MODE_SET) /*&& (gRFAL.TxRx.state == RFAL_TXRX_STATE_INIT )*/) { + /*******************************************************************************/ + /* Check whether the field is already On, otherwise no TXE will be received */ + if(!st25r3916IsTxEnabled() && + (!rfalIsModePassiveListen(gRFAL.mode) && (ctx->txBuf != NULL))) { + return ERR_WRONG_STATE; + } + + gRFAL.TxRx.ctx = *ctx; + + /*******************************************************************************/ + if(gRFAL.timings.FDTListen != RFAL_TIMING_NONE) { + /* Calculate MRT adjustment accordingly to the current mode */ + FxTAdj = RFAL_FDT_LISTEN_MRT_ADJUSTMENT; + if(gRFAL.mode == RFAL_MODE_POLL_NFCA) { + FxTAdj += (uint32_t)RFAL_FDT_LISTEN_A_ADJUSTMENT; + } + if(gRFAL.mode == RFAL_MODE_POLL_NFCA_T1T) { + FxTAdj += (uint32_t)RFAL_FDT_LISTEN_A_ADJUSTMENT; + } + if(gRFAL.mode == RFAL_MODE_POLL_NFCB) { + FxTAdj += (uint32_t)RFAL_FDT_LISTEN_B_ADJUSTMENT; + } + if(gRFAL.mode == RFAL_MODE_POLL_NFCV) { + FxTAdj += (uint32_t)RFAL_FDT_LISTEN_V_ADJUSTMENT; + } + + /* Ensure that MRT is using 64/fc steps */ + st25r3916ClrRegisterBits( + ST25R3916_REG_TIMER_EMV_CONTROL, ST25R3916_REG_TIMER_EMV_CONTROL_mrt_step); + + /* If Correlator is being used further adjustment is required for NFCB */ + if((st25r3916CheckReg(ST25R3916_REG_AUX, ST25R3916_REG_AUX_dis_corr, 0x00U)) && + (gRFAL.mode == RFAL_MODE_POLL_NFCB)) { + FxTAdj += (uint32_t) + RFAL_FDT_LISTEN_B_ADJT_CORR; /* Reduce FDT(Listen) */ + st25r3916SetRegisterBits( + ST25R3916_REG_CORR_CONF1, + ST25R3916_REG_CORR_CONF1_corr_s3); /* Ensure BPSK start to 33 pilot pulses */ + st25r3916ChangeRegisterBits( + ST25R3916_REG_SUBC_START_TIME, + ST25R3916_REG_SUBC_START_TIME_sst_mask, + RFAL_FDT_LISTEN_B_ADJT_CORR_SST); /* Set sst */ + } + + /* Set Minimum FDT(Listen) in which PICC is not allowed to send a response */ + st25r3916WriteRegister( + ST25R3916_REG_MASK_RX_TIMER, + (uint8_t)rfalConv1fcTo64fc( + (FxTAdj > gRFAL.timings.FDTListen) ? RFAL_ST25R3916_MRT_MIN_1FC : + (gRFAL.timings.FDTListen - FxTAdj))); + } + + /*******************************************************************************/ + /* FDT Poll will be loaded in rfalPrepareTransceive() once the previous was expired */ + + /*******************************************************************************/ + if((gRFAL.TxRx.ctx.fwt != RFAL_FWT_NONE) && (gRFAL.TxRx.ctx.fwt != 0U)) { + /* Ensure proper timing configuration */ + if(gRFAL.timings.FDTListen >= gRFAL.TxRx.ctx.fwt) { + return ERR_PARAM; + } + + FxTAdj = RFAL_FWT_ADJUSTMENT; + if(gRFAL.mode == RFAL_MODE_POLL_NFCA) { + FxTAdj += (uint32_t)RFAL_FWT_A_ADJUSTMENT; + } + if(gRFAL.mode == RFAL_MODE_POLL_NFCA_T1T) { + FxTAdj += (uint32_t)RFAL_FWT_A_ADJUSTMENT; + } + if(gRFAL.mode == RFAL_MODE_POLL_NFCB) { + FxTAdj += (uint32_t)RFAL_FWT_B_ADJUSTMENT; + } + if((gRFAL.mode == RFAL_MODE_POLL_NFCF) || (gRFAL.mode == RFAL_MODE_POLL_ACTIVE_P2P)) { + FxTAdj += (uint32_t)((gRFAL.txBR == RFAL_BR_212) ? RFAL_FWT_F_212_ADJUSTMENT : + RFAL_FWT_F_424_ADJUSTMENT); + } + + /* Ensure that the given FWT doesn't exceed NRT maximum */ + gRFAL.TxRx.ctx.fwt = MIN((gRFAL.TxRx.ctx.fwt + FxTAdj), RFAL_ST25R3916_NRT_MAX_1FC); + + /* Set FWT in the NRT */ + st25r3916SetNoResponseTime(rfalConv1fcTo64fc(gRFAL.TxRx.ctx.fwt)); + } else { + /* Disable NRT, no NRE will be triggered, therefore wait endlessly for Rx */ + st25r3916SetNoResponseTime(RFAL_ST25R3916_NRT_DISABLED); + } + + gRFAL.state = RFAL_STATE_TXRX; + gRFAL.TxRx.state = RFAL_TXRX_STATE_TX_IDLE; + gRFAL.TxRx.status = ERR_BUSY; + +#if RFAL_FEATURE_NFCV + /*******************************************************************************/ + if((RFAL_MODE_POLL_NFCV == gRFAL.mode) || + (RFAL_MODE_POLL_PICOPASS == + gRFAL.mode)) { /* Exchange receive buffer with internal buffer */ + gRFAL.nfcvData.origCtx = gRFAL.TxRx.ctx; + + gRFAL.TxRx.ctx.rxBuf = + ((gRFAL.nfcvData.origCtx.rxBuf != NULL) ? gRFAL.nfcvData.codingBuffer : NULL); + gRFAL.TxRx.ctx.rxBufLen = + (uint16_t)rfalConvBytesToBits(sizeof(gRFAL.nfcvData.codingBuffer)); + gRFAL.TxRx.ctx.flags = + (uint32_t)RFAL_TXRX_FLAGS_CRC_TX_MANUAL | (uint32_t)RFAL_TXRX_FLAGS_CRC_RX_KEEP | + (uint32_t)RFAL_TXRX_FLAGS_NFCIP1_OFF | + (uint32_t)(gRFAL.nfcvData.origCtx.flags & (uint32_t)RFAL_TXRX_FLAGS_AGC_OFF) | + (uint32_t)RFAL_TXRX_FLAGS_PAR_RX_KEEP | (uint32_t)RFAL_TXRX_FLAGS_PAR_TX_NONE; + + /* In NFCV a TxRx with a valid txBuf and txBufSize==0 indicates to send an EOF */ + /* Skip logic below that would go directly into receive */ + if(gRFAL.TxRx.ctx.txBuf != NULL) { + return ERR_NONE; + } + } +#endif /* RFAL_FEATURE_NFCV */ + + /*******************************************************************************/ + /* Check if the Transceive start performing Tx or goes directly to Rx */ + if((gRFAL.TxRx.ctx.txBuf == NULL) || (gRFAL.TxRx.ctx.txBufLen == 0U)) { + /* Clear FIFO, Clear and Enable the Interrupts */ + rfalPrepareTransceive(); + + /* In AP2P check the field status */ + if(rfalIsModeActiveComm(gRFAL.mode)) { + /* Disable our field upon a Rx reEnable, and start PPON2 manually */ + st25r3916TxOff(); + st25r3916ExecuteCommand(ST25R3916_CMD_START_PPON2_TIMER); + } + + /* No Tx done, enable the Receiver */ + st25r3916ExecuteCommand(ST25R3916_CMD_UNMASK_RECEIVE_DATA); + + /* Start NRT manually, if FWT = 0 (wait endlessly for Rx) chip will ignore anyhow */ + st25r3916ExecuteCommand(ST25R3916_CMD_START_NO_RESPONSE_TIMER); + + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_IDLE; + } + + return ERR_NONE; + } + + return ERR_WRONG_STATE; +} + +/*******************************************************************************/ +bool rfalIsTransceiveInTx(void) { + return ( + (gRFAL.TxRx.state >= RFAL_TXRX_STATE_TX_IDLE) && + (gRFAL.TxRx.state < RFAL_TXRX_STATE_RX_IDLE)); +} + +/*******************************************************************************/ +bool rfalIsTransceiveInRx(void) { + return (gRFAL.TxRx.state >= RFAL_TXRX_STATE_RX_IDLE); +} + +/*******************************************************************************/ +ReturnCode rfalTransceiveBlockingTx( + uint8_t* txBuf, + uint16_t txBufLen, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* actLen, + uint32_t flags, + uint32_t fwt) { + ReturnCode ret; + rfalTransceiveContext ctx; + + rfalCreateByteFlagsTxRxContext(ctx, txBuf, txBufLen, rxBuf, rxBufLen, actLen, flags, fwt); + EXIT_ON_ERR(ret, rfalStartTransceive(&ctx)); + + return rfalTransceiveRunBlockingTx(); +} + +ReturnCode rfalTransceiveBitsBlockingTx( + uint8_t* txBuf, + uint16_t txBufLen, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* actLen, + uint32_t flags, + uint32_t fwt) { + ReturnCode ret; + rfalTransceiveContext ctx = { + .rxBuf = rxBuf, + .rxBufLen = rxBufLen, + .rxRcvdLen = actLen, + .txBuf = txBuf, + .txBufLen = txBufLen, + .flags = flags, + .fwt = fwt, + }; + + EXIT_ON_ERR(ret, rfalStartTransceive(&ctx)); + + return rfalTransceiveRunBlockingTx(); +} + +/*******************************************************************************/ +static ReturnCode rfalTransceiveRunBlockingTx(void) { + ReturnCode ret; + + do { + rfalWorker(); + ret = rfalGetTransceiveStatus(); + } while(rfalIsTransceiveInTx() && (ret == ERR_BUSY)); + + if(rfalIsTransceiveInRx()) { + return ERR_NONE; + } + + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalTransceiveBlockingRx(void) { + ReturnCode ret; + + do { + rfalWorker(); + ret = rfalGetTransceiveStatus(); + } while(rfalIsTransceiveInRx() && (ret == ERR_BUSY)); + + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalTransceiveBlockingTxRx( + uint8_t* txBuf, + uint16_t txBufLen, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* actLen, + uint32_t flags, + uint32_t fwt) { + ReturnCode ret; + + EXIT_ON_ERR( + ret, rfalTransceiveBlockingTx(txBuf, txBufLen, rxBuf, rxBufLen, actLen, flags, fwt)); + ret = rfalTransceiveBlockingRx(); + + /* Convert received bits to bytes */ + if(actLen != NULL) { + *actLen = rfalConvBitsToBytes(*actLen); + } + + return ret; +} + +ReturnCode rfalTransceiveBitsBlockingTxRx( + uint8_t* txBuf, + uint16_t txBufLen, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* actLen, + uint32_t flags, + uint32_t fwt) { + ReturnCode ret; + + EXIT_ON_ERR( + ret, rfalTransceiveBitsBlockingTx(txBuf, txBufLen, rxBuf, rxBufLen, actLen, flags, fwt)); + ret = rfalTransceiveBlockingRx(); + + return ret; +} + +/*******************************************************************************/ +static ReturnCode rfalRunTransceiveWorker(void) { + if(gRFAL.state == RFAL_STATE_TXRX) { + /*******************************************************************************/ + /* Check Transceive Sanity Timer has expired */ + if(gRFAL.tmr.txRx != RFAL_TIMING_NONE) { + if(rfalTimerisExpired(gRFAL.tmr.txRx)) { + /* If sanity timer has expired abort ongoing transceive and signal error */ + gRFAL.TxRx.status = ERR_IO; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + } + } + + /*******************************************************************************/ + /* Run Tx or Rx state machines */ + if(rfalIsTransceiveInTx()) { + rfalTransceiveTx(); + return rfalGetTransceiveStatus(); + } + if(rfalIsTransceiveInRx()) { + rfalTransceiveRx(); + return rfalGetTransceiveStatus(); + } + } + return ERR_WRONG_STATE; +} + +/*******************************************************************************/ +rfalTransceiveState rfalGetTransceiveState(void) { + return gRFAL.TxRx.state; +} + +/*******************************************************************************/ +ReturnCode rfalGetTransceiveStatus(void) { + return ((gRFAL.TxRx.state == RFAL_TXRX_STATE_IDLE) ? gRFAL.TxRx.status : ERR_BUSY); +} + +/*******************************************************************************/ +ReturnCode rfalGetTransceiveRSSI(uint16_t* rssi) { + uint16_t amRSSI; + uint16_t pmRSSI; + bool isSumMode; + + if(rssi == NULL) { + return ERR_PARAM; + } + + st25r3916GetRSSI(&amRSSI, &pmRSSI); + + /* Check if Correlator Summation mode is being used */ + isSumMode = + (st25r3916CheckReg( + ST25R3916_REG_CORR_CONF1, + ST25R3916_REG_CORR_CONF1_corr_s4, + ST25R3916_REG_CORR_CONF1_corr_s4) ? + st25r3916CheckReg(ST25R3916_REG_AUX, ST25R3916_REG_AUX_dis_corr, 0x00) : + false); + if(isSumMode) { + /*******************************************************************************/ + /* Using SQRT from math.h and float. If due to compiler, resources or performance + * issue this cannot be used, other approaches can be foreseen with less accuracy: + * Use a simpler sqrt algorithm + * *rssi = MAX( amRSSI, pmRSSI ); + * *rssi = ( (amRSSI + pmRSSI) / 2); + */ + *rssi = (uint16_t)sqrt( + ((double)amRSSI * (double)amRSSI) + + ((double)pmRSSI * + (double) + pmRSSI)); /* PRQA S 5209 # MISRA 4.9 - External function (sqrt()) requires double */ + } else { + /* Check which channel was used */ + *rssi = + (st25r3916CheckReg( + ST25R3916_REG_AUX_DISPLAY, + ST25R3916_REG_AUX_DISPLAY_a_cha, + ST25R3916_REG_AUX_DISPLAY_a_cha) ? + pmRSSI : + amRSSI); + } + return ERR_NONE; +} + +/*******************************************************************************/ +void rfalWorker(void) { + platformProtectWorker(); /* Protect RFAL Worker/Task/Process */ + + switch(gRFAL.state) { + case RFAL_STATE_TXRX: + rfalRunTransceiveWorker(); + break; + +#if RFAL_FEATURE_LISTEN_MODE + case RFAL_STATE_LM: + rfalRunListenModeWorker(); + break; +#endif /* RFAL_FEATURE_LISTEN_MODE */ + +#if RFAL_FEATURE_WAKEUP_MODE + case RFAL_STATE_WUM: + rfalRunWakeUpModeWorker(); + break; +#endif /* RFAL_FEATURE_WAKEUP_MODE */ + + /* Nothing to be done */ + default: + /* MISRA 16.4: no empty default statement (a comment being enough) */ + break; + } + + platformUnprotectWorker(); /* Unprotect RFAL Worker/Task/Process */ +} + +/*******************************************************************************/ +static void rfalErrorHandling(void) { + uint16_t fifoBytesToRead; + + fifoBytesToRead = rfalFIFOStatusGetNumBytes(); + +#ifdef RFAL_SW_EMD + /*******************************************************************************/ + /* EMVCo */ + /*******************************************************************************/ + if(gRFAL.conf.eHandling == RFAL_ERRORHANDLING_EMVCO) { + bool rxHasIncParError; + + /*******************************************************************************/ + /* EMD Handling - NFC Forum Digital 1.1 4.1.1.1 ; EMVCo v2.5 4.9.2 */ + /* ReEnable the receiver on frames with a length < 4 bytes, upon: */ + /* - Collision or Framing error detected */ + /* - Residual bits are detected (hard framing error) */ + /* - Parity error */ + /* - CRC error */ + /*******************************************************************************/ + + /* Check if reception has incomplete bytes or parity error */ + rxHasIncParError = + (rfalFIFOStatusIsIncompleteByte() ? true : + rfalFIFOStatusIsMissingPar()); /* MISRA 13.5 */ + + /* In case there are residual bits decrement FIFO bytes */ + /* Ensure FIFO contains some byte as the FIFO might be empty upon Framing errors */ + if((fifoBytesToRead > 0U) && rxHasIncParError) { + fifoBytesToRead--; + } + + if(((gRFAL.fifo.bytesTotal + fifoBytesToRead) < RFAL_EMVCO_RX_MAXLEN) && + ((gRFAL.TxRx.status == ERR_RF_COLLISION) || (gRFAL.TxRx.status == ERR_FRAMING) || + (gRFAL.TxRx.status == ERR_PAR) || (gRFAL.TxRx.status == ERR_CRC) || + rxHasIncParError)) { + /* Ignore this reception, ReEnable receiver which also clears the FIFO */ + st25r3916ExecuteCommand(ST25R3916_CMD_UNMASK_RECEIVE_DATA); + + /* Ensure that the NRT has not expired meanwhile */ + if(st25r3916CheckReg( + ST25R3916_REG_NFCIP1_BIT_RATE, ST25R3916_REG_NFCIP1_BIT_RATE_nrt_on, 0x00)) { + if(st25r3916CheckReg( + ST25R3916_REG_AUX_DISPLAY, ST25R3916_REG_AUX_DISPLAY_rx_act, 0x00)) { + /* Abort reception */ + st25r3916ExecuteCommand(ST25R3916_CMD_MASK_RECEIVE_DATA); + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + return; + } + } + + rfalFIFOStatusClear(); + gRFAL.fifo.bytesTotal = 0; + gRFAL.TxRx.status = ERR_BUSY; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_WAIT_RXS; + } + return; + } +#endif + + /*******************************************************************************/ + /* ISO14443A Mode */ + /*******************************************************************************/ + if(gRFAL.mode == RFAL_MODE_POLL_NFCA) { + /*******************************************************************************/ + /* If we received a frame with a incomplete byte we`ll raise a specific error * + * ( support for T2T 4 bit ACK / NAK, MIFARE and Kovio ) */ + /*******************************************************************************/ + if((gRFAL.TxRx.status == ERR_PAR) || (gRFAL.TxRx.status == ERR_CRC)) { + if(rfalFIFOStatusIsIncompleteByte()) { + st25r3916ReadFifo((uint8_t*)(gRFAL.TxRx.ctx.rxBuf), fifoBytesToRead); + if((gRFAL.TxRx.ctx.rxRcvdLen) != NULL) { + *gRFAL.TxRx.ctx.rxRcvdLen = rfalFIFOGetNumIncompleteBits(); + } + + gRFAL.TxRx.status = ERR_INCOMPLETE_BYTE; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + } + } + } +} + +/*******************************************************************************/ +static void rfalCleanupTransceive(void) { + /*******************************************************************************/ + /* Transceive flags */ + /*******************************************************************************/ + + /* Restore default settings on NFCIP1 mode, Receiving parity + CRC bits and manual Tx Parity*/ + st25r3916ClrRegisterBits( + ST25R3916_REG_ISO14443A_NFC, + (ST25R3916_REG_ISO14443A_NFC_no_tx_par | ST25R3916_REG_ISO14443A_NFC_no_rx_par | + ST25R3916_REG_ISO14443A_NFC_nfc_f0)); + + /* Restore AGC enabled */ + st25r3916SetRegisterBits(ST25R3916_REG_RX_CONF2, ST25R3916_REG_RX_CONF2_agc_en); + + /*******************************************************************************/ + + /*******************************************************************************/ + /* Transceive timers */ + /*******************************************************************************/ + rfalTimerDestroy(gRFAL.tmr.txRx); + rfalTimerDestroy(gRFAL.tmr.RXE); + gRFAL.tmr.txRx = RFAL_TIMING_NONE; + gRFAL.tmr.RXE = RFAL_TIMING_NONE; + /*******************************************************************************/ + + /*******************************************************************************/ + /* Execute Post Transceive Callback */ + /*******************************************************************************/ + if(gRFAL.callbacks.postTxRx != NULL) { + gRFAL.callbacks.postTxRx(gRFAL.callbacks.ctx); + } + /*******************************************************************************/ +} + +/*******************************************************************************/ +static void rfalPrepareTransceive(void) { + uint32_t maskInterrupts; + uint8_t reg; + + /* If we are in RW or AP2P mode */ + if(!rfalIsModePassiveListen(gRFAL.mode)) { + /* Reset receive logic with STOP command */ + st25r3916ExecuteCommand(ST25R3916_CMD_STOP); + + /* Reset Rx Gain */ + st25r3916ExecuteCommand(ST25R3916_CMD_RESET_RXGAIN); + } else { + /* In Passive Listen Mode do not use STOP as it stops FDT timer */ + st25r3916ExecuteCommand(ST25R3916_CMD_CLEAR_FIFO); + } + + /*******************************************************************************/ + /* FDT Poll */ + /*******************************************************************************/ + if(rfalIsModePassiveComm(gRFAL.mode)) /* Passive Comms */ + { + /* In Passive communications General Purpose Timer is used to measure FDT Poll */ + if(gRFAL.timings.FDTPoll != RFAL_TIMING_NONE) { + /* Configure GPT to start at RX end */ + st25r3916SetStartGPTimer( + (uint16_t)rfalConv1fcTo8fc(MIN( + gRFAL.timings.FDTPoll, (gRFAL.timings.FDTPoll - RFAL_FDT_POLL_ADJUSTMENT))), + ST25R3916_REG_TIMER_EMV_CONTROL_gptc_erx); + } + } + + /*******************************************************************************/ + /* Execute Pre Transceive Callback */ + /*******************************************************************************/ + if(gRFAL.callbacks.preTxRx != NULL) { + gRFAL.callbacks.preTxRx(gRFAL.callbacks.ctx); + } + /*******************************************************************************/ + + maskInterrupts = + (ST25R3916_IRQ_MASK_FWL | ST25R3916_IRQ_MASK_TXE | ST25R3916_IRQ_MASK_RXS | + ST25R3916_IRQ_MASK_RXE | ST25R3916_IRQ_MASK_PAR | ST25R3916_IRQ_MASK_CRC | + ST25R3916_IRQ_MASK_ERR1 | ST25R3916_IRQ_MASK_ERR2 | ST25R3916_IRQ_MASK_NRE); + + /*******************************************************************************/ + /* Transceive flags */ + /*******************************************************************************/ + + reg = + (ST25R3916_REG_ISO14443A_NFC_no_tx_par_off | ST25R3916_REG_ISO14443A_NFC_no_rx_par_off | + ST25R3916_REG_ISO14443A_NFC_nfc_f0_off); + + /* Check if NFCIP1 mode is to be enabled */ + if((gRFAL.TxRx.ctx.flags & (uint8_t)RFAL_TXRX_FLAGS_NFCIP1_ON) != 0U) { + reg |= ST25R3916_REG_ISO14443A_NFC_nfc_f0; + } + + /* Check if Parity check is to be skipped and to keep the parity + CRC bits in FIFO */ + if((gRFAL.TxRx.ctx.flags & (uint8_t)RFAL_TXRX_FLAGS_PAR_RX_KEEP) != 0U) { + reg |= ST25R3916_REG_ISO14443A_NFC_no_rx_par; + } + + /* Check if automatic Parity bits is to be disabled */ + if((gRFAL.TxRx.ctx.flags & (uint8_t)RFAL_TXRX_FLAGS_PAR_TX_NONE) != 0U) { + reg |= ST25R3916_REG_ISO14443A_NFC_no_tx_par; + } + + /* Apply current TxRx flags on ISO14443A and NFC 106kb/s Settings Register */ + st25r3916ChangeRegisterBits( + ST25R3916_REG_ISO14443A_NFC, + (ST25R3916_REG_ISO14443A_NFC_no_tx_par | ST25R3916_REG_ISO14443A_NFC_no_rx_par | + ST25R3916_REG_ISO14443A_NFC_nfc_f0), + reg); + + /* Check if AGC is to be disabled */ + if((gRFAL.TxRx.ctx.flags & (uint8_t)RFAL_TXRX_FLAGS_AGC_OFF) != 0U) { + st25r3916ClrRegisterBits(ST25R3916_REG_RX_CONF2, ST25R3916_REG_RX_CONF2_agc_en); + } else { + st25r3916SetRegisterBits(ST25R3916_REG_RX_CONF2, ST25R3916_REG_RX_CONF2_agc_en); + } + /*******************************************************************************/ + + /*******************************************************************************/ + /* EMVCo NRT mode */ + /*******************************************************************************/ + if(gRFAL.conf.eHandling == RFAL_ERRORHANDLING_EMVCO) { + st25r3916SetRegisterBits( + ST25R3916_REG_TIMER_EMV_CONTROL, ST25R3916_REG_TIMER_EMV_CONTROL_nrt_emv); + maskInterrupts |= ST25R3916_IRQ_MASK_RX_REST; + } else { + st25r3916ClrRegisterBits( + ST25R3916_REG_TIMER_EMV_CONTROL, ST25R3916_REG_TIMER_EMV_CONTROL_nrt_emv); + } + /*******************************************************************************/ + + /* In Passive Listen mode additionally enable External Field interrupts */ + if(rfalIsModePassiveListen(gRFAL.mode)) { + maskInterrupts |= + (ST25R3916_IRQ_MASK_EOF | + ST25R3916_IRQ_MASK_WU_F); /* Enable external Field interrupts to detect Link Loss and SENF_REQ auto responses */ + } + + /* In Active comms enable also External Field interrupts and set RF Collision Avoindance */ + if(rfalIsModeActiveComm(gRFAL.mode)) { + maskInterrupts |= + (ST25R3916_IRQ_MASK_EOF | ST25R3916_IRQ_MASK_EON | ST25R3916_IRQ_MASK_PPON2 | + ST25R3916_IRQ_MASK_CAT | ST25R3916_IRQ_MASK_CAC); + + /* Set n=0 for subsequent RF Collision Avoidance */ + st25r3916ChangeRegisterBits(ST25R3916_REG_AUX, ST25R3916_REG_AUX_nfc_n_mask, 0); + } + + /*******************************************************************************/ + /* Start transceive Sanity Timer if a FWT is used */ + if((gRFAL.TxRx.ctx.fwt != RFAL_FWT_NONE) && (gRFAL.TxRx.ctx.fwt != 0U)) { + rfalTimerStart(gRFAL.tmr.txRx, rfalCalcSanityTmr(gRFAL.TxRx.ctx.fwt)); + } + /*******************************************************************************/ + + /*******************************************************************************/ + /* Clear and enable these interrupts */ + st25r3916GetInterrupt(maskInterrupts); + st25r3916EnableInterrupts(maskInterrupts); + + /* Clear FIFO status local copy */ + rfalFIFOStatusClear(); +} + +/*******************************************************************************/ +static void rfalTransceiveTx(void) { + volatile uint32_t irqs; + uint16_t tmp; + ReturnCode ret; + + /* Suppress warning in case NFC-V feature is disabled */ + ret = ERR_NONE; + NO_WARNING(ret); + + irqs = ST25R3916_IRQ_MASK_NONE; + + if(gRFAL.TxRx.state != gRFAL.TxRx.lastState) { + /* rfalLogD( "RFAL: lastSt: %d curSt: %d \r\n", gRFAL.TxRx.lastState, gRFAL.TxRx.state ); */ + gRFAL.TxRx.lastState = gRFAL.TxRx.state; + } + + switch(gRFAL.TxRx.state) { + /*******************************************************************************/ + case RFAL_TXRX_STATE_TX_IDLE: + + /* Nothing to do */ + + gRFAL.TxRx.state = RFAL_TXRX_STATE_TX_WAIT_GT; + /* fall through */ + + /*******************************************************************************/ + case RFAL_TXRX_STATE_TX_WAIT_GT: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + + if(!rfalIsGTExpired()) { + break; + } + + rfalTimerDestroy(gRFAL.tmr.GT); + gRFAL.tmr.GT = RFAL_TIMING_NONE; + + gRFAL.TxRx.state = RFAL_TXRX_STATE_TX_WAIT_FDT; + /* fall through */ + + /*******************************************************************************/ + case RFAL_TXRX_STATE_TX_WAIT_FDT: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + + /* Only in Passive communications GPT is used to measure FDT Poll */ + if(rfalIsModePassiveComm(gRFAL.mode)) { + if(st25r3916IsGPTRunning()) { + break; + } + } + + gRFAL.TxRx.state = RFAL_TXRX_STATE_TX_TRANSMIT; + /* fall through */ + + /*******************************************************************************/ + case RFAL_TXRX_STATE_TX_TRANSMIT: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + + /* Clear FIFO, Clear and Enable the Interrupts */ + rfalPrepareTransceive(); + + /* ST25R3916 has a fixed FIFO water level */ + gRFAL.fifo.expWL = RFAL_FIFO_OUT_WL; + +#if RFAL_FEATURE_NFCV + /*******************************************************************************/ + /* In NFC-V streaming mode, the FIFO needs to be loaded with the coded bits */ + if((RFAL_MODE_POLL_NFCV == gRFAL.mode) || (RFAL_MODE_POLL_PICOPASS == gRFAL.mode)) { +#if 0 + /* Debugging code: output the payload bits by writing into the FIFO and subsequent clearing */ + st25r3916WriteFifo(gRFAL.TxRx.ctx.txBuf, rfalConvBitsToBytes(gRFAL.TxRx.ctx.txBufLen)); + st25r3916ExecuteCommand( ST25R3916_CMD_CLEAR_FIFO ); +#endif + /* Calculate the bytes needed to be Written into FIFO (a incomplete byte will be added as 1byte) */ + gRFAL.nfcvData.nfcvOffset = 0; + ret = iso15693VCDCode( + gRFAL.TxRx.ctx.txBuf, + rfalConvBitsToBytes(gRFAL.TxRx.ctx.txBufLen), + (((gRFAL.nfcvData.origCtx.flags & (uint32_t)RFAL_TXRX_FLAGS_CRC_TX_MANUAL) != 0U) ? + false : + true), + (((gRFAL.nfcvData.origCtx.flags & (uint32_t)RFAL_TXRX_FLAGS_NFCV_FLAG_MANUAL) != + 0U) ? + false : + true), + (RFAL_MODE_POLL_PICOPASS == gRFAL.mode), + &gRFAL.fifo.bytesTotal, + &gRFAL.nfcvData.nfcvOffset, + gRFAL.nfcvData.codingBuffer, + MIN((uint16_t)ST25R3916_FIFO_DEPTH, (uint16_t)sizeof(gRFAL.nfcvData.codingBuffer)), + &gRFAL.fifo.bytesWritten); + + if((ret != ERR_NONE) && (ret != ERR_AGAIN)) { + gRFAL.TxRx.status = ret; + gRFAL.TxRx.state = RFAL_TXRX_STATE_TX_FAIL; + break; + } + /* Set the number of full bytes and bits to be transmitted */ + st25r3916SetNumTxBits((uint16_t)rfalConvBytesToBits(gRFAL.fifo.bytesTotal)); + + /* Load FIFO with coded bytes */ + st25r3916WriteFifo(gRFAL.nfcvData.codingBuffer, gRFAL.fifo.bytesWritten); + + } + /*******************************************************************************/ + else +#endif /* RFAL_FEATURE_NFCV */ + { + /* Calculate the bytes needed to be Written into FIFO (a incomplete byte will be added as 1byte) */ + gRFAL.fifo.bytesTotal = (uint16_t)rfalCalcNumBytes(gRFAL.TxRx.ctx.txBufLen); + + /* Set the number of full bytes and bits to be transmitted */ + st25r3916SetNumTxBits(gRFAL.TxRx.ctx.txBufLen); + + /* Load FIFO with total length or FIFO's maximum */ + gRFAL.fifo.bytesWritten = MIN(gRFAL.fifo.bytesTotal, ST25R3916_FIFO_DEPTH); + st25r3916WriteFifo(gRFAL.TxRx.ctx.txBuf, gRFAL.fifo.bytesWritten); + } + + /*Check if Observation Mode is enabled and set it on ST25R391x */ + rfalCheckEnableObsModeTx(); + + /*******************************************************************************/ + /* If we're in Passive Listen mode ensure that the external field is still On */ + if(rfalIsModePassiveListen(gRFAL.mode)) { + if(!rfalIsExtFieldOn()) { + gRFAL.TxRx.status = ERR_LINK_LOSS; + gRFAL.TxRx.state = RFAL_TXRX_STATE_TX_FAIL; + break; + } + } + + /*******************************************************************************/ + /* Trigger/Start transmission */ + if((gRFAL.TxRx.ctx.flags & (uint32_t)RFAL_TXRX_FLAGS_CRC_TX_MANUAL) != 0U) { + st25r3916ExecuteCommand(ST25R3916_CMD_TRANSMIT_WITHOUT_CRC); + } else { + st25r3916ExecuteCommand(ST25R3916_CMD_TRANSMIT_WITH_CRC); + } + + /* Check if a WL level is expected or TXE should come */ + gRFAL.TxRx.state = + ((gRFAL.fifo.bytesWritten < gRFAL.fifo.bytesTotal) ? RFAL_TXRX_STATE_TX_WAIT_WL : + RFAL_TXRX_STATE_TX_WAIT_TXE); + break; + + /*******************************************************************************/ + case RFAL_TXRX_STATE_TX_WAIT_WL: + + irqs = st25r3916GetInterrupt((ST25R3916_IRQ_MASK_FWL | ST25R3916_IRQ_MASK_TXE)); + if(irqs == ST25R3916_IRQ_MASK_NONE) { + break; /* No interrupt to process */ + } + + if(((irqs & ST25R3916_IRQ_MASK_FWL) != 0U) && ((irqs & ST25R3916_IRQ_MASK_TXE) == 0U)) { + gRFAL.TxRx.state = RFAL_TXRX_STATE_TX_RELOAD_FIFO; + } else { + gRFAL.TxRx.status = ERR_IO; + gRFAL.TxRx.state = RFAL_TXRX_STATE_TX_FAIL; + break; + } + + /* fall through */ + + /*******************************************************************************/ + case RFAL_TXRX_STATE_TX_RELOAD_FIFO: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + +#if RFAL_FEATURE_NFCV + /*******************************************************************************/ + /* In NFC-V streaming mode, the FIFO needs to be loaded with the coded bits */ + if((RFAL_MODE_POLL_NFCV == gRFAL.mode) || (RFAL_MODE_POLL_PICOPASS == gRFAL.mode)) { + uint16_t maxLen; + + /* Load FIFO with the remaining length or maximum available (which fit on the coding buffer) */ + maxLen = + (uint16_t)MIN((gRFAL.fifo.bytesTotal - gRFAL.fifo.bytesWritten), gRFAL.fifo.expWL); + maxLen = (uint16_t)MIN(maxLen, sizeof(gRFAL.nfcvData.codingBuffer)); + tmp = 0; + + /* Calculate the bytes needed to be Written into FIFO (a incomplete byte will be added as 1byte) */ + ret = iso15693VCDCode( + gRFAL.TxRx.ctx.txBuf, + rfalConvBitsToBytes(gRFAL.TxRx.ctx.txBufLen), + (((gRFAL.nfcvData.origCtx.flags & (uint32_t)RFAL_TXRX_FLAGS_CRC_TX_MANUAL) != 0U) ? + false : + true), + (((gRFAL.nfcvData.origCtx.flags & (uint32_t)RFAL_TXRX_FLAGS_NFCV_FLAG_MANUAL) != + 0U) ? + false : + true), + (RFAL_MODE_POLL_PICOPASS == gRFAL.mode), + &gRFAL.fifo.bytesTotal, + &gRFAL.nfcvData.nfcvOffset, + gRFAL.nfcvData.codingBuffer, + maxLen, + &tmp); + + if((ret != ERR_NONE) && (ret != ERR_AGAIN)) { + gRFAL.TxRx.status = ret; + gRFAL.TxRx.state = RFAL_TXRX_STATE_TX_FAIL; + break; + } + + /* Load FIFO with coded bytes */ + st25r3916WriteFifo(gRFAL.nfcvData.codingBuffer, tmp); + } + /*******************************************************************************/ + else +#endif /* RFAL_FEATURE_NFCV */ + { + /* Load FIFO with the remaining length or maximum available */ + tmp = MIN( + (gRFAL.fifo.bytesTotal - gRFAL.fifo.bytesWritten), + gRFAL.fifo.expWL); /* tmp holds the number of bytes written on this iteration */ + st25r3916WriteFifo(&gRFAL.TxRx.ctx.txBuf[gRFAL.fifo.bytesWritten], tmp); + } + + /* Update total written bytes to FIFO */ + gRFAL.fifo.bytesWritten += tmp; + + /* Check if a WL level is expected or TXE should come */ + gRFAL.TxRx.state = + ((gRFAL.fifo.bytesWritten < gRFAL.fifo.bytesTotal) ? RFAL_TXRX_STATE_TX_WAIT_WL : + RFAL_TXRX_STATE_TX_WAIT_TXE); + break; + + /*******************************************************************************/ + case RFAL_TXRX_STATE_TX_WAIT_TXE: + + irqs = st25r3916GetInterrupt((ST25R3916_IRQ_MASK_FWL | ST25R3916_IRQ_MASK_TXE)); + if(irqs == ST25R3916_IRQ_MASK_NONE) { + break; /* No interrupt to process */ + } + + if((irqs & ST25R3916_IRQ_MASK_TXE) != 0U) { + gRFAL.TxRx.state = RFAL_TXRX_STATE_TX_DONE; + } else if((irqs & ST25R3916_IRQ_MASK_FWL) != 0U) { + break; /* Ignore ST25R3916 FIFO WL if total TxLen is already on the FIFO */ + } else { + gRFAL.TxRx.status = ERR_IO; + gRFAL.TxRx.state = RFAL_TXRX_STATE_TX_FAIL; + break; + } + + /* fall through */ + + /*******************************************************************************/ + case RFAL_TXRX_STATE_TX_DONE: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + + /* If no rxBuf is provided do not wait/expect Rx */ + if(gRFAL.TxRx.ctx.rxBuf == NULL) { + /*Check if Observation Mode was enabled and disable it on ST25R391x */ + rfalCheckDisableObsMode(); + + /* Clean up Transceive */ + rfalCleanupTransceive(); + + gRFAL.TxRx.status = ERR_NONE; + gRFAL.TxRx.state = RFAL_TXRX_STATE_IDLE; + break; + } + + rfalCheckEnableObsModeRx(); + + /* Goto Rx */ + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_IDLE; + break; + + /*******************************************************************************/ + case RFAL_TXRX_STATE_TX_FAIL: + + /* Error should be assigned by previous state */ + if(gRFAL.TxRx.status == ERR_BUSY) { + gRFAL.TxRx.status = ERR_SYSTEM; + } + + /*Check if Observation Mode was enabled and disable it on ST25R391x */ + rfalCheckDisableObsMode(); + + /* Clean up Transceive */ + rfalCleanupTransceive(); + + gRFAL.TxRx.state = RFAL_TXRX_STATE_IDLE; + break; + + /*******************************************************************************/ + default: + gRFAL.TxRx.status = ERR_SYSTEM; + gRFAL.TxRx.state = RFAL_TXRX_STATE_TX_FAIL; + break; + } +} + +/*******************************************************************************/ +static void rfalTransceiveRx(void) { + volatile uint32_t irqs; + uint16_t tmp; + uint16_t aux; + + irqs = ST25R3916_IRQ_MASK_NONE; + + if(gRFAL.TxRx.state != gRFAL.TxRx.lastState) { + /* rfalLogD( "RFAL: lastSt: %d curSt: %d \r\n", gRFAL.TxRx.lastState, gRFAL.TxRx.state ); */ + gRFAL.TxRx.lastState = gRFAL.TxRx.state; + } + + switch(gRFAL.TxRx.state) { + /*******************************************************************************/ + case RFAL_TXRX_STATE_RX_IDLE: + + /* Clear rx counters */ + gRFAL.fifo.bytesWritten = 0; /* Total bytes written on RxBuffer */ + gRFAL.fifo.bytesTotal = 0; /* Total bytes in FIFO will now be from Rx */ + if(gRFAL.TxRx.ctx.rxRcvdLen != NULL) { + *gRFAL.TxRx.ctx.rxRcvdLen = 0; + } + + gRFAL.TxRx.state = + (rfalIsModeActiveComm(gRFAL.mode) ? RFAL_TXRX_STATE_RX_WAIT_EON : + RFAL_TXRX_STATE_RX_WAIT_RXS); + break; + + /*******************************************************************************/ + case RFAL_TXRX_STATE_RX_WAIT_RXS: + + /*******************************************************************************/ + irqs = st25r3916GetInterrupt( + (ST25R3916_IRQ_MASK_RXS | ST25R3916_IRQ_MASK_NRE | ST25R3916_IRQ_MASK_EOF)); + if(irqs == ST25R3916_IRQ_MASK_NONE) { + break; /* No interrupt to process */ + } + + /* Only raise Timeout if NRE is detected with no Rx Start (NRT EMV mode) */ + if(((irqs & ST25R3916_IRQ_MASK_NRE) != 0U) && ((irqs & ST25R3916_IRQ_MASK_RXS) == 0U)) { + gRFAL.TxRx.status = ERR_TIMEOUT; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + break; + } + + /* Only raise Link Loss if EOF is detected with no Rx Start */ + if(((irqs & ST25R3916_IRQ_MASK_EOF) != 0U) && ((irqs & ST25R3916_IRQ_MASK_RXS) == 0U)) { + /* In AP2P a Field On has already occurred - treat this as timeout | mute */ + gRFAL.TxRx.status = (rfalIsModeActiveComm(gRFAL.mode) ? ERR_TIMEOUT : ERR_LINK_LOSS); + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + break; + } + + if((irqs & ST25R3916_IRQ_MASK_RXS) != 0U) { + /*******************************************************************************/ + /* REMARK: Silicon workaround ST25R3916 Errata #TBD */ + /* Rarely on corrupted frames I_rxs gets signaled but I_rxe is not signaled */ + /* Use a SW timer to handle an eventual missing RXE */ + rfalTimerStart(gRFAL.tmr.RXE, RFAL_NORXE_TOUT); + /*******************************************************************************/ + + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_WAIT_RXE; + } else { + gRFAL.TxRx.status = ERR_IO; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + break; + } + + /* remove NRE that might appear together (NRT EMV mode), and remove RXS, but keep EOF if present for next state */ + irqs &= ~(ST25R3916_IRQ_MASK_RXS | ST25R3916_IRQ_MASK_NRE); + + /* fall through */ + + /*******************************************************************************/ + case RFAL_TXRX_STATE_RX_WAIT_RXE: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + + /*******************************************************************************/ + /* REMARK: Silicon workaround ST25R3916 Errata #TBD */ + /* ST25R396 may indicate RXS without RXE afterwards, this happens rarely on */ + /* corrupted frames. */ + /* SW timer is used to timeout upon a missing RXE */ + if(rfalTimerisExpired(gRFAL.tmr.RXE)) { + gRFAL.TxRx.status = ERR_FRAMING; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + } + /*******************************************************************************/ + + irqs |= st25r3916GetInterrupt( + (ST25R3916_IRQ_MASK_RXE | ST25R3916_IRQ_MASK_FWL | ST25R3916_IRQ_MASK_EOF | + ST25R3916_IRQ_MASK_RX_REST | ST25R3916_IRQ_MASK_WU_F)); + if(irqs == ST25R3916_IRQ_MASK_NONE) { + break; /* No interrupt to process */ + } + + if((irqs & ST25R3916_IRQ_MASK_RX_REST) != 0U) { + /* RX_REST indicates that Receiver has been reset due to EMD, therefore a RXS + RXE should * + * follow if a good reception is followed within the valid initial timeout */ + + /* Check whether NRT has expired already, if so signal a timeout */ + if(st25r3916GetInterrupt(ST25R3916_IRQ_MASK_NRE) != 0U) { + gRFAL.TxRx.status = ERR_TIMEOUT; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + break; + } + if(st25r3916CheckReg( + ST25R3916_REG_NFCIP1_BIT_RATE, + ST25R3916_REG_NFCIP1_BIT_RATE_nrt_on, + 0)) /* MISRA 13.5 */ + { + gRFAL.TxRx.status = ERR_TIMEOUT; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + break; + } + + /* Discard any previous RXS */ + st25r3916GetInterrupt(ST25R3916_IRQ_MASK_RXS); + + /* Check whether a following reception has already started */ + if(st25r3916CheckReg( + ST25R3916_REG_AUX_DISPLAY, + ST25R3916_REG_AUX_DISPLAY_rx_act, + ST25R3916_REG_AUX_DISPLAY_rx_act)) { + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_WAIT_RXE; + break; + } + + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_WAIT_RXS; + break; + } + + if(((irqs & ST25R3916_IRQ_MASK_FWL) != 0U) && ((irqs & ST25R3916_IRQ_MASK_RXE) == 0U)) { + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_READ_FIFO; + break; + } + + /* Automatic responses allowed during TxRx only for the SENSF_REQ */ + if((irqs & ST25R3916_IRQ_MASK_WU_F) != 0U) { + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_WAIT_RXS; + break; + } + + /* After RXE retrieve and check for any error irqs */ + irqs |= st25r3916GetInterrupt( + (ST25R3916_IRQ_MASK_CRC | ST25R3916_IRQ_MASK_PAR | ST25R3916_IRQ_MASK_ERR1 | + ST25R3916_IRQ_MASK_ERR2 | ST25R3916_IRQ_MASK_COL)); + + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_ERR_CHECK; + /* fall through */ + + /*******************************************************************************/ + case RFAL_TXRX_STATE_RX_ERR_CHECK: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + + if((irqs & ST25R3916_IRQ_MASK_ERR1) != 0U) { + gRFAL.TxRx.status = ERR_FRAMING; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_READ_DATA; + + /* Check if there's a specific error handling for this */ + rfalErrorHandling(); + break; + } + /* Discard Soft Framing errors in AP2P and CE */ + else if(rfalIsModePassivePoll(gRFAL.mode) && ((irqs & ST25R3916_IRQ_MASK_ERR2) != 0U)) { + gRFAL.TxRx.status = ERR_FRAMING; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_READ_DATA; + + /* Check if there's a specific error handling for this */ + rfalErrorHandling(); + break; + } else if((irqs & ST25R3916_IRQ_MASK_PAR) != 0U) { + gRFAL.TxRx.status = ERR_PAR; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_READ_DATA; + + /* Check if there's a specific error handling for this */ + rfalErrorHandling(); + break; + } else if((irqs & ST25R3916_IRQ_MASK_CRC) != 0U) { + gRFAL.TxRx.status = ERR_CRC; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_READ_DATA; + + /* Check if there's a specific error handling for this */ + rfalErrorHandling(); + break; + } else if((irqs & ST25R3916_IRQ_MASK_COL) != 0U) { + gRFAL.TxRx.status = ERR_RF_COLLISION; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_READ_DATA; + + /* Check if there's a specific error handling for this */ + rfalErrorHandling(); + break; + } else if(rfalIsModePassiveListen(gRFAL.mode) && ((irqs & ST25R3916_IRQ_MASK_EOF) != 0U)) { + gRFAL.TxRx.status = ERR_LINK_LOSS; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + break; + } else if((irqs & ST25R3916_IRQ_MASK_RXE) != 0U) { + /* Reception ended without any error indication, * + * check FIFO status for malformed or incomplete frames */ + + /* Check if the reception ends with an incomplete byte (residual bits) */ + if(rfalFIFOStatusIsIncompleteByte()) { + gRFAL.TxRx.status = ERR_INCOMPLETE_BYTE; + } + /* Check if the reception ends missing parity bit */ + else if(rfalFIFOStatusIsMissingPar()) { + gRFAL.TxRx.status = ERR_FRAMING; + } else { + /* MISRA 15.7 - Empty else */ + } + + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_READ_DATA; + } else { + gRFAL.TxRx.status = ERR_IO; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + break; + } + + /* fall through */ + + /*******************************************************************************/ + case RFAL_TXRX_STATE_RX_READ_DATA: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + + tmp = rfalFIFOStatusGetNumBytes(); + + /*******************************************************************************/ + /* Check if CRC should not be placed in rxBuf */ + if(((gRFAL.TxRx.ctx.flags & (uint32_t)RFAL_TXRX_FLAGS_CRC_RX_KEEP) == 0U)) { + /* if received frame was bigger than CRC */ + if((uint16_t)(gRFAL.fifo.bytesTotal + tmp) > 0U) { + /* By default CRC will not be placed into the rxBuffer */ + if((tmp > RFAL_CRC_LEN)) { + tmp -= RFAL_CRC_LEN; + } + /* If the CRC was already placed into rxBuffer (due to WL interrupt where CRC was already in FIFO Read) + * cannot remove it from rxBuf. Can only remove it from rxBufLen not indicate the presence of CRC */ + else if(gRFAL.fifo.bytesTotal > RFAL_CRC_LEN) { + gRFAL.fifo.bytesTotal -= RFAL_CRC_LEN; + } else { + /* MISRA 15.7 - Empty else */ + } + } + } + + gRFAL.fifo.bytesTotal += tmp; /* add to total bytes counter */ + + /*******************************************************************************/ + /* Check if remaining bytes fit on the rxBuf available */ + if(gRFAL.fifo.bytesTotal > rfalConvBitsToBytes(gRFAL.TxRx.ctx.rxBufLen)) { + tmp = + (uint16_t)(rfalConvBitsToBytes(gRFAL.TxRx.ctx.rxBufLen) - gRFAL.fifo.bytesWritten); + + /* Transmission errors have precedence over buffer error */ + if(gRFAL.TxRx.status == ERR_BUSY) { + gRFAL.TxRx.status = ERR_NOMEM; + } + } + + /*******************************************************************************/ + /* Retrieve remaining bytes from FIFO to rxBuf, and assign total length rcvd */ + st25r3916ReadFifo(&gRFAL.TxRx.ctx.rxBuf[gRFAL.fifo.bytesWritten], tmp); + if(gRFAL.TxRx.ctx.rxRcvdLen != NULL) { + (*gRFAL.TxRx.ctx.rxRcvdLen) = (uint16_t)rfalConvBytesToBits(gRFAL.fifo.bytesTotal); + if(rfalFIFOStatusIsIncompleteByte()) { + (*gRFAL.TxRx.ctx.rxRcvdLen) -= + (RFAL_BITS_IN_BYTE - rfalFIFOGetNumIncompleteBits()); + } + } + +#if RFAL_FEATURE_NFCV + /*******************************************************************************/ + /* Decode sub bit stream into payload bits for NFCV, if no error found so far */ + if(((RFAL_MODE_POLL_NFCV == gRFAL.mode) || (RFAL_MODE_POLL_PICOPASS == gRFAL.mode)) && + (gRFAL.TxRx.status == ERR_BUSY)) { + ReturnCode ret; + uint16_t offset = 0; /* REMARK offset not currently used */ + + ret = iso15693VICCDecode( + gRFAL.TxRx.ctx.rxBuf, + gRFAL.fifo.bytesTotal, + gRFAL.nfcvData.origCtx.rxBuf, + rfalConvBitsToBytes(gRFAL.nfcvData.origCtx.rxBufLen), + &offset, + gRFAL.nfcvData.origCtx.rxRcvdLen, + gRFAL.nfcvData.ignoreBits, + (RFAL_MODE_POLL_PICOPASS == gRFAL.mode)); + + if(((ERR_NONE == ret) || (ERR_CRC == ret)) && + (((uint32_t)RFAL_TXRX_FLAGS_CRC_RX_KEEP & gRFAL.nfcvData.origCtx.flags) == 0U) && + ((*gRFAL.nfcvData.origCtx.rxRcvdLen % RFAL_BITS_IN_BYTE) == 0U) && + (*gRFAL.nfcvData.origCtx.rxRcvdLen >= rfalConvBytesToBits(RFAL_CRC_LEN))) { + *gRFAL.nfcvData.origCtx.rxRcvdLen -= + (uint16_t)rfalConvBytesToBits(RFAL_CRC_LEN); /* Remove CRC */ + } +#if 0 + /* Debugging code: output the payload bits by writing into the FIFO and subsequent clearing */ + st25r3916WriteFifo(gRFAL.nfcvData.origCtx.rxBuf, rfalConvBitsToBytes( *gRFAL.nfcvData.origCtx.rxRcvdLen)); + st25r3916ExecuteCommand( ST25R3916_CMD_CLEAR_FIFO ); +#endif + + /* Restore original ctx */ + gRFAL.TxRx.ctx = gRFAL.nfcvData.origCtx; + gRFAL.TxRx.status = ((ret != ERR_NONE) ? ret : ERR_BUSY); + } +#endif /* RFAL_FEATURE_NFCV */ + + /*******************************************************************************/ + /* If an error as been marked/detected don't fall into to RX_DONE */ + if(gRFAL.TxRx.status != ERR_BUSY) { + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + break; + } + + if(rfalIsModeActiveComm(gRFAL.mode)) { + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_WAIT_EOF; + break; + } + + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_DONE; + /* fall through */ + + /*******************************************************************************/ + case RFAL_TXRX_STATE_RX_DONE: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + + /*Check if Observation Mode was enabled and disable it on ST25R391x */ + rfalCheckDisableObsMode(); + + /* Clean up Transceive */ + rfalCleanupTransceive(); + + gRFAL.TxRx.status = ERR_NONE; + gRFAL.TxRx.state = RFAL_TXRX_STATE_IDLE; + break; + + /*******************************************************************************/ + case RFAL_TXRX_STATE_RX_READ_FIFO: + + /*******************************************************************************/ + /* REMARK: Silicon workaround ST25R3916 Errata #TBD */ + /* Rarely on corrupted frames I_rxs gets signaled but I_rxe is not signaled */ + /* Use a SW timer to handle an eventual missing RXE */ + rfalTimerStart(gRFAL.tmr.RXE, RFAL_NORXE_TOUT); + /*******************************************************************************/ + + tmp = rfalFIFOStatusGetNumBytes(); + gRFAL.fifo.bytesTotal += tmp; + + /*******************************************************************************/ + /* Calculate the amount of bytes that still fits in rxBuf */ + aux = + ((gRFAL.fifo.bytesTotal > rfalConvBitsToBytes(gRFAL.TxRx.ctx.rxBufLen)) ? + (rfalConvBitsToBytes(gRFAL.TxRx.ctx.rxBufLen) - gRFAL.fifo.bytesWritten) : + tmp); + + /*******************************************************************************/ + /* Retrieve incoming bytes from FIFO to rxBuf, and store already read amount */ + st25r3916ReadFifo(&gRFAL.TxRx.ctx.rxBuf[gRFAL.fifo.bytesWritten], aux); + gRFAL.fifo.bytesWritten += aux; + + /*******************************************************************************/ + /* If the bytes already read were not the full FIFO WL, dump the remaining * + * FIFO so that ST25R391x can continue with reception */ + if(aux < tmp) { + st25r3916ReadFifo(NULL, (tmp - aux)); + } + + rfalFIFOStatusClear(); + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_WAIT_RXE; + break; + + /*******************************************************************************/ + case RFAL_TXRX_STATE_RX_FAIL: + + /*Check if Observation Mode was enabled and disable it on ST25R391x */ + rfalCheckDisableObsMode(); + + /* Clean up Transceive */ + rfalCleanupTransceive(); + + /* Error should be assigned by previous state */ + if(gRFAL.TxRx.status == ERR_BUSY) { + gRFAL.TxRx.status = ERR_SYSTEM; + } + + /*rfalLogD( "RFAL: curSt: %d Error: %d \r\n", gRFAL.TxRx.state, gRFAL.TxRx.status );*/ + gRFAL.TxRx.state = RFAL_TXRX_STATE_IDLE; + break; + + /*******************************************************************************/ + case RFAL_TXRX_STATE_RX_WAIT_EON: + + irqs = st25r3916GetInterrupt( + (ST25R3916_IRQ_MASK_EON | ST25R3916_IRQ_MASK_NRE | ST25R3916_IRQ_MASK_PPON2)); + if(irqs == ST25R3916_IRQ_MASK_NONE) { + break; /* No interrupt to process */ + } + + if((irqs & ST25R3916_IRQ_MASK_EON) != 0U) { + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_WAIT_RXS; + } + + if((irqs & ST25R3916_IRQ_MASK_NRE) != 0U) { + gRFAL.TxRx.status = ERR_TIMEOUT; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + } + if((irqs & ST25R3916_IRQ_MASK_PPON2) != 0U) { + gRFAL.TxRx.status = ERR_LINK_LOSS; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + } + break; + + /*******************************************************************************/ + case RFAL_TXRX_STATE_RX_WAIT_EOF: + + irqs = st25r3916GetInterrupt((ST25R3916_IRQ_MASK_CAT | ST25R3916_IRQ_MASK_CAC)); + if(irqs == ST25R3916_IRQ_MASK_NONE) { + break; /* No interrupt to process */ + } + + if((irqs & ST25R3916_IRQ_MASK_CAT) != 0U) { + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_DONE; + } else if((irqs & ST25R3916_IRQ_MASK_CAC) != 0U) { + gRFAL.TxRx.status = ERR_RF_COLLISION; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + } else { + gRFAL.TxRx.status = ERR_IO; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + } + break; + + /*******************************************************************************/ + default: + gRFAL.TxRx.status = ERR_SYSTEM; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_FAIL; + break; + } +} + +/*******************************************************************************/ +static void rfalFIFOStatusUpdate(void) { + if(gRFAL.fifo.status[RFAL_FIFO_STATUS_REG2] == RFAL_FIFO_STATUS_INVALID) { + st25r3916ReadMultipleRegisters( + ST25R3916_REG_FIFO_STATUS1, gRFAL.fifo.status, ST25R3916_FIFO_STATUS_LEN); + } +} + +/*******************************************************************************/ +static void rfalFIFOStatusClear(void) { + gRFAL.fifo.status[RFAL_FIFO_STATUS_REG2] = RFAL_FIFO_STATUS_INVALID; +} + +/*******************************************************************************/ +static uint16_t rfalFIFOStatusGetNumBytes(void) { + uint16_t result; + + rfalFIFOStatusUpdate(); + + result = + ((((uint16_t)gRFAL.fifo.status[RFAL_FIFO_STATUS_REG2] & + ST25R3916_REG_FIFO_STATUS2_fifo_b_mask) >> + ST25R3916_REG_FIFO_STATUS2_fifo_b_shift) + << RFAL_BITS_IN_BYTE); + result |= (((uint16_t)gRFAL.fifo.status[RFAL_FIFO_STATUS_REG1]) & 0x00FFU); + return result; +} + +/*******************************************************************************/ +static bool rfalFIFOStatusIsIncompleteByte(void) { + rfalFIFOStatusUpdate(); + return ( + (gRFAL.fifo.status[RFAL_FIFO_STATUS_REG2] & ST25R3916_REG_FIFO_STATUS2_fifo_lb_mask) != + 0U); +} + +/*******************************************************************************/ +static bool rfalFIFOStatusIsMissingPar(void) { + rfalFIFOStatusUpdate(); + return ((gRFAL.fifo.status[RFAL_FIFO_STATUS_REG2] & ST25R3916_REG_FIFO_STATUS2_np_lb) != 0U); +} + +/*******************************************************************************/ +static uint8_t rfalFIFOGetNumIncompleteBits(void) { + rfalFIFOStatusUpdate(); + return ( + (gRFAL.fifo.status[RFAL_FIFO_STATUS_REG2] & ST25R3916_REG_FIFO_STATUS2_fifo_lb_mask) >> + ST25R3916_REG_FIFO_STATUS2_fifo_lb_shift); +} + +#if RFAL_FEATURE_NFCA + +/*******************************************************************************/ +ReturnCode rfalISO14443ATransceiveShortFrame( + rfal14443AShortFrameCmd txCmd, + uint8_t* rxBuf, + uint8_t rxBufLen, + uint16_t* rxRcvdLen, + uint32_t fwt) { + ReturnCode ret; + uint8_t directCmd; + + /* Check if RFAL is properly initialized */ + if(!st25r3916IsTxEnabled() || (gRFAL.state < RFAL_STATE_MODE_SET) || + ((gRFAL.mode != RFAL_MODE_POLL_NFCA) && (gRFAL.mode != RFAL_MODE_POLL_NFCA_T1T))) { + return ERR_WRONG_STATE; + } + + /* Check for valid parameters */ + if((rxBuf == NULL) || (rxRcvdLen == NULL) || (fwt == RFAL_FWT_NONE)) { + return ERR_PARAM; + } + + /*******************************************************************************/ + /* Select the Direct Command to be performed */ + switch(txCmd) { + case RFAL_14443A_SHORTFRAME_CMD_WUPA: + directCmd = ST25R3916_CMD_TRANSMIT_WUPA; + break; + + case RFAL_14443A_SHORTFRAME_CMD_REQA: + directCmd = ST25R3916_CMD_TRANSMIT_REQA; + break; + + default: + return ERR_PARAM; + } + + /* Disable CRC while receiving since ATQA has no CRC included */ + st25r3916SetRegisterBits(ST25R3916_REG_AUX, ST25R3916_REG_AUX_no_crc_rx); + + /*******************************************************************************/ + /* Wait for GT and FDT */ + while(!rfalIsGTExpired()) { /* MISRA 15.6: mandatory brackets */ + }; + while(st25r3916IsGPTRunning()) { /* MISRA 15.6: mandatory brackets */ + }; + + rfalTimerDestroy(gRFAL.tmr.GT); + gRFAL.tmr.GT = RFAL_TIMING_NONE; + + /*******************************************************************************/ + /* Prepare for Transceive, Receive only (bypass Tx states) */ + gRFAL.TxRx.ctx.flags = + ((uint32_t)RFAL_TXRX_FLAGS_CRC_TX_MANUAL | (uint32_t)RFAL_TXRX_FLAGS_CRC_RX_KEEP); + gRFAL.TxRx.ctx.rxBuf = rxBuf; + gRFAL.TxRx.ctx.rxBufLen = rxBufLen; + gRFAL.TxRx.ctx.rxRcvdLen = rxRcvdLen; + gRFAL.TxRx.ctx.fwt = fwt; + + /*******************************************************************************/ + /* Load NRT with FWT */ + st25r3916SetNoResponseTime(rfalConv1fcTo64fc( + MIN((fwt + RFAL_FWT_ADJUSTMENT + RFAL_FWT_A_ADJUSTMENT), RFAL_ST25R3916_NRT_MAX_1FC))); + + if(gRFAL.timings.FDTListen != RFAL_TIMING_NONE) { + /* Ensure that MRT is using 64/fc steps */ + st25r3916ClrRegisterBits( + ST25R3916_REG_TIMER_EMV_CONTROL, ST25R3916_REG_TIMER_EMV_CONTROL_mrt_step); + + /* Set Minimum FDT(Listen) in which PICC is not allowed to send a response */ + st25r3916WriteRegister( + ST25R3916_REG_MASK_RX_TIMER, + (uint8_t)rfalConv1fcTo64fc( + ((RFAL_FDT_LISTEN_MRT_ADJUSTMENT + RFAL_FDT_LISTEN_A_ADJUSTMENT) > + gRFAL.timings.FDTListen) ? + RFAL_ST25R3916_MRT_MIN_1FC : + (gRFAL.timings.FDTListen - + (RFAL_FDT_LISTEN_MRT_ADJUSTMENT + RFAL_FDT_LISTEN_A_ADJUSTMENT)))); + } + + /* In Passive communications General Purpose Timer is used to measure FDT Poll */ + if(gRFAL.timings.FDTPoll != RFAL_TIMING_NONE) { + /* Configure GPT to start at RX end */ + st25r3916SetStartGPTimer( + (uint16_t)rfalConv1fcTo8fc( + MIN(gRFAL.timings.FDTPoll, (gRFAL.timings.FDTPoll - RFAL_FDT_POLL_ADJUSTMENT))), + ST25R3916_REG_TIMER_EMV_CONTROL_gptc_erx); + } + + /*******************************************************************************/ + rfalPrepareTransceive(); + + /* Also enable bit collision interrupt */ + st25r3916GetInterrupt(ST25R3916_IRQ_MASK_COL); + st25r3916EnableInterrupts(ST25R3916_IRQ_MASK_COL); + + /*Check if Observation Mode is enabled and set it on ST25R391x */ + rfalCheckEnableObsModeTx(); + + /*******************************************************************************/ + /* Clear nbtx bits before sending WUPA/REQA - otherwise ST25R3916 will report parity error, Note2 of the register */ + st25r3916WriteRegister(ST25R3916_REG_NUM_TX_BYTES2, 0); + + /* Send either WUPA or REQA. All affected tags will backscatter ATQA and change to READY state */ + st25r3916ExecuteCommand(directCmd); + + /* Wait for TXE */ + if(st25r3916WaitForInterruptsTimed( + ST25R3916_IRQ_MASK_TXE, + (uint16_t)MAX(rfalConv1fcToMs(fwt), RFAL_ST25R3916_SW_TMR_MIN_1MS)) == 0U) { + ret = ERR_IO; + } else { + /*Check if Observation Mode is enabled and set it on ST25R391x */ + rfalCheckEnableObsModeRx(); + + /* Jump into a transceive Rx state for reception (bypass Tx states) */ + gRFAL.state = RFAL_STATE_TXRX; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_IDLE; + gRFAL.TxRx.status = ERR_BUSY; + + /* Execute Transceive Rx blocking */ + ret = rfalTransceiveBlockingRx(); + } + + /* Disable Collision interrupt */ + st25r3916DisableInterrupts((ST25R3916_IRQ_MASK_COL)); + + /* ReEnable CRC on Rx */ + st25r3916ClrRegisterBits(ST25R3916_REG_AUX, ST25R3916_REG_AUX_no_crc_rx); + + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalISO14443ATransceiveAnticollisionFrame( + uint8_t* buf, + uint8_t* bytesToSend, + uint8_t* bitsToSend, + uint16_t* rxLength, + uint32_t fwt) { + ReturnCode ret; + rfalTransceiveContext ctx; + uint8_t collByte; + uint8_t collData; + + /* Check if RFAL is properly initialized */ + if((gRFAL.state < RFAL_STATE_MODE_SET) || (gRFAL.mode != RFAL_MODE_POLL_NFCA)) { + return ERR_WRONG_STATE; + } + + /* Check for valid parameters */ + if((buf == NULL) || (bytesToSend == NULL) || (bitsToSend == NULL) || (rxLength == NULL)) { + return ERR_PARAM; + } + + /*******************************************************************************/ + /* Set specific Analog Config for Anticolission if needed */ + rfalSetAnalogConfig( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_ANTICOL)); + + /*******************************************************************************/ + /* Enable anti collision to recognise collision in first byte of SENS_REQ */ + st25r3916SetRegisterBits(ST25R3916_REG_ISO14443A_NFC, ST25R3916_REG_ISO14443A_NFC_antcl); + + /* Disable CRC while receiving */ + st25r3916SetRegisterBits(ST25R3916_REG_AUX, ST25R3916_REG_AUX_no_crc_rx); + + /*******************************************************************************/ + /* Prepare for Transceive */ + ctx.flags = ((uint32_t)RFAL_TXRX_FLAGS_CRC_TX_MANUAL | (uint32_t)RFAL_TXRX_FLAGS_CRC_RX_KEEP); + ctx.txBuf = buf; + ctx.txBufLen = (uint16_t)(rfalConvBytesToBits(*bytesToSend) + *bitsToSend); + ctx.rxBuf = &buf[*bytesToSend]; + ctx.rxBufLen = (uint16_t)rfalConvBytesToBits(RFAL_ISO14443A_SDD_RES_LEN); + ctx.rxRcvdLen = rxLength; + ctx.fwt = fwt; + + /* Disable Automatic Gain Control (AGC) for better detection of collisions if using Coherent Receiver */ + ctx.flags |= + (st25r3916CheckReg( + ST25R3916_REG_AUX, ST25R3916_REG_AUX_dis_corr, ST25R3916_REG_AUX_dis_corr) ? + (uint32_t)RFAL_TXRX_FLAGS_AGC_OFF : + 0x00U); + + rfalStartTransceive(&ctx); + + /* Additionally enable bit collision interrupt */ + st25r3916GetInterrupt(ST25R3916_IRQ_MASK_COL); + st25r3916EnableInterrupts(ST25R3916_IRQ_MASK_COL); + + /*******************************************************************************/ + collByte = 0; + + /* save the collision byte */ + if((*bitsToSend) > 0U) { + buf[(*bytesToSend)] <<= (RFAL_BITS_IN_BYTE - (*bitsToSend)); + buf[(*bytesToSend)] >>= (RFAL_BITS_IN_BYTE - (*bitsToSend)); + collByte = buf[(*bytesToSend)]; + } + + /*******************************************************************************/ + /* Run Transceive blocking */ + ret = rfalTransceiveRunBlockingTx(); + if(ret == ERR_NONE) { + ret = rfalTransceiveBlockingRx(); + + /*******************************************************************************/ + if((*bitsToSend) > 0U) { + buf[(*bytesToSend)] >>= (*bitsToSend); + buf[(*bytesToSend)] <<= (*bitsToSend); + buf[(*bytesToSend)] |= collByte; + } + + if((ERR_RF_COLLISION == ret)) { + /* read out collision register */ + st25r3916ReadRegister(ST25R3916_REG_COLLISION_STATUS, &collData); + + (*bytesToSend) = + ((collData >> ST25R3916_REG_COLLISION_STATUS_c_byte_shift) & + 0x0FU); // 4-bits Byte information + (*bitsToSend) = + ((collData >> ST25R3916_REG_COLLISION_STATUS_c_bit_shift) & + 0x07U); // 3-bits bit information + } + } + + /*******************************************************************************/ + /* Disable Collision interrupt */ + st25r3916DisableInterrupts((ST25R3916_IRQ_MASK_COL)); + + /* Disable anti collision again */ + st25r3916ClrRegisterBits(ST25R3916_REG_ISO14443A_NFC, ST25R3916_REG_ISO14443A_NFC_antcl); + + /* ReEnable CRC on Rx */ + st25r3916ClrRegisterBits(ST25R3916_REG_AUX, ST25R3916_REG_AUX_no_crc_rx); + /*******************************************************************************/ + + /* Restore common Analog configurations for this mode */ + rfalSetAnalogConfig( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | rfalConvBR2ACBR(gRFAL.txBR) | + RFAL_ANALOG_CONFIG_TX)); + rfalSetAnalogConfig( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCA | rfalConvBR2ACBR(gRFAL.rxBR) | + RFAL_ANALOG_CONFIG_RX)); + + return ret; +} + +#endif /* RFAL_FEATURE_NFCA */ + +#if RFAL_FEATURE_NFCV + +/*******************************************************************************/ +ReturnCode rfalISO15693TransceiveAnticollisionFrame( + uint8_t* txBuf, + uint8_t txBufLen, + uint8_t* rxBuf, + uint8_t rxBufLen, + uint16_t* actLen) { + ReturnCode ret; + rfalTransceiveContext ctx; + + /* Check if RFAL is properly initialized */ + if((gRFAL.state < RFAL_STATE_MODE_SET) || (gRFAL.mode != RFAL_MODE_POLL_NFCV)) { + return ERR_WRONG_STATE; + } + + /*******************************************************************************/ + /* Set specific Analog Config for Anticolission if needed */ + rfalSetAnalogConfig( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCV | + RFAL_ANALOG_CONFIG_BITRATE_COMMON | RFAL_ANALOG_CONFIG_ANTICOL)); + + /* Ignoring collisions before the UID (RES_FLAG + DSFID) */ + gRFAL.nfcvData.ignoreBits = (uint16_t)RFAL_ISO15693_IGNORE_BITS; + + /*******************************************************************************/ + /* Prepare for Transceive */ + ctx.flags = + ((txBufLen == 0U) ? (uint32_t)RFAL_TXRX_FLAGS_CRC_TX_MANUAL : + (uint32_t)RFAL_TXRX_FLAGS_CRC_TX_AUTO) | + (uint32_t)RFAL_TXRX_FLAGS_CRC_RX_KEEP | (uint32_t)RFAL_TXRX_FLAGS_AGC_OFF | + ((txBufLen == 0U) ? + (uint32_t)RFAL_TXRX_FLAGS_NFCV_FLAG_MANUAL : + (uint32_t) + RFAL_TXRX_FLAGS_NFCV_FLAG_AUTO); /* Disable Automatic Gain Control (AGC) for better detection of collision */ + ctx.txBuf = txBuf; + ctx.txBufLen = (uint16_t)rfalConvBytesToBits(txBufLen); + ctx.rxBuf = rxBuf; + ctx.rxBufLen = (uint16_t)rfalConvBytesToBits(rxBufLen); + ctx.rxRcvdLen = actLen; + ctx.fwt = rfalConv64fcTo1fc(ISO15693_FWT); + + rfalStartTransceive(&ctx); + + /*******************************************************************************/ + /* Run Transceive blocking */ + ret = rfalTransceiveRunBlockingTx(); + if(ret == ERR_NONE) { + ret = rfalTransceiveBlockingRx(); + } + + /* Check if a Transmission error and received data is less then expected */ + if(((ret == ERR_RF_COLLISION) || (ret == ERR_CRC) || (ret == ERR_FRAMING)) && + (rfalConvBitsToBytes(*ctx.rxRcvdLen) < RFAL_ISO15693_INV_RES_LEN)) { + /* If INVENTORY_RES is shorter than expected, tag is still modulating * + * Ensure that response is complete before next frame */ + platformDelay((uint8_t)((RFAL_ISO15693_INV_RES_LEN - rfalConvBitsToBytes(*ctx.rxRcvdLen)) / + ((RFAL_ISO15693_INV_RES_LEN / RFAL_ISO15693_INV_RES_DUR) + 1U))); + } + + /* Restore common Analog configurations for this mode */ + rfalSetAnalogConfig( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCV | rfalConvBR2ACBR(gRFAL.txBR) | + RFAL_ANALOG_CONFIG_TX)); + rfalSetAnalogConfig( + (RFAL_ANALOG_CONFIG_POLL | RFAL_ANALOG_CONFIG_TECH_NFCV | rfalConvBR2ACBR(gRFAL.rxBR) | + RFAL_ANALOG_CONFIG_RX)); + + gRFAL.nfcvData.ignoreBits = 0; + return ret; +} + +/*******************************************************************************/ +ReturnCode + rfalISO15693TransceiveEOFAnticollision(uint8_t* rxBuf, uint8_t rxBufLen, uint16_t* actLen) { + uint8_t dummy; + + return rfalISO15693TransceiveAnticollisionFrame(&dummy, 0, rxBuf, rxBufLen, actLen); +} + +/*******************************************************************************/ +ReturnCode rfalISO15693TransceiveEOF(uint8_t* rxBuf, uint8_t rxBufLen, uint16_t* actLen) { + ReturnCode ret; + uint8_t dummy; + + /* Check if RFAL is properly initialized */ + if((gRFAL.state < RFAL_STATE_MODE_SET) || (gRFAL.mode != RFAL_MODE_POLL_NFCV)) { + return ERR_WRONG_STATE; + } + + /*******************************************************************************/ + /* Run Transceive blocking */ + ret = rfalTransceiveBlockingTxRx( + &dummy, + 0, + rxBuf, + rxBufLen, + actLen, + ((uint32_t)RFAL_TXRX_FLAGS_CRC_TX_MANUAL | (uint32_t)RFAL_TXRX_FLAGS_CRC_RX_KEEP | + (uint32_t)RFAL_TXRX_FLAGS_AGC_ON), + rfalConv64fcTo1fc(ISO15693_FWT)); + return ret; +} + +#endif /* RFAL_FEATURE_NFCV */ + +#if RFAL_FEATURE_NFCF + +/*******************************************************************************/ +ReturnCode rfalFeliCaPoll( + rfalFeliCaPollSlots slots, + uint16_t sysCode, + uint8_t reqCode, + rfalFeliCaPollRes* pollResList, + uint8_t pollResListSize, + uint8_t* devicesDetected, + uint8_t* collisionsDetected) { + ReturnCode ret; + uint8_t frame + [RFAL_FELICA_POLL_REQ_LEN - RFAL_FELICA_LEN_LEN]; // LEN is added by ST25R391x automatically + uint16_t actLen; + uint8_t frameIdx; + uint8_t devDetected; + uint8_t colDetected; + rfalEHandling curHandling; + uint8_t nbSlots; + + /* Check if RFAL is properly initialized */ + if((gRFAL.state < RFAL_STATE_MODE_SET) || (gRFAL.mode != RFAL_MODE_POLL_NFCF)) { + return ERR_WRONG_STATE; + } + + frameIdx = 0; + colDetected = 0; + devDetected = 0; + nbSlots = (uint8_t)slots; + + /*******************************************************************************/ + /* Compute SENSF_REQ frame */ + frame[frameIdx++] = (uint8_t)FELICA_CMD_POLLING; /* CMD: SENF_REQ */ + frame[frameIdx++] = (uint8_t)(sysCode >> 8); /* System Code (SC) */ + frame[frameIdx++] = (uint8_t)(sysCode & 0xFFU); /* System Code (SC) */ + frame[frameIdx++] = reqCode; /* Communication Parameter Request (RC)*/ + frame[frameIdx++] = nbSlots; /* TimeSlot (TSN) */ + + /*******************************************************************************/ + /* NRT should not stop on reception - Use EMVCo mode to run NRT in nrt_emv * + * ERRORHANDLING_EMVCO has no special handling for NFC-F mode */ + curHandling = gRFAL.conf.eHandling; + rfalSetErrorHandling(RFAL_ERRORHANDLING_EMVCO); + + /*******************************************************************************/ + /* Run transceive blocking, + * Calculate Total Response Time in(64/fc): + * 512 PICC process time + (n * 256 Time Slot duration) */ + ret = rfalTransceiveBlockingTx( + frame, + (uint16_t)frameIdx, + (uint8_t*)gRFAL.nfcfData.pollResponses, + RFAL_FELICA_POLL_RES_LEN, + &actLen, + (RFAL_TXRX_FLAGS_DEFAULT), + rfalConv64fcTo1fc( + RFAL_FELICA_POLL_DELAY_TIME + + (RFAL_FELICA_POLL_SLOT_TIME * ((uint32_t)nbSlots + 1U)))); + + /*******************************************************************************/ + /* If Tx OK, Wait for all responses, store them as soon as they appear */ + if(ret == ERR_NONE) { + bool timeout; + + do { + ret = rfalTransceiveBlockingRx(); + if(ret == ERR_TIMEOUT) { + /* Upon timeout the full Poll Delay + (Slot time)*(nbSlots) has expired */ + timeout = true; + } else { + /* Reception done, reEnabled Rx for following Slot */ + st25r3916ExecuteCommand(ST25R3916_CMD_UNMASK_RECEIVE_DATA); + st25r3916ExecuteCommand(ST25R3916_CMD_RESET_RXGAIN); + + /* If the reception was OK, new device found */ + if(ret == ERR_NONE) { + devDetected++; + + /* Overwrite the Transceive context for the next reception */ + gRFAL.TxRx.ctx.rxBuf = (uint8_t*)gRFAL.nfcfData.pollResponses[devDetected]; + } + /* If the reception was not OK, mark as collision */ + else { + colDetected++; + } + + /* Check whether NRT has expired meanwhile */ + timeout = st25r3916CheckReg( + ST25R3916_REG_NFCIP1_BIT_RATE, ST25R3916_REG_NFCIP1_BIT_RATE_nrt_on, 0x00); + if(!timeout) { + /* Jump again into transceive Rx state for the following reception */ + gRFAL.TxRx.status = ERR_BUSY; + gRFAL.state = RFAL_STATE_TXRX; + gRFAL.TxRx.state = RFAL_TXRX_STATE_RX_IDLE; + } + } + } while(((nbSlots--) != 0U) && !timeout); + } + + /*******************************************************************************/ + /* Restore NRT to normal mode - back to previous error handling */ + rfalSetErrorHandling(curHandling); + + /*******************************************************************************/ + /* Assign output parameters if requested */ + + if((pollResList != NULL) && (pollResListSize > 0U) && (devDetected > 0U)) { + ST_MEMCPY( + pollResList, + gRFAL.nfcfData.pollResponses, + (RFAL_FELICA_POLL_RES_LEN * (uint32_t)MIN(pollResListSize, devDetected))); + } + + if(devicesDetected != NULL) { + *devicesDetected = devDetected; + } + + if(collisionsDetected != NULL) { + *collisionsDetected = colDetected; + } + + return (((colDetected != 0U) || (devDetected != 0U)) ? ERR_NONE : ret); +} + +#endif /* RFAL_FEATURE_NFCF */ + +/***************************************************************************** + * Listen Mode * + *****************************************************************************/ + +/*******************************************************************************/ +bool rfalIsExtFieldOn(void) { + return st25r3916IsExtFieldOn(); +} + +#if RFAL_FEATURE_LISTEN_MODE + +/*******************************************************************************/ +ReturnCode rfalListenStart( + uint32_t lmMask, + const rfalLmConfPA* confA, + const rfalLmConfPB* confB, + const rfalLmConfPF* confF, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* rxLen) { + t_rfalPTMem + PTMem; /* PRQA S 0759 # MISRA 19.2 - Allocating Union where members are of the same type, just different names. Thus no problem can occur. */ + uint8_t* pPTMem; + uint8_t autoResp; + + /* Check if RFAL is initialized */ + if(gRFAL.state < RFAL_STATE_INIT) { + return ERR_WRONG_STATE; + } + + gRFAL.Lm.state = RFAL_LM_STATE_NOT_INIT; + gRFAL.Lm.mdIrqs = ST25R3916_IRQ_MASK_NONE; + gRFAL.Lm.mdReg = + (ST25R3916_REG_MODE_targ_init | ST25R3916_REG_MODE_om_nfc | ST25R3916_REG_MODE_nfc_ar_off); + + /* By default disable all automatic responses */ + autoResp = + (ST25R3916_REG_PASSIVE_TARGET_d_106_ac_a | ST25R3916_REG_PASSIVE_TARGET_rfu | + ST25R3916_REG_PASSIVE_TARGET_d_212_424_1r | ST25R3916_REG_PASSIVE_TARGET_d_ac_ap2p); + + /*******************************************************************************/ + if((lmMask & RFAL_LM_MASK_NFCA) != 0U) { + /* Check if the conf has been provided */ + if(confA == NULL) { + return ERR_PARAM; + } + + pPTMem = (uint8_t*)PTMem.PTMem_A; + + /*******************************************************************************/ + /* Check and set supported NFCID Length */ + switch(confA->nfcidLen) { + case RFAL_LM_NFCID_LEN_04: + st25r3916ChangeRegisterBits( + ST25R3916_REG_AUX, ST25R3916_REG_AUX_nfc_id_mask, ST25R3916_REG_AUX_nfc_id_4bytes); + break; + + case RFAL_LM_NFCID_LEN_07: + st25r3916ChangeRegisterBits( + ST25R3916_REG_AUX, ST25R3916_REG_AUX_nfc_id_mask, ST25R3916_REG_AUX_nfc_id_7bytes); + break; + + default: + return ERR_PARAM; + } + + /*******************************************************************************/ + /* Set NFCID */ + ST_MEMCPY(pPTMem, confA->nfcid, RFAL_NFCID1_TRIPLE_LEN); + pPTMem = &pPTMem[RFAL_NFCID1_TRIPLE_LEN]; /* MISRA 18.4 */ + + /* Set SENS_RES */ + ST_MEMCPY(pPTMem, confA->SENS_RES, RFAL_LM_SENS_RES_LEN); + pPTMem = &pPTMem[RFAL_LM_SENS_RES_LEN]; /* MISRA 18.4 */ + + /* Set SEL_RES */ + *pPTMem++ = + ((confA->nfcidLen == RFAL_LM_NFCID_LEN_04) ? + (confA->SEL_RES & ~RFAL_LM_NFCID_INCOMPLETE) : + (confA->SEL_RES | RFAL_LM_NFCID_INCOMPLETE)); + *pPTMem++ = (confA->SEL_RES & ~RFAL_LM_NFCID_INCOMPLETE); + *pPTMem++ = (confA->SEL_RES & ~RFAL_LM_NFCID_INCOMPLETE); + + /* Write into PTMem-A */ + st25r3916WritePTMem(PTMem.PTMem_A, ST25R3916_PTM_A_LEN); + + /*******************************************************************************/ + /* Enable automatic responses for A */ + autoResp &= ~ST25R3916_REG_PASSIVE_TARGET_d_106_ac_a; + + /* Set Target mode, Bit Rate detection and Listen Mode for NFC-F */ + gRFAL.Lm.mdReg |= + (ST25R3916_REG_MODE_targ_targ | ST25R3916_REG_MODE_om3 | ST25R3916_REG_MODE_om0 | + ST25R3916_REG_MODE_nfc_ar_off); + + gRFAL.Lm.mdIrqs |= + (ST25R3916_IRQ_MASK_WU_A | ST25R3916_IRQ_MASK_WU_A_X | ST25R3916_IRQ_MASK_RXE_PTA); + } + + /*******************************************************************************/ + if((lmMask & RFAL_LM_MASK_NFCB) != 0U) { + /* Check if the conf has been provided */ + if(confB == NULL) { + return ERR_PARAM; + } + + return ERR_NOTSUPP; + } + + /*******************************************************************************/ + if((lmMask & RFAL_LM_MASK_NFCF) != 0U) { + pPTMem = (uint8_t*)PTMem.PTMem_F; + + /* Check if the conf has been provided */ + if(confF == NULL) { + return ERR_PARAM; + } + + /*******************************************************************************/ + /* Set System Code */ + ST_MEMCPY(pPTMem, confF->SC, RFAL_LM_SENSF_SC_LEN); + pPTMem = &pPTMem[RFAL_LM_SENSF_SC_LEN]; /* MISRA 18.4 */ + + /* Set SENSF_RES */ + ST_MEMCPY(pPTMem, confF->SENSF_RES, RFAL_LM_SENSF_RES_LEN); + + /* Set RD bytes to 0x00 as ST25R3916 cannot support advances features */ + pPTMem[RFAL_LM_SENSF_RD0_POS] = + 0x00; /* NFC Forum Digital 1.1 Table 46: 0x00 */ + pPTMem[RFAL_LM_SENSF_RD1_POS] = + 0x00; /* NFC Forum Digital 1.1 Table 47: No automatic bit rates */ + + pPTMem = &pPTMem[RFAL_LM_SENS_RES_LEN]; /* MISRA 18.4 */ + + /* Write into PTMem-F */ + st25r3916WritePTMemF(PTMem.PTMem_F, ST25R3916_PTM_F_LEN); + + /*******************************************************************************/ + /* Write 24 TSN "Random" Numbers at first initialization and let it rollover */ + if(!gRFAL.Lm.iniFlag) { + pPTMem = (uint8_t*)PTMem.TSN; + + *pPTMem++ = 0x12; + *pPTMem++ = 0x34; + *pPTMem++ = 0x56; + *pPTMem++ = 0x78; + *pPTMem++ = 0x9A; + *pPTMem++ = 0xBC; + *pPTMem++ = 0xDF; + *pPTMem++ = 0x21; + *pPTMem++ = 0x43; + *pPTMem++ = 0x65; + *pPTMem++ = 0x87; + *pPTMem++ = 0xA9; + + /* Write into PTMem-TSN */ + st25r3916WritePTMemTSN(PTMem.TSN, ST25R3916_PTM_TSN_LEN); + } + + /*******************************************************************************/ + /* Enable automatic responses for F */ + autoResp &= ~(ST25R3916_REG_PASSIVE_TARGET_d_212_424_1r); + + /* Set Target mode, Bit Rate detection and Listen Mode for NFC-F */ + gRFAL.Lm.mdReg |= + (ST25R3916_REG_MODE_targ_targ | ST25R3916_REG_MODE_om3 | ST25R3916_REG_MODE_om2 | + ST25R3916_REG_MODE_nfc_ar_off); + + /* In CE NFC-F any data without error will be passed to FIFO, to support CUP */ + gRFAL.Lm.mdIrqs |= + (ST25R3916_IRQ_MASK_WU_F | ST25R3916_IRQ_MASK_RXE_PTA | ST25R3916_IRQ_MASK_RXE); + } + + /*******************************************************************************/ + if((lmMask & RFAL_LM_MASK_ACTIVE_P2P) != 0U) { + /* Enable Reception of P2P frames */ + autoResp &= ~(ST25R3916_REG_PASSIVE_TARGET_d_ac_ap2p); + + /* Set Target mode, Bit Rate detection and Automatic Response RF Collision Avoidance */ + gRFAL.Lm.mdReg |= + (ST25R3916_REG_MODE_targ_targ | ST25R3916_REG_MODE_om3 | ST25R3916_REG_MODE_om2 | + ST25R3916_REG_MODE_om0 | ST25R3916_REG_MODE_nfc_ar_auto_rx); + + /* n * TRFW timing shall vary Activity 2.1 3.4.1.1 */ + st25r3916ChangeRegisterBits( + ST25R3916_REG_AUX, ST25R3916_REG_AUX_nfc_n_mask, gRFAL.timings.nTRFW); + gRFAL.timings.nTRFW = rfalGennTRFW(gRFAL.timings.nTRFW); + + gRFAL.Lm.mdIrqs |= (ST25R3916_IRQ_MASK_RXE); + } + + /* Check if one of the modes were selected */ + if((gRFAL.Lm.mdReg & ST25R3916_REG_MODE_targ) == ST25R3916_REG_MODE_targ_targ) { + gRFAL.state = RFAL_STATE_LM; + gRFAL.Lm.mdMask = lmMask; + + gRFAL.Lm.rxBuf = rxBuf; + gRFAL.Lm.rxBufLen = rxBufLen; + gRFAL.Lm.rxLen = rxLen; + *gRFAL.Lm.rxLen = 0; + gRFAL.Lm.dataFlag = false; + gRFAL.Lm.iniFlag = true; + + /* Apply the Automatic Responses configuration */ + st25r3916ChangeRegisterBits( + ST25R3916_REG_PASSIVE_TARGET, + (ST25R3916_REG_PASSIVE_TARGET_d_106_ac_a | ST25R3916_REG_PASSIVE_TARGET_rfu | + ST25R3916_REG_PASSIVE_TARGET_d_212_424_1r | ST25R3916_REG_PASSIVE_TARGET_d_ac_ap2p), + autoResp); + + /* Disable GPT trigger source */ + st25r3916ChangeRegisterBits( + ST25R3916_REG_TIMER_EMV_CONTROL, + ST25R3916_REG_TIMER_EMV_CONTROL_gptc_mask, + ST25R3916_REG_TIMER_EMV_CONTROL_gptc_no_trigger); + + /* On Bit Rate Detection Mode ST25R391x will filter incoming frames during MRT time starting on External Field On event, use 512/fc steps */ + st25r3916SetRegisterBits( + ST25R3916_REG_TIMER_EMV_CONTROL, ST25R3916_REG_TIMER_EMV_CONTROL_mrt_step_512); + st25r3916WriteRegister( + ST25R3916_REG_MASK_RX_TIMER, (uint8_t)rfalConv1fcTo512fc(RFAL_LM_GT)); + + /* Restore default settings on NFCIP1 mode, Receiving parity + CRC bits and manual Tx Parity*/ + st25r3916ClrRegisterBits( + ST25R3916_REG_ISO14443A_NFC, + (ST25R3916_REG_ISO14443A_NFC_no_tx_par | ST25R3916_REG_ISO14443A_NFC_no_rx_par | + ST25R3916_REG_ISO14443A_NFC_nfc_f0)); + + /* External Field Detector enabled as Automatics on rfalInitialize() */ + + /* Set Analog configurations for generic Listen mode */ + /* Not on SetState(POWER OFF) as otherwise would be applied on every Field Event */ + rfalSetAnalogConfig((RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_LISTEN_ON)); + + /* Initialize as POWER_OFF and set proper mode in RF Chip */ + rfalListenSetState(RFAL_LM_STATE_POWER_OFF); + } else { + return ERR_REQUEST; /* Listen Start called but no mode was enabled */ + } + + return ERR_NONE; +} + +/*******************************************************************************/ +static ReturnCode rfalRunListenModeWorker(void) { + volatile uint32_t irqs; + uint8_t tmp; + + if(gRFAL.state != RFAL_STATE_LM) { + return ERR_WRONG_STATE; + } + + switch(gRFAL.Lm.state) { + /*******************************************************************************/ + case RFAL_LM_STATE_POWER_OFF: + + irqs = st25r3916GetInterrupt((ST25R3916_IRQ_MASK_EON)); + if(irqs == ST25R3916_IRQ_MASK_NONE) { + break; /* No interrupt to process */ + } + + if((irqs & ST25R3916_IRQ_MASK_EON) != 0U) { + rfalListenSetState(RFAL_LM_STATE_IDLE); + } else { + break; + } + /* fall through */ + + /*******************************************************************************/ + case RFAL_LM_STATE_IDLE: /* PRQA S 2003 # MISRA 16.3 - Intentional fall through */ + + irqs = st25r3916GetInterrupt( + (ST25R3916_IRQ_MASK_NFCT | ST25R3916_IRQ_MASK_WU_F | ST25R3916_IRQ_MASK_RXE | + ST25R3916_IRQ_MASK_EOF | ST25R3916_IRQ_MASK_RXE_PTA)); + if(irqs == ST25R3916_IRQ_MASK_NONE) { + break; /* No interrupt to process */ + } + + if((irqs & ST25R3916_IRQ_MASK_NFCT) != 0U) { + /* Retrieve detected bitrate */ + uint8_t newBr; + st25r3916ReadRegister(ST25R3916_REG_NFCIP1_BIT_RATE, &newBr); + newBr >>= ST25R3916_REG_NFCIP1_BIT_RATE_nfc_rate_shift; + + if(newBr > ST25R3916_REG_BIT_RATE_rxrate_424) { + newBr = ST25R3916_REG_BIT_RATE_rxrate_424; + } + + gRFAL.Lm.brDetected = + (rfalBitRate)(newBr); /* PRQA S 4342 # MISRA 10.5 - Guaranteed that no invalid enum values may be created. See also equalityGuard_RFAL_BR_106 ff.*/ + } + + if(((irqs & ST25R3916_IRQ_MASK_WU_F) != 0U) && (gRFAL.Lm.brDetected != RFAL_BR_KEEP)) { + rfalListenSetState(RFAL_LM_STATE_READY_F); + } else if(((irqs & ST25R3916_IRQ_MASK_RXE) != 0U) && (gRFAL.Lm.brDetected != RFAL_BR_KEEP)) { + irqs = st25r3916GetInterrupt( + (ST25R3916_IRQ_MASK_WU_F | ST25R3916_IRQ_MASK_RXE | ST25R3916_IRQ_MASK_EOF | + ST25R3916_IRQ_MASK_CRC | ST25R3916_IRQ_MASK_PAR | ST25R3916_IRQ_MASK_ERR2 | + ST25R3916_IRQ_MASK_ERR1)); + + if(((irqs & ST25R3916_IRQ_MASK_CRC) != 0U) || + ((irqs & ST25R3916_IRQ_MASK_PAR) != 0U) || + ((irqs & ST25R3916_IRQ_MASK_ERR1) != 0U)) { + st25r3916ExecuteCommand(ST25R3916_CMD_CLEAR_FIFO); + st25r3916ExecuteCommand(ST25R3916_CMD_UNMASK_RECEIVE_DATA); + st25r3916TxOff(); + break; /* A bad reception occurred, remain in same state */ + } + + /* Retrieve received data */ + *gRFAL.Lm.rxLen = st25r3916GetNumFIFOBytes(); + st25r3916ReadFifo( + gRFAL.Lm.rxBuf, MIN(*gRFAL.Lm.rxLen, rfalConvBitsToBytes(gRFAL.Lm.rxBufLen))); + + /*******************************************************************************/ + /* REMARK: Silicon workaround ST25R3916 Errata #TBD */ + /* In bitrate detection mode CRC is now checked for NFC-A frames */ + if((*gRFAL.Lm.rxLen > RFAL_CRC_LEN) && (gRFAL.Lm.brDetected == RFAL_BR_106)) { + if(rfalCrcCalculateCcitt( + RFAL_ISO14443A_CRC_INTVAL, gRFAL.Lm.rxBuf, *gRFAL.Lm.rxLen) != 0U) { + st25r3916ExecuteCommand(ST25R3916_CMD_CLEAR_FIFO); + st25r3916ExecuteCommand(ST25R3916_CMD_UNMASK_RECEIVE_DATA); + st25r3916TxOff(); + break; /* A bad reception occurred, remain in same state */ + } + } + /*******************************************************************************/ + + /* Check if the data we got has at least the CRC and remove it, otherwise leave at 0 */ + *gRFAL.Lm.rxLen -= ((*gRFAL.Lm.rxLen > RFAL_CRC_LEN) ? RFAL_CRC_LEN : *gRFAL.Lm.rxLen); + *gRFAL.Lm.rxLen = (uint16_t)rfalConvBytesToBits(*gRFAL.Lm.rxLen); + gRFAL.Lm.dataFlag = true; + + /*Check if Observation Mode was enabled and disable it on ST25R391x */ + rfalCheckDisableObsMode(); + } else if( + ((irqs & ST25R3916_IRQ_MASK_RXE_PTA) != 0U) && (gRFAL.Lm.brDetected != RFAL_BR_KEEP)) { + if(((gRFAL.Lm.mdMask & RFAL_LM_MASK_NFCA) != 0U) && + (gRFAL.Lm.brDetected == RFAL_BR_106)) { + st25r3916ReadRegister(ST25R3916_REG_PASSIVE_TARGET_STATUS, &tmp); + if(tmp > ST25R3916_REG_PASSIVE_TARGET_STATUS_pta_st_idle) { + rfalListenSetState(RFAL_LM_STATE_READY_A); + } + } + } else if(((irqs & ST25R3916_IRQ_MASK_EOF) != 0U) && (!gRFAL.Lm.dataFlag)) { + rfalListenSetState(RFAL_LM_STATE_POWER_OFF); + } else { + /* MISRA 15.7 - Empty else */ + } + break; + + /*******************************************************************************/ + case RFAL_LM_STATE_READY_F: + + irqs = st25r3916GetInterrupt( + (ST25R3916_IRQ_MASK_WU_F | ST25R3916_IRQ_MASK_RXE | ST25R3916_IRQ_MASK_EOF)); + if(irqs == ST25R3916_IRQ_MASK_NONE) { + break; /* No interrupt to process */ + } + + if((irqs & ST25R3916_IRQ_MASK_WU_F) != 0U) { + break; + } else if((irqs & ST25R3916_IRQ_MASK_RXE) != 0U) { + /* Retrieve the error flags/irqs */ + irqs |= st25r3916GetInterrupt( + (ST25R3916_IRQ_MASK_CRC | ST25R3916_IRQ_MASK_ERR2 | ST25R3916_IRQ_MASK_ERR1)); + + if(((irqs & ST25R3916_IRQ_MASK_CRC) != 0U) || + ((irqs & ST25R3916_IRQ_MASK_ERR1) != 0U)) { + st25r3916ExecuteCommand(ST25R3916_CMD_CLEAR_FIFO); + st25r3916ExecuteCommand(ST25R3916_CMD_UNMASK_RECEIVE_DATA); + break; /* A bad reception occurred, remain in same state */ + } + + /* Retrieve received data */ + *gRFAL.Lm.rxLen = st25r3916GetNumFIFOBytes(); + st25r3916ReadFifo( + gRFAL.Lm.rxBuf, MIN(*gRFAL.Lm.rxLen, rfalConvBitsToBytes(gRFAL.Lm.rxBufLen))); + + /* Check if the data we got has at least the CRC and remove it, otherwise leave at 0 */ + *gRFAL.Lm.rxLen -= ((*gRFAL.Lm.rxLen > RFAL_CRC_LEN) ? RFAL_CRC_LEN : *gRFAL.Lm.rxLen); + *gRFAL.Lm.rxLen = (uint16_t)rfalConvBytesToBits(*gRFAL.Lm.rxLen); + gRFAL.Lm.dataFlag = true; + } else if((irqs & ST25R3916_IRQ_MASK_EOF) != 0U) { + rfalListenSetState(RFAL_LM_STATE_POWER_OFF); + } else { + /* MISRA 15.7 - Empty else */ + } + break; + + /*******************************************************************************/ + case RFAL_LM_STATE_READY_A: + + irqs = st25r3916GetInterrupt((ST25R3916_IRQ_MASK_EOF | ST25R3916_IRQ_MASK_WU_A)); + if(irqs == ST25R3916_IRQ_MASK_NONE) { + break; /* No interrupt to process */ + } + + if((irqs & ST25R3916_IRQ_MASK_WU_A) != 0U) { + rfalListenSetState(RFAL_LM_STATE_ACTIVE_A); + } else if((irqs & ST25R3916_IRQ_MASK_EOF) != 0U) { + rfalListenSetState(RFAL_LM_STATE_POWER_OFF); + } else { + /* MISRA 15.7 - Empty else */ + } + break; + + /*******************************************************************************/ + case RFAL_LM_STATE_ACTIVE_A: + case RFAL_LM_STATE_ACTIVE_Ax: + + irqs = st25r3916GetInterrupt((ST25R3916_IRQ_MASK_RXE | ST25R3916_IRQ_MASK_EOF)); + if(irqs == ST25R3916_IRQ_MASK_NONE) { + break; /* No interrupt to process */ + } + + if((irqs & ST25R3916_IRQ_MASK_RXE) != 0U) { + /* Retrieve the error flags/irqs */ + irqs |= st25r3916GetInterrupt( + (ST25R3916_IRQ_MASK_PAR | ST25R3916_IRQ_MASK_CRC | ST25R3916_IRQ_MASK_ERR2 | + ST25R3916_IRQ_MASK_ERR1)); + *gRFAL.Lm.rxLen = st25r3916GetNumFIFOBytes(); + + if(((irqs & ST25R3916_IRQ_MASK_CRC) != 0U) || + ((irqs & ST25R3916_IRQ_MASK_ERR1) != 0U) || + ((irqs & ST25R3916_IRQ_MASK_PAR) != 0U) || (*gRFAL.Lm.rxLen <= RFAL_CRC_LEN)) { + /* Clear rx context and FIFO */ + *gRFAL.Lm.rxLen = 0; + st25r3916ExecuteCommand(ST25R3916_CMD_CLEAR_FIFO); + st25r3916ExecuteCommand(ST25R3916_CMD_UNMASK_RECEIVE_DATA); + + /* Check if we should go to IDLE or Sleep */ + if(gRFAL.Lm.state == RFAL_LM_STATE_ACTIVE_Ax) { + rfalListenSleepStart( + RFAL_LM_STATE_SLEEP_A, gRFAL.Lm.rxBuf, gRFAL.Lm.rxBufLen, gRFAL.Lm.rxLen); + } else { + rfalListenSetState(RFAL_LM_STATE_IDLE); + } + + st25r3916DisableInterrupts(ST25R3916_IRQ_MASK_RXE); + break; + } + + /* Remove CRC from length */ + *gRFAL.Lm.rxLen -= RFAL_CRC_LEN; + + /* Retrieve received data */ + st25r3916ReadFifo( + gRFAL.Lm.rxBuf, MIN(*gRFAL.Lm.rxLen, rfalConvBitsToBytes(gRFAL.Lm.rxBufLen))); + *gRFAL.Lm.rxLen = (uint16_t)rfalConvBytesToBits(*gRFAL.Lm.rxLen); + gRFAL.Lm.dataFlag = true; + } else if((irqs & ST25R3916_IRQ_MASK_EOF) != 0U) { + rfalListenSetState(RFAL_LM_STATE_POWER_OFF); + } else { + /* MISRA 15.7 - Empty else */ + } + break; + + /*******************************************************************************/ + case RFAL_LM_STATE_SLEEP_A: + case RFAL_LM_STATE_SLEEP_B: + case RFAL_LM_STATE_SLEEP_AF: + + irqs = st25r3916GetInterrupt( + (ST25R3916_IRQ_MASK_NFCT | ST25R3916_IRQ_MASK_WU_F | ST25R3916_IRQ_MASK_RXE | + ST25R3916_IRQ_MASK_EOF | ST25R3916_IRQ_MASK_RXE_PTA)); + if(irqs == ST25R3916_IRQ_MASK_NONE) { + break; /* No interrupt to process */ + } + + if((irqs & ST25R3916_IRQ_MASK_NFCT) != 0U) { + uint8_t newBr; + /* Retrieve detected bitrate */ + st25r3916ReadRegister(ST25R3916_REG_NFCIP1_BIT_RATE, &newBr); + newBr >>= ST25R3916_REG_NFCIP1_BIT_RATE_nfc_rate_shift; + + if(newBr > ST25R3916_REG_BIT_RATE_rxrate_424) { + newBr = ST25R3916_REG_BIT_RATE_rxrate_424; + } + + gRFAL.Lm.brDetected = + (rfalBitRate)(newBr); /* PRQA S 4342 # MISRA 10.5 - Guaranteed that no invalid enum values may be created. See also equalityGuard_RFAL_BR_106 ff.*/ + } + + if(((irqs & ST25R3916_IRQ_MASK_WU_F) != 0U) && (gRFAL.Lm.brDetected != RFAL_BR_KEEP)) { + rfalListenSetState(RFAL_LM_STATE_READY_F); + } else if(((irqs & ST25R3916_IRQ_MASK_RXE) != 0U) && (gRFAL.Lm.brDetected != RFAL_BR_KEEP)) { + /* Clear rx context and FIFO */ + *gRFAL.Lm.rxLen = 0; + st25r3916ExecuteCommand(ST25R3916_CMD_CLEAR_FIFO); + st25r3916ExecuteCommand(ST25R3916_CMD_UNMASK_RECEIVE_DATA); + + /* REMARK: In order to support CUP or proprietary frames, handling could be added here */ + } else if( + ((irqs & ST25R3916_IRQ_MASK_RXE_PTA) != 0U) && (gRFAL.Lm.brDetected != RFAL_BR_KEEP)) { + if(((gRFAL.Lm.mdMask & RFAL_LM_MASK_NFCA) != 0U) && + (gRFAL.Lm.brDetected == RFAL_BR_106)) { + st25r3916ReadRegister(ST25R3916_REG_PASSIVE_TARGET_STATUS, &tmp); + if(tmp > ST25R3916_REG_PASSIVE_TARGET_STATUS_pta_st_halt) { + rfalListenSetState(RFAL_LM_STATE_READY_Ax); + } + } + } else if((irqs & ST25R3916_IRQ_MASK_EOF) != 0U) { + rfalListenSetState(RFAL_LM_STATE_POWER_OFF); + } else { + /* MISRA 15.7 - Empty else */ + } + break; + + /*******************************************************************************/ + case RFAL_LM_STATE_READY_Ax: + + irqs = st25r3916GetInterrupt((ST25R3916_IRQ_MASK_EOF | ST25R3916_IRQ_MASK_WU_A_X)); + if(irqs == ST25R3916_IRQ_MASK_NONE) { + break; /* No interrupt to process */ + } + + if((irqs & ST25R3916_IRQ_MASK_WU_A_X) != 0U) { + rfalListenSetState(RFAL_LM_STATE_ACTIVE_Ax); + } else if((irqs & ST25R3916_IRQ_MASK_EOF) != 0U) { + rfalListenSetState(RFAL_LM_STATE_POWER_OFF); + } else { + /* MISRA 15.7 - Empty else */ + } + break; + + /*******************************************************************************/ + case RFAL_LM_STATE_CARDEMU_4A: + case RFAL_LM_STATE_CARDEMU_4B: + case RFAL_LM_STATE_CARDEMU_3: + case RFAL_LM_STATE_TARGET_F: + case RFAL_LM_STATE_TARGET_A: + break; + + /*******************************************************************************/ + default: + return ERR_WRONG_STATE; + } + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalListenStop(void) { + /* Check if RFAL is initialized */ + if(gRFAL.state < RFAL_STATE_INIT) { + return ERR_WRONG_STATE; + } + + gRFAL.Lm.state = RFAL_LM_STATE_NOT_INIT; + + /*Check if Observation Mode was enabled and disable it on ST25R391x */ + rfalCheckDisableObsMode(); + + /* Re-Enable the Oscillator if not running */ + st25r3916OscOn(); + + /* Disable Receiver and Transmitter */ + rfalFieldOff(); + + /* Disable all automatic responses */ + st25r3916SetRegisterBits( + ST25R3916_REG_PASSIVE_TARGET, + (ST25R3916_REG_PASSIVE_TARGET_d_212_424_1r | ST25R3916_REG_PASSIVE_TARGET_rfu | + ST25R3916_REG_PASSIVE_TARGET_d_106_ac_a | ST25R3916_REG_PASSIVE_TARGET_d_ac_ap2p)); + + /* As there's no Off mode, set default value: ISO14443A with automatic RF Collision Avoidance Off */ + st25r3916WriteRegister( + ST25R3916_REG_MODE, + (ST25R3916_REG_MODE_om_iso14443a | ST25R3916_REG_MODE_tr_am_ook | + ST25R3916_REG_MODE_nfc_ar_off)); + + st25r3916DisableInterrupts( + (ST25R3916_IRQ_MASK_RXE_PTA | ST25R3916_IRQ_MASK_WU_F | ST25R3916_IRQ_MASK_WU_A | + ST25R3916_IRQ_MASK_WU_A_X | ST25R3916_IRQ_MASK_RFU2 | ST25R3916_IRQ_MASK_OSC)); + st25r3916GetInterrupt( + (ST25R3916_IRQ_MASK_RXE_PTA | ST25R3916_IRQ_MASK_WU_F | ST25R3916_IRQ_MASK_WU_A | + ST25R3916_IRQ_MASK_WU_A_X | ST25R3916_IRQ_MASK_RFU2)); + + /* Set Analog configurations for Listen Off event */ + rfalSetAnalogConfig((RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_LISTEN_OFF)); + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode + rfalListenSleepStart(rfalLmState sleepSt, uint8_t* rxBuf, uint16_t rxBufLen, uint16_t* rxLen) { + /* Check if RFAL is not initialized */ + if(gRFAL.state < RFAL_STATE_INIT) { + return ERR_WRONG_STATE; + } + + switch(sleepSt) { + /*******************************************************************************/ + case RFAL_LM_STATE_SLEEP_A: + + /* Enable automatic responses for A */ + st25r3916ClrRegisterBits( + ST25R3916_REG_PASSIVE_TARGET, (ST25R3916_REG_PASSIVE_TARGET_d_106_ac_a)); + + /* Reset NFCA target */ + st25r3916ExecuteCommand(ST25R3916_CMD_GOTO_SLEEP); + + /* Set Target mode, Bit Rate detection and Listen Mode for NFC-A */ + st25r3916ChangeRegisterBits( + ST25R3916_REG_MODE, + (ST25R3916_REG_MODE_targ | ST25R3916_REG_MODE_om_mask | + ST25R3916_REG_MODE_nfc_ar_mask), + (ST25R3916_REG_MODE_targ_targ | ST25R3916_REG_MODE_om3 | ST25R3916_REG_MODE_om0 | + ST25R3916_REG_MODE_nfc_ar_off)); + break; + + /*******************************************************************************/ + case RFAL_LM_STATE_SLEEP_AF: + + /* Enable automatic responses for A + F */ + st25r3916ClrRegisterBits( + ST25R3916_REG_PASSIVE_TARGET, + (ST25R3916_REG_PASSIVE_TARGET_d_212_424_1r | ST25R3916_REG_PASSIVE_TARGET_d_106_ac_a)); + + /* Reset NFCA target state */ + st25r3916ExecuteCommand(ST25R3916_CMD_GOTO_SLEEP); + + /* Set Target mode, Bit Rate detection, Listen Mode for NFC-A and NFC-F */ + st25r3916ChangeRegisterBits( + ST25R3916_REG_MODE, + (ST25R3916_REG_MODE_targ | ST25R3916_REG_MODE_om_mask | + ST25R3916_REG_MODE_nfc_ar_mask), + (ST25R3916_REG_MODE_targ_targ | ST25R3916_REG_MODE_om3 | ST25R3916_REG_MODE_om2 | + ST25R3916_REG_MODE_om0 | ST25R3916_REG_MODE_nfc_ar_off)); + break; + + /*******************************************************************************/ + case RFAL_LM_STATE_SLEEP_B: + /* REMARK: Support for CE-B would be added here */ + return ERR_NOT_IMPLEMENTED; + + /*******************************************************************************/ + default: + return ERR_PARAM; + } + + /* Ensure that the NFCIP1 mode is disabled */ + st25r3916ClrRegisterBits(ST25R3916_REG_ISO14443A_NFC, ST25R3916_REG_ISO14443A_NFC_nfc_f0); + + st25r3916ExecuteCommand(ST25R3916_CMD_UNMASK_RECEIVE_DATA); + + /* Clear and enable required IRQs */ + st25r3916ClearAndEnableInterrupts( + (ST25R3916_IRQ_MASK_NFCT | ST25R3916_IRQ_MASK_RXS | ST25R3916_IRQ_MASK_CRC | + ST25R3916_IRQ_MASK_ERR1 | ST25R3916_IRQ_MASK_ERR2 | ST25R3916_IRQ_MASK_PAR | + ST25R3916_IRQ_MASK_EON | ST25R3916_IRQ_MASK_EOF | gRFAL.Lm.mdIrqs)); + + /* Check whether the field was turn off right after the Sleep request */ + if(!rfalIsExtFieldOn()) { + /*rfalLogD( "RFAL: curState: %02X newState: %02X \r\n", gRFAL.Lm.state, RFAL_LM_STATE_NOT_INIT );*/ + + rfalListenStop(); + return ERR_LINK_LOSS; + } + + /*rfalLogD( "RFAL: curState: %02X newState: %02X \r\n", gRFAL.Lm.state, sleepSt );*/ + + /* Set the new Sleep State*/ + gRFAL.Lm.state = sleepSt; + gRFAL.state = RFAL_STATE_LM; + + gRFAL.Lm.rxBuf = rxBuf; + gRFAL.Lm.rxBufLen = rxBufLen; + gRFAL.Lm.rxLen = rxLen; + *gRFAL.Lm.rxLen = 0; + gRFAL.Lm.dataFlag = false; + + return ERR_NONE; +} + +/*******************************************************************************/ +rfalLmState rfalListenGetState(bool* dataFlag, rfalBitRate* lastBR) { + /* Allow state retrieval even if gRFAL.state != RFAL_STATE_LM so * + * that this Lm state can be used by caller after activation */ + + if(lastBR != NULL) { + *lastBR = gRFAL.Lm.brDetected; + } + + if(dataFlag != NULL) { + *dataFlag = gRFAL.Lm.dataFlag; + } + + return gRFAL.Lm.state; +} + +/*******************************************************************************/ +ReturnCode rfalListenSetState(rfalLmState newSt) { + ReturnCode ret; + rfalLmState newState; + bool reSetState; + + /* Check if RFAL is initialized */ + if(gRFAL.state < RFAL_STATE_INIT) { + return ERR_WRONG_STATE; + } + + /* SetState clears the Data flag */ + gRFAL.Lm.dataFlag = false; + newState = newSt; + ret = ERR_NONE; + + do { + reSetState = false; + + /*******************************************************************************/ + switch(newState) { + /*******************************************************************************/ + case RFAL_LM_STATE_POWER_OFF: + + /* Enable the receiver and reset logic */ + st25r3916SetRegisterBits(ST25R3916_REG_OP_CONTROL, ST25R3916_REG_OP_CONTROL_rx_en); + st25r3916ExecuteCommand(ST25R3916_CMD_STOP); + + if((gRFAL.Lm.mdMask & RFAL_LM_MASK_NFCA) != 0U) { + /* Enable automatic responses for A */ + st25r3916ClrRegisterBits( + ST25R3916_REG_PASSIVE_TARGET, ST25R3916_REG_PASSIVE_TARGET_d_106_ac_a); + + /* Prepares the NFCIP-1 Passive target logic to wait in the Sense/Idle state */ + st25r3916ExecuteCommand(ST25R3916_CMD_GOTO_SENSE); + } + + if((gRFAL.Lm.mdMask & RFAL_LM_MASK_NFCF) != 0U) { + /* Enable automatic responses for F */ + st25r3916ClrRegisterBits( + ST25R3916_REG_PASSIVE_TARGET, (ST25R3916_REG_PASSIVE_TARGET_d_212_424_1r)); + } + + if((gRFAL.Lm.mdMask & RFAL_LM_MASK_ACTIVE_P2P) != 0U) { + /* Ensure automatic response RF Collision Avoidance is back to only after Rx */ + st25r3916ChangeRegisterBits( + ST25R3916_REG_MODE, + ST25R3916_REG_MODE_nfc_ar_mask, + ST25R3916_REG_MODE_nfc_ar_auto_rx); + + /* Ensure that our field is Off, as automatic response RF Collision Avoidance may have been triggered */ + st25r3916TxOff(); + } + + /*******************************************************************************/ + /* Ensure that the NFCIP1 mode is disabled */ + st25r3916ClrRegisterBits( + ST25R3916_REG_ISO14443A_NFC, ST25R3916_REG_ISO14443A_NFC_nfc_f0); + + /*******************************************************************************/ + /* Clear and enable required IRQs */ + st25r3916DisableInterrupts(ST25R3916_IRQ_MASK_ALL); + + st25r3916ClearAndEnableInterrupts( + (ST25R3916_IRQ_MASK_NFCT | ST25R3916_IRQ_MASK_RXS | ST25R3916_IRQ_MASK_CRC | + ST25R3916_IRQ_MASK_ERR1 | ST25R3916_IRQ_MASK_OSC | ST25R3916_IRQ_MASK_ERR2 | + ST25R3916_IRQ_MASK_PAR | ST25R3916_IRQ_MASK_EON | ST25R3916_IRQ_MASK_EOF | + gRFAL.Lm.mdIrqs)); + + /*******************************************************************************/ + /* Clear the bitRate previously detected */ + gRFAL.Lm.brDetected = RFAL_BR_KEEP; + + /*******************************************************************************/ + /* Apply the initial mode */ + st25r3916ChangeRegisterBits( + ST25R3916_REG_MODE, + (ST25R3916_REG_MODE_targ | ST25R3916_REG_MODE_om_mask | + ST25R3916_REG_MODE_nfc_ar_mask), + (uint8_t)gRFAL.Lm.mdReg); + + /*******************************************************************************/ + /* Check if external Field is already On */ + if(rfalIsExtFieldOn()) { + reSetState = true; + newState = RFAL_LM_STATE_IDLE; /* Set IDLE state */ + } +#if 1 /* Perform bit rate detection in Low power mode */ + else { + st25r3916ClrRegisterBits( + ST25R3916_REG_OP_CONTROL, + (ST25R3916_REG_OP_CONTROL_tx_en | ST25R3916_REG_OP_CONTROL_rx_en | + ST25R3916_REG_OP_CONTROL_en)); + } +#endif + break; + + /*******************************************************************************/ + case RFAL_LM_STATE_IDLE: + + /*******************************************************************************/ + /* Check if device is coming from Low Power bit rate detection */ + if(!st25r3916CheckReg( + ST25R3916_REG_OP_CONTROL, + ST25R3916_REG_OP_CONTROL_en, + ST25R3916_REG_OP_CONTROL_en)) { + /* Exit Low Power mode and confirm the temporarily enable */ + st25r3916SetRegisterBits( + ST25R3916_REG_OP_CONTROL, + (ST25R3916_REG_OP_CONTROL_en | ST25R3916_REG_OP_CONTROL_rx_en)); + + if(!st25r3916CheckReg( + ST25R3916_REG_AUX_DISPLAY, + ST25R3916_REG_AUX_DISPLAY_osc_ok, + ST25R3916_REG_AUX_DISPLAY_osc_ok)) { + /* Wait for Oscillator ready */ + if(st25r3916WaitForInterruptsTimed( + ST25R3916_IRQ_MASK_OSC, ST25R3916_TOUT_OSC_STABLE) == 0U) { + ret = ERR_IO; + break; + } + } + } else { + st25r3916GetInterrupt(ST25R3916_IRQ_MASK_OSC); + } + + /*******************************************************************************/ + /* In Active P2P the Initiator may: Turn its field On; LM goes into IDLE state; + * Initiator sends an unexpected frame raising a Protocol error; Initiator + * turns its field Off and ST25R3916 performs the automatic RF Collision + * Avoidance keeping our field On; upon a Protocol error upper layer sets + * again the state to IDLE to clear dataFlag and wait for next data. + * + * Ensure that when upper layer calls SetState(IDLE), it restores initial + * configuration and that check whether an external Field is still present */ + if((gRFAL.Lm.mdMask & RFAL_LM_MASK_ACTIVE_P2P) != 0U) { + /* Ensure nfc_ar is reset and back to only after Rx */ + st25r3916ExecuteCommand(ST25R3916_CMD_STOP); + st25r3916ChangeRegisterBits( + ST25R3916_REG_MODE, + ST25R3916_REG_MODE_nfc_ar_mask, + ST25R3916_REG_MODE_nfc_ar_auto_rx); + + /* Ensure that our field is Off, as automatic response RF Collision Avoidance may have been triggered */ + st25r3916TxOff(); + + /* If external Field is no longer detected go back to POWER_OFF */ + if(!st25r3916IsExtFieldOn()) { + reSetState = true; + newState = RFAL_LM_STATE_POWER_OFF; /* Set POWER_OFF state */ + } + } + /*******************************************************************************/ + + /* If we are in ACTIVE_A, reEnable Listen for A before going to IDLE, otherwise do nothing */ + if(gRFAL.Lm.state == RFAL_LM_STATE_ACTIVE_A) { + /* Enable automatic responses for A and Reset NFCA target state */ + st25r3916ClrRegisterBits( + ST25R3916_REG_PASSIVE_TARGET, (ST25R3916_REG_PASSIVE_TARGET_d_106_ac_a)); + st25r3916ExecuteCommand(ST25R3916_CMD_GOTO_SENSE); + } + + /* ReEnable the receiver */ + st25r3916ExecuteCommand(ST25R3916_CMD_CLEAR_FIFO); + st25r3916ExecuteCommand(ST25R3916_CMD_UNMASK_RECEIVE_DATA); + + /*******************************************************************************/ + /*Check if Observation Mode is enabled and set it on ST25R391x */ + rfalCheckEnableObsModeRx(); + break; + + /*******************************************************************************/ + case RFAL_LM_STATE_READY_F: + + /*******************************************************************************/ + /* If we're coming from BitRate detection mode, the Bit Rate Definition reg + * still has the last bit rate used. + * If a frame is received between setting the mode to Listen NFCA and + * setting Bit Rate Definition reg, it will raise a framing error. + * Set the bitrate immediately, and then the normal SetMode procedure */ + st25r3916SetBitrate((uint8_t)gRFAL.Lm.brDetected, (uint8_t)gRFAL.Lm.brDetected); + /*******************************************************************************/ + + /* Disable automatic responses for NFC-A */ + st25r3916SetRegisterBits( + ST25R3916_REG_PASSIVE_TARGET, (ST25R3916_REG_PASSIVE_TARGET_d_106_ac_a)); + + /* Set Mode NFC-F only */ + ret = rfalSetMode(RFAL_MODE_LISTEN_NFCF, gRFAL.Lm.brDetected, gRFAL.Lm.brDetected); + gRFAL.state = RFAL_STATE_LM; /* Keep in Listen Mode */ + + /* ReEnable the receiver */ + st25r3916ExecuteCommand(ST25R3916_CMD_CLEAR_FIFO); + st25r3916ExecuteCommand(ST25R3916_CMD_UNMASK_RECEIVE_DATA); + + /* Clear any previous transmission errors (if Reader polled for other/unsupported technologies) */ + st25r3916GetInterrupt( + (ST25R3916_IRQ_MASK_PAR | ST25R3916_IRQ_MASK_CRC | ST25R3916_IRQ_MASK_ERR2 | + ST25R3916_IRQ_MASK_ERR1)); + + st25r3916EnableInterrupts( + ST25R3916_IRQ_MASK_RXE); /* Start looking for any incoming data */ + break; + + /*******************************************************************************/ + case RFAL_LM_STATE_CARDEMU_3: + + /* Set Listen NFCF mode */ + ret = rfalSetMode(RFAL_MODE_LISTEN_NFCF, gRFAL.Lm.brDetected, gRFAL.Lm.brDetected); + break; + + /*******************************************************************************/ + case RFAL_LM_STATE_READY_Ax: + case RFAL_LM_STATE_READY_A: + + /*******************************************************************************/ + /* If we're coming from BitRate detection mode, the Bit Rate Definition reg + * still has the last bit rate used. + * If a frame is received between setting the mode to Listen NFCA and + * setting Bit Rate Definition reg, it will raise a framing error. + * Set the bitrate immediately, and then the normal SetMode procedure */ + st25r3916SetBitrate((uint8_t)gRFAL.Lm.brDetected, (uint8_t)gRFAL.Lm.brDetected); + /*******************************************************************************/ + + /* Disable automatic responses for NFC-F */ + st25r3916SetRegisterBits( + ST25R3916_REG_PASSIVE_TARGET, (ST25R3916_REG_PASSIVE_TARGET_d_212_424_1r)); + + /* Set Mode NFC-A only */ + ret = rfalSetMode(RFAL_MODE_LISTEN_NFCA, gRFAL.Lm.brDetected, gRFAL.Lm.brDetected); + + gRFAL.state = RFAL_STATE_LM; /* Keep in Listen Mode */ + break; + + /*******************************************************************************/ + case RFAL_LM_STATE_ACTIVE_Ax: + case RFAL_LM_STATE_ACTIVE_A: + + /* Disable automatic responses for A */ + st25r3916SetRegisterBits( + ST25R3916_REG_PASSIVE_TARGET, (ST25R3916_REG_PASSIVE_TARGET_d_106_ac_a)); + + /* Clear any previous transmission errors (if Reader polled for other/unsupported technologies) */ + st25r3916GetInterrupt( + (ST25R3916_IRQ_MASK_PAR | ST25R3916_IRQ_MASK_CRC | ST25R3916_IRQ_MASK_ERR2 | + ST25R3916_IRQ_MASK_ERR1)); + + st25r3916EnableInterrupts( + ST25R3916_IRQ_MASK_RXE); /* Start looking for any incoming data */ + break; + + case RFAL_LM_STATE_TARGET_F: + /* Disable Automatic response SENSF_REQ */ + st25r3916SetRegisterBits( + ST25R3916_REG_PASSIVE_TARGET, (ST25R3916_REG_PASSIVE_TARGET_d_212_424_1r)); + break; + + /*******************************************************************************/ + case RFAL_LM_STATE_SLEEP_A: + case RFAL_LM_STATE_SLEEP_B: + case RFAL_LM_STATE_SLEEP_AF: + /* These sleep states have to be set by the rfalListenSleepStart() method */ + return ERR_REQUEST; + + /*******************************************************************************/ + case RFAL_LM_STATE_CARDEMU_4A: + case RFAL_LM_STATE_CARDEMU_4B: + case RFAL_LM_STATE_TARGET_A: + /* States not handled by the LM, just keep state context */ + break; + + /*******************************************************************************/ + default: + return ERR_WRONG_STATE; + } + } while(reSetState); + + gRFAL.Lm.state = newState; + + // Call callback on state change + if(gRFAL.callbacks.state_changed_cb) { + gRFAL.callbacks.state_changed_cb(gRFAL.callbacks.ctx); + } + + return ret; +} + +#endif /* RFAL_FEATURE_LISTEN_MODE */ + +/******************************************************************************* + * Wake-Up Mode * + *******************************************************************************/ + +#if RFAL_FEATURE_WAKEUP_MODE + +/*******************************************************************************/ +ReturnCode rfalWakeUpModeStart(const rfalWakeUpConfig* config) { + uint8_t aux; + uint8_t reg; + uint32_t irqs; + + /* Check if RFAL is not initialized */ + if(gRFAL.state < RFAL_STATE_INIT) { + return ERR_WRONG_STATE; + } + + /* The Wake-Up procedure is explained in detail in Application Note: AN4985 */ + + if(config == NULL) { + gRFAL.wum.cfg.period = RFAL_WUM_PERIOD_200MS; + gRFAL.wum.cfg.irqTout = false; + gRFAL.wum.cfg.indAmp.enabled = true; + gRFAL.wum.cfg.indPha.enabled = false; + gRFAL.wum.cfg.cap.enabled = false; + gRFAL.wum.cfg.indAmp.delta = 2U; + gRFAL.wum.cfg.indAmp.reference = RFAL_WUM_REFERENCE_AUTO; + gRFAL.wum.cfg.indAmp.autoAvg = false; + + /*******************************************************************************/ + /* Check if AAT is enabled and if so make use of the SW Tag Detection */ + if(st25r3916CheckReg( + ST25R3916_REG_IO_CONF2, + ST25R3916_REG_IO_CONF2_aat_en, + ST25R3916_REG_IO_CONF2_aat_en)) { + gRFAL.wum.cfg.swTagDetect = true; + gRFAL.wum.cfg.indAmp.autoAvg = true; + gRFAL.wum.cfg.indAmp.aaWeight = RFAL_WUM_AA_WEIGHT_16; + } + } else { + gRFAL.wum.cfg = *config; + } + + /* Check for valid configuration */ + if((!gRFAL.wum.cfg.cap.enabled && !gRFAL.wum.cfg.indAmp.enabled && + !gRFAL.wum.cfg.indPha.enabled) || + (gRFAL.wum.cfg.cap.enabled && + (gRFAL.wum.cfg.indAmp.enabled || gRFAL.wum.cfg.indPha.enabled)) || + (gRFAL.wum.cfg.cap.enabled && gRFAL.wum.cfg.swTagDetect) || + ((gRFAL.wum.cfg.indAmp.reference > RFAL_WUM_REFERENCE_AUTO) || + (gRFAL.wum.cfg.indPha.reference > RFAL_WUM_REFERENCE_AUTO) || + (gRFAL.wum.cfg.cap.reference > RFAL_WUM_REFERENCE_AUTO))) { + return ERR_PARAM; + } + + irqs = ST25R3916_IRQ_MASK_NONE; + + /* Disable Tx, Rx, External Field Detector and set default ISO14443A mode */ + st25r3916TxRxOff(); + st25r3916ClrRegisterBits(ST25R3916_REG_OP_CONTROL, ST25R3916_REG_OP_CONTROL_en_fd_mask); + st25r3916ChangeRegisterBits( + ST25R3916_REG_MODE, + (ST25R3916_REG_MODE_targ | ST25R3916_REG_MODE_om_mask), + (ST25R3916_REG_MODE_targ_init | ST25R3916_REG_MODE_om_iso14443a)); + + /* Set Analog configurations for Wake-up On event */ + rfalSetAnalogConfig((RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_WAKEUP_ON)); + + /*******************************************************************************/ + /* Prepare Wake-Up Timer Control Register */ + reg = (uint8_t)(((uint8_t)gRFAL.wum.cfg.period & 0x0FU) + << ST25R3916_REG_WUP_TIMER_CONTROL_wut_shift); + reg |= (uint8_t)(((uint8_t)gRFAL.wum.cfg.period < (uint8_t)RFAL_WUM_PERIOD_100MS) ? + ST25R3916_REG_WUP_TIMER_CONTROL_wur : + 0x00U); + + if(gRFAL.wum.cfg.irqTout || gRFAL.wum.cfg.swTagDetect) { + reg |= ST25R3916_REG_WUP_TIMER_CONTROL_wto; + irqs |= ST25R3916_IRQ_MASK_WT; + } + + /* Check if HW Wake-up is to be used or SW Tag detection */ + if(gRFAL.wum.cfg.swTagDetect) { + gRFAL.wum.cfg.indAmp.reference = 0U; + gRFAL.wum.cfg.indPha.reference = 0U; + gRFAL.wum.cfg.cap.reference = 0U; + } else { + /*******************************************************************************/ + /* Check if Inductive Amplitude is to be performed */ + if(gRFAL.wum.cfg.indAmp.enabled) { + aux = (uint8_t)((gRFAL.wum.cfg.indAmp.delta) + << ST25R3916_REG_AMPLITUDE_MEASURE_CONF_am_d_shift); + aux |= (uint8_t)(gRFAL.wum.cfg.indAmp.aaInclMeas ? + ST25R3916_REG_AMPLITUDE_MEASURE_CONF_am_aam : + 0x00U); + aux |= (uint8_t)(((uint8_t)gRFAL.wum.cfg.indAmp.aaWeight + << ST25R3916_REG_AMPLITUDE_MEASURE_CONF_am_aew_shift) & + ST25R3916_REG_AMPLITUDE_MEASURE_CONF_am_aew_mask); + aux |= (uint8_t)(gRFAL.wum.cfg.indAmp.autoAvg ? + ST25R3916_REG_AMPLITUDE_MEASURE_CONF_am_ae : + 0x00U); + + st25r3916WriteRegister(ST25R3916_REG_AMPLITUDE_MEASURE_CONF, aux); + + /* Only need to set the reference if not using Auto Average */ + if(!gRFAL.wum.cfg.indAmp.autoAvg) { + if(gRFAL.wum.cfg.indAmp.reference == RFAL_WUM_REFERENCE_AUTO) { + st25r3916MeasureAmplitude(&aux); + gRFAL.wum.cfg.indAmp.reference = aux; + } + st25r3916WriteRegister( + ST25R3916_REG_AMPLITUDE_MEASURE_REF, (uint8_t)gRFAL.wum.cfg.indAmp.reference); + } + + reg |= ST25R3916_REG_WUP_TIMER_CONTROL_wam; + irqs |= ST25R3916_IRQ_MASK_WAM; + } + + /*******************************************************************************/ + /* Check if Inductive Phase is to be performed */ + if(gRFAL.wum.cfg.indPha.enabled) { + aux = (uint8_t)((gRFAL.wum.cfg.indPha.delta) + << ST25R3916_REG_PHASE_MEASURE_CONF_pm_d_shift); + aux |= (uint8_t)(gRFAL.wum.cfg.indPha.aaInclMeas ? + ST25R3916_REG_PHASE_MEASURE_CONF_pm_aam : + 0x00U); + aux |= (uint8_t)(((uint8_t)gRFAL.wum.cfg.indPha.aaWeight + << ST25R3916_REG_PHASE_MEASURE_CONF_pm_aew_shift) & + ST25R3916_REG_PHASE_MEASURE_CONF_pm_aew_mask); + aux |= (uint8_t)(gRFAL.wum.cfg.indPha.autoAvg ? + ST25R3916_REG_PHASE_MEASURE_CONF_pm_ae : + 0x00U); + + st25r3916WriteRegister(ST25R3916_REG_PHASE_MEASURE_CONF, aux); + + /* Only need to set the reference if not using Auto Average */ + if(!gRFAL.wum.cfg.indPha.autoAvg) { + if(gRFAL.wum.cfg.indPha.reference == RFAL_WUM_REFERENCE_AUTO) { + st25r3916MeasurePhase(&aux); + gRFAL.wum.cfg.indPha.reference = aux; + } + st25r3916WriteRegister( + ST25R3916_REG_PHASE_MEASURE_REF, (uint8_t)gRFAL.wum.cfg.indPha.reference); + } + + reg |= ST25R3916_REG_WUP_TIMER_CONTROL_wph; + irqs |= ST25R3916_IRQ_MASK_WPH; + } + + /*******************************************************************************/ + /* Check if Capacitive is to be performed */ + if(gRFAL.wum.cfg.cap.enabled) { + /*******************************************************************************/ + /* Perform Capacitive sensor calibration */ + + /* Disable Oscillator and Field */ + st25r3916ClrRegisterBits( + ST25R3916_REG_OP_CONTROL, + (ST25R3916_REG_OP_CONTROL_en | ST25R3916_REG_OP_CONTROL_tx_en)); + + /* Sensor gain should be configured on Analog Config: RFAL_ANALOG_CONFIG_CHIP_WAKEUP_ON */ + + /* Perform calibration procedure */ + st25r3916CalibrateCapacitiveSensor(NULL); + + /*******************************************************************************/ + aux = (uint8_t)((gRFAL.wum.cfg.cap.delta) + << ST25R3916_REG_CAPACITANCE_MEASURE_CONF_cm_d_shift); + aux |= (uint8_t)(gRFAL.wum.cfg.cap.aaInclMeas ? + ST25R3916_REG_CAPACITANCE_MEASURE_CONF_cm_aam : + 0x00U); + aux |= (uint8_t)(((uint8_t)gRFAL.wum.cfg.cap.aaWeight + << ST25R3916_REG_CAPACITANCE_MEASURE_CONF_cm_aew_shift) & + ST25R3916_REG_CAPACITANCE_MEASURE_CONF_cm_aew_mask); + aux |= (uint8_t)(gRFAL.wum.cfg.cap.autoAvg ? + ST25R3916_REG_CAPACITANCE_MEASURE_CONF_cm_ae : + 0x00U); + + st25r3916WriteRegister(ST25R3916_REG_CAPACITANCE_MEASURE_CONF, aux); + + /* Only need to set the reference if not using Auto Average */ + if(!gRFAL.wum.cfg.cap.autoAvg || gRFAL.wum.cfg.swTagDetect) { + if(gRFAL.wum.cfg.indPha.reference == RFAL_WUM_REFERENCE_AUTO) { + st25r3916MeasureCapacitance(&aux); + gRFAL.wum.cfg.cap.reference = aux; + } + st25r3916WriteRegister( + ST25R3916_REG_CAPACITANCE_MEASURE_REF, (uint8_t)gRFAL.wum.cfg.cap.reference); + } + + reg |= ST25R3916_REG_WUP_TIMER_CONTROL_wcap; + irqs |= ST25R3916_IRQ_MASK_WCAP; + } + } + + /* Disable and clear all interrupts except Wake-Up IRQs */ + st25r3916DisableInterrupts(ST25R3916_IRQ_MASK_ALL); + st25r3916GetInterrupt(irqs); + st25r3916EnableInterrupts(irqs); + + /* Enable Low Power Wake-Up Mode (Disable: Oscilattor, Tx, Rx and External Field Detector) */ + st25r3916WriteRegister(ST25R3916_REG_WUP_TIMER_CONTROL, reg); + st25r3916ChangeRegisterBits( + ST25R3916_REG_OP_CONTROL, + (ST25R3916_REG_OP_CONTROL_en | ST25R3916_REG_OP_CONTROL_rx_en | + ST25R3916_REG_OP_CONTROL_tx_en | ST25R3916_REG_OP_CONTROL_en_fd_mask | + ST25R3916_REG_OP_CONTROL_wu), + ST25R3916_REG_OP_CONTROL_wu); + + gRFAL.wum.state = RFAL_WUM_STATE_ENABLED; + gRFAL.state = RFAL_STATE_WUM; + + return ERR_NONE; +} + +/*******************************************************************************/ +bool rfalWakeUpModeHasWoke(void) { + return (gRFAL.wum.state >= RFAL_WUM_STATE_ENABLED_WOKE); +} + +/*******************************************************************************/ +static uint16_t rfalWakeUpModeFilter(uint16_t curRef, uint16_t curVal, uint8_t weight) { + uint16_t newRef; + + /* Perform the averaging|filter as describded in ST25R3916 DS */ + + /* Avoid signed arithmetics by splitting in two cases */ + if(curVal > curRef) { + newRef = curRef + ((curVal - curRef) / weight); + + /* In order for the reference to converge to final value * + * increment once the diff is smaller that the weight */ + if((curVal != curRef) && (curRef == newRef)) { + newRef &= 0xFF00U; + newRef += 0x0100U; + } + } else { + newRef = curRef - ((curRef - curVal) / weight); + + /* In order for the reference to converge to final value * + * decrement once the diff is smaller that the weight */ + if((curVal != curRef) && (curRef == newRef)) { + newRef &= 0xFF00U; + } + } + + return newRef; +} + +/*******************************************************************************/ +static void rfalRunWakeUpModeWorker(void) { + uint32_t irqs; + uint8_t reg; + uint16_t value; + uint16_t delta; + + if(gRFAL.state != RFAL_STATE_WUM) { + return; + } + + switch(gRFAL.wum.state) { + case RFAL_WUM_STATE_ENABLED: + case RFAL_WUM_STATE_ENABLED_WOKE: + + irqs = st25r3916GetInterrupt( + (ST25R3916_IRQ_MASK_WT | ST25R3916_IRQ_MASK_WAM | ST25R3916_IRQ_MASK_WPH | + ST25R3916_IRQ_MASK_WCAP)); + if(irqs == ST25R3916_IRQ_MASK_NONE) { + break; /* No interrupt to process */ + } + + /*******************************************************************************/ + /* Check and mark which measurement(s) cause interrupt */ + if((irqs & ST25R3916_IRQ_MASK_WAM) != 0U) { + st25r3916ReadRegister(ST25R3916_REG_AMPLITUDE_MEASURE_RESULT, ®); + gRFAL.wum.state = RFAL_WUM_STATE_ENABLED_WOKE; + } + + if((irqs & ST25R3916_IRQ_MASK_WPH) != 0U) { + st25r3916ReadRegister(ST25R3916_REG_PHASE_MEASURE_RESULT, ®); + gRFAL.wum.state = RFAL_WUM_STATE_ENABLED_WOKE; + } + + if((irqs & ST25R3916_IRQ_MASK_WCAP) != 0U) { + st25r3916ReadRegister(ST25R3916_REG_CAPACITANCE_MEASURE_RESULT, ®); + gRFAL.wum.state = RFAL_WUM_STATE_ENABLED_WOKE; + } + + if((irqs & ST25R3916_IRQ_MASK_WT) != 0U) { + /*******************************************************************************/ + if(gRFAL.wum.cfg.swTagDetect) { + /* Enable Ready mode and wait the settle time */ + st25r3916ChangeRegisterBits( + ST25R3916_REG_OP_CONTROL, + (ST25R3916_REG_OP_CONTROL_en | ST25R3916_REG_OP_CONTROL_wu), + ST25R3916_REG_OP_CONTROL_en); + platformDelay(RFAL_ST25R3916_AAT_SETTLE); + + /*******************************************************************************/ + if(gRFAL.wum.cfg.indAmp.enabled) { + /* Perform amplitude measurement */ + st25r3916MeasureAmplitude(®); + + /* Convert inputs to TD format */ + value = rfalConvTDFormat(reg); + delta = rfalConvTDFormat(gRFAL.wum.cfg.indAmp.delta); + + /* Set first measurement as reference */ + if(gRFAL.wum.cfg.indAmp.reference == 0U) { + gRFAL.wum.cfg.indAmp.reference = value; + } + + /* Check if device should be woken */ + if((value >= (gRFAL.wum.cfg.indAmp.reference + delta)) || + (value <= (gRFAL.wum.cfg.indAmp.reference - delta))) { + gRFAL.wum.state = RFAL_WUM_STATE_ENABLED_WOKE; + break; + } + + /* Update moving reference if enabled */ + if(gRFAL.wum.cfg.indAmp.autoAvg) { + gRFAL.wum.cfg.indAmp.reference = rfalWakeUpModeFilter( + gRFAL.wum.cfg.indAmp.reference, + value, + (RFAL_WU_MIN_WEIGHT_VAL << (uint8_t)gRFAL.wum.cfg.indAmp.aaWeight)); + } + } + + /*******************************************************************************/ + if(gRFAL.wum.cfg.indPha.enabled) { + /* Perform Phase measurement */ + st25r3916MeasurePhase(®); + + /* Convert inputs to TD format */ + value = rfalConvTDFormat(reg); + delta = rfalConvTDFormat(gRFAL.wum.cfg.indPha.delta); + + /* Set first measurement as reference */ + if(gRFAL.wum.cfg.indPha.reference == 0U) { + gRFAL.wum.cfg.indPha.reference = value; + } + + /* Check if device should be woken */ + if((value >= (gRFAL.wum.cfg.indPha.reference + delta)) || + (value <= (gRFAL.wum.cfg.indPha.reference - delta))) { + gRFAL.wum.state = RFAL_WUM_STATE_ENABLED_WOKE; + break; + } + + /* Update moving reference if enabled */ + if(gRFAL.wum.cfg.indPha.autoAvg) { + gRFAL.wum.cfg.indPha.reference = rfalWakeUpModeFilter( + gRFAL.wum.cfg.indPha.reference, + value, + (RFAL_WU_MIN_WEIGHT_VAL << (uint8_t)gRFAL.wum.cfg.indPha.aaWeight)); + } + } + + /* Re-Enable low power Wake-Up mode for wto to trigger another measurement(s) */ + st25r3916ChangeRegisterBits( + ST25R3916_REG_OP_CONTROL, + (ST25R3916_REG_OP_CONTROL_en | ST25R3916_REG_OP_CONTROL_wu), + (ST25R3916_REG_OP_CONTROL_wu)); + } + } + break; + + default: + /* MISRA 16.4: no empty default statement (a comment being enough) */ + break; + } +} + +/*******************************************************************************/ +ReturnCode rfalWakeUpModeStop(void) { + /* Check if RFAL is in Wake-up mode */ + if(gRFAL.state != RFAL_STATE_WUM) { + return ERR_WRONG_STATE; + } + + gRFAL.wum.state = RFAL_WUM_STATE_NOT_INIT; + + /* Disable Wake-Up Mode */ + st25r3916ClrRegisterBits(ST25R3916_REG_OP_CONTROL, ST25R3916_REG_OP_CONTROL_wu); + st25r3916DisableInterrupts( + (ST25R3916_IRQ_MASK_WT | ST25R3916_IRQ_MASK_WAM | ST25R3916_IRQ_MASK_WPH | + ST25R3916_IRQ_MASK_WCAP)); + + /* Re-Enable External Field Detector as: Automatics */ + st25r3916ChangeRegisterBits( + ST25R3916_REG_OP_CONTROL, + ST25R3916_REG_OP_CONTROL_en_fd_mask, + ST25R3916_REG_OP_CONTROL_en_fd_auto_efd); + + /* Re-Enable the Oscillator */ + st25r3916OscOn(); + + /* Set Analog configurations for Wake-up Off event */ + rfalSetAnalogConfig((RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_WAKEUP_OFF)); + + return ERR_NONE; +} + +#endif /* RFAL_FEATURE_WAKEUP_MODE */ + +/******************************************************************************* + * Low-Power Mode * + *******************************************************************************/ + +#if RFAL_FEATURE_LOWPOWER_MODE + +/*******************************************************************************/ +ReturnCode rfalLowPowerModeStart(void) { + /* Check if RFAL is not initialized */ + if(gRFAL.state < RFAL_STATE_INIT) { + return ERR_WRONG_STATE; + } + + /* Stop any ongoing activity and set the device in low power by disabling oscillator, transmitter, receiver and external field detector */ + st25r3916ExecuteCommand(ST25R3916_CMD_STOP); + st25r3916ClrRegisterBits( + ST25R3916_REG_OP_CONTROL, + (ST25R3916_REG_OP_CONTROL_en | ST25R3916_REG_OP_CONTROL_rx_en | + ST25R3916_REG_OP_CONTROL_wu | ST25R3916_REG_OP_CONTROL_tx_en | + ST25R3916_REG_OP_CONTROL_en_fd_mask)); + + rfalSetAnalogConfig((RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_LOWPOWER_ON)); + + gRFAL.state = RFAL_STATE_IDLE; + gRFAL.lpm.isRunning = true; + + platformDisableIrqCallback(); + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalLowPowerModeStop(void) { + ReturnCode ret; + + platformEnableIrqCallback(); + + /* Check if RFAL is on right state */ + if(!gRFAL.lpm.isRunning) { + return ERR_WRONG_STATE; + } + + /* Re-enable device */ + EXIT_ON_ERR(ret, st25r3916OscOn()); + st25r3916ChangeRegisterBits( + ST25R3916_REG_OP_CONTROL, + ST25R3916_REG_OP_CONTROL_en_fd_mask, + ST25R3916_REG_OP_CONTROL_en_fd_auto_efd); + + rfalSetAnalogConfig((RFAL_ANALOG_CONFIG_TECH_CHIP | RFAL_ANALOG_CONFIG_CHIP_LOWPOWER_OFF)); + + gRFAL.state = RFAL_STATE_INIT; + return ERR_NONE; +} + +#endif /* RFAL_FEATURE_LOWPOWER_MODE */ + +/******************************************************************************* + * RF Chip * + *******************************************************************************/ + +/*******************************************************************************/ +ReturnCode rfalChipWriteReg(uint16_t reg, const uint8_t* values, uint8_t len) { + if(!st25r3916IsRegValid((uint8_t)reg)) { + return ERR_PARAM; + } + + return st25r3916WriteMultipleRegisters((uint8_t)reg, values, len); +} + +/*******************************************************************************/ +ReturnCode rfalChipReadReg(uint16_t reg, uint8_t* values, uint8_t len) { + if(!st25r3916IsRegValid((uint8_t)reg)) { + return ERR_PARAM; + } + + return st25r3916ReadMultipleRegisters((uint8_t)reg, values, len); +} + +/*******************************************************************************/ +ReturnCode rfalChipExecCmd(uint16_t cmd) { + if(!st25r3916IsCmdValid((uint8_t)cmd)) { + return ERR_PARAM; + } + + return st25r3916ExecuteCommand((uint8_t)cmd); +} + +/*******************************************************************************/ +ReturnCode rfalChipWriteTestReg(uint16_t reg, uint8_t value) { + return st25r3916WriteTestRegister((uint8_t)reg, value); +} + +/*******************************************************************************/ +ReturnCode rfalChipReadTestReg(uint16_t reg, uint8_t* value) { + return st25r3916ReadTestRegister((uint8_t)reg, value); +} + +/*******************************************************************************/ +ReturnCode rfalChipChangeRegBits(uint16_t reg, uint8_t valueMask, uint8_t value) { + if(!st25r3916IsRegValid((uint8_t)reg)) { + return ERR_PARAM; + } + + return st25r3916ChangeRegisterBits((uint8_t)reg, valueMask, value); +} + +/*******************************************************************************/ +ReturnCode rfalChipChangeTestRegBits(uint16_t reg, uint8_t valueMask, uint8_t value) { + st25r3916ChangeTestRegisterBits((uint8_t)reg, valueMask, value); + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalChipSetRFO(uint8_t rfo) { + return st25r3916ChangeRegisterBits( + ST25R3916_REG_TX_DRIVER, ST25R3916_REG_TX_DRIVER_d_res_mask, rfo); +} + +/*******************************************************************************/ +ReturnCode rfalChipGetRFO(uint8_t* result) { + ReturnCode ret; + + ret = st25r3916ReadRegister(ST25R3916_REG_TX_DRIVER, result); + + (*result) = ((*result) & ST25R3916_REG_TX_DRIVER_d_res_mask); + + return ret; +} + +/*******************************************************************************/ +ReturnCode rfalChipMeasureAmplitude(uint8_t* result) { + ReturnCode err; + uint8_t reg_opc, reg_mode, reg_conf1, reg_conf2; + + /* Save registers which will be adjusted below */ + st25r3916ReadRegister(ST25R3916_REG_OP_CONTROL, ®_opc); + st25r3916ReadRegister(ST25R3916_REG_MODE, ®_mode); + st25r3916ReadRegister(ST25R3916_REG_RX_CONF1, ®_conf1); + st25r3916ReadRegister(ST25R3916_REG_RX_CONF2, ®_conf2); + + /* Set values as per defaults of DS. These regs/bits influence receiver chain and change amplitude */ + /* Doing so achieves an amplitude comparable over a complete polling cylce */ + st25r3916WriteRegister(ST25R3916_REG_OP_CONTROL, (reg_opc & ~ST25R3916_REG_OP_CONTROL_rx_chn)); + st25r3916WriteRegister( + ST25R3916_REG_MODE, + ST25R3916_REG_MODE_om_iso14443a | ST25R3916_REG_MODE_targ_init | + ST25R3916_REG_MODE_tr_am_ook | ST25R3916_REG_MODE_nfc_ar_off); + st25r3916WriteRegister( + ST25R3916_REG_RX_CONF1, (reg_conf1 & ~ST25R3916_REG_RX_CONF1_ch_sel_AM)); + st25r3916WriteRegister( + ST25R3916_REG_RX_CONF2, + ((reg_conf2 & ~(ST25R3916_REG_RX_CONF2_demod_mode | ST25R3916_REG_RX_CONF2_amd_sel)) | + ST25R3916_REG_RX_CONF2_amd_sel_peak)); + + /* Perform the actual measurement */ + err = st25r3916MeasureAmplitude(result); + + /* Restore values */ + st25r3916WriteRegister(ST25R3916_REG_OP_CONTROL, reg_opc); + st25r3916WriteRegister(ST25R3916_REG_MODE, reg_mode); + st25r3916WriteRegister(ST25R3916_REG_RX_CONF1, reg_conf1); + st25r3916WriteRegister(ST25R3916_REG_RX_CONF2, reg_conf2); + + return err; +} + +/*******************************************************************************/ +ReturnCode rfalChipMeasurePhase(uint8_t* result) { + st25r3916MeasurePhase(result); + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalChipMeasureCapacitance(uint8_t* result) { + st25r3916MeasureCapacitance(result); + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode rfalChipMeasurePowerSupply(uint8_t param, uint8_t* result) { + *result = st25r3916MeasurePowerSupply(param); + + return ERR_NONE; +} + +/*******************************************************************************/ +extern uint8_t invalid_size_of_stream_configs + [(sizeof(struct st25r3916StreamConfig) == sizeof(struct iso15693StreamConfig)) ? 1 : (-1)]; diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/st25r3916.c b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/st25r3916.c new file mode 100644 index 00000000000..278950d07bd --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/st25r3916.c @@ -0,0 +1,801 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R3916 firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file + * + * \author Gustavo Patricio + * + * \brief ST25R3916 high level interface + * + */ + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ + +#include "st25r3916.h" +#include "st25r3916_com.h" +#include "st25r3916_led.h" +#include "st25r3916_irq.h" +#include "../../utils.h" + +/* +****************************************************************************** +* LOCAL DEFINES +****************************************************************************** +*/ + +#define ST25R3916_SUPPLY_THRESHOLD \ + 3600U /*!< Power supply measure threshold between 3.3V or 5V */ +#define ST25R3916_NRT_MAX \ + 0xFFFFU /*!< Max Register value of NRT */ + +#define ST25R3916_TOUT_MEASURE_VDD \ + 100U /*!< Max duration time of Measure Power Supply command Datasheet: 25us */ +#define ST25R3916_TOUT_MEASURE_AMPLITUDE \ + 10U /*!< Max duration time of Measure Amplitude command Datasheet: 25us */ +#define ST25R3916_TOUT_MEASURE_PHASE \ + 10U /*!< Max duration time of Measure Phase command Datasheet: 25us */ +#define ST25R3916_TOUT_MEASURE_CAPACITANCE \ + 10U /*!< Max duration time of Measure Capacitance command Datasheet: 25us */ +#define ST25R3916_TOUT_CALIBRATE_CAP_SENSOR \ + 4U /*!< Max duration Calibrate Capacitive Sensor command Datasheet: 3ms */ +#define ST25R3916_TOUT_ADJUST_REGULATORS \ + 6U /*!< Max duration time of Adjust Regulators command Datasheet: 5ms */ +#define ST25R3916_TOUT_CA \ + 10U /*!< Max duration time of Collision Avoidance command */ + +#define ST25R3916_TEST_REG_PATTERN \ + 0x33U /*!< Register Read Write test pattern used during selftest */ +#define ST25R3916_TEST_WU_TOUT \ + 12U /*!< Timeout used on WU timer during self test */ +#define ST25R3916_TEST_TMR_TOUT \ + 20U /*!< Timeout used during self test */ +#define ST25R3916_TEST_TMR_TOUT_DELTA \ + 2U /*!< Timeout used during self test */ +#define ST25R3916_TEST_TMR_TOUT_8FC \ + (ST25R3916_TEST_TMR_TOUT * 16950U) /*!< Timeout in 8/fc */ + +/* +****************************************************************************** +* LOCAL CONSTANTS +****************************************************************************** +*/ + +/* +****************************************************************************** +* LOCAL VARIABLES +****************************************************************************** +*/ + +static uint32_t gST25R3916NRT_64fcs; + +/* +****************************************************************************** +* LOCAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +/* + ****************************************************************************** + * LOCAL FUNCTION + ****************************************************************************** + */ + +ReturnCode st25r3916ExecuteCommandAndGetResult( + uint8_t cmd, + uint8_t resReg, + uint8_t tout, + uint8_t* result) { + /* Clear and enable Direct Command interrupt */ + st25r3916GetInterrupt(ST25R3916_IRQ_MASK_DCT); + st25r3916EnableInterrupts(ST25R3916_IRQ_MASK_DCT); + + st25r3916ExecuteCommand(cmd); + + st25r3916WaitForInterruptsTimed(ST25R3916_IRQ_MASK_DCT, tout); + st25r3916DisableInterrupts(ST25R3916_IRQ_MASK_DCT); + + /* After execution read out the result if the pointer is not NULL */ + if(result != NULL) { + st25r3916ReadRegister(resReg, result); + } + + return ERR_NONE; +} + +/* +****************************************************************************** +* GLOBAL FUNCTIONS +****************************************************************************** +*/ + +ReturnCode st25r3916Initialize(void) { + uint16_t vdd_mV; + ReturnCode ret; + + /* Set default state on the ST25R3916 */ + st25r3916ExecuteCommand(ST25R3916_CMD_SET_DEFAULT); + +#ifndef RFAL_USE_I2C + /* Increase MISO driving level as SPI can go up to 10MHz */ + st25r3916WriteRegister(ST25R3916_REG_IO_CONF2, ST25R3916_REG_IO_CONF2_io_drv_lvl); +#endif /* RFAL_USE_I2C */ + + if(!st25r3916CheckChipID(NULL)) { + platformErrorHandle(); + return ERR_HW_MISMATCH; + } + + st25r3916InitInterrupts(); + st25r3916ledInit(); + + gST25R3916NRT_64fcs = 0; + +#ifndef RFAL_USE_I2C + /* Enable pull downs on MISO line */ + st25r3916SetRegisterBits( + ST25R3916_REG_IO_CONF2, + (ST25R3916_REG_IO_CONF2_miso_pd1 | ST25R3916_REG_IO_CONF2_miso_pd2)); +#endif /* RFAL_USE_I2C */ + + /* Disable internal overheat protection */ + st25r3916ChangeTestRegisterBits(0x04, 0x10, 0x10); + +#ifdef ST25R_SELFTEST + /****************************************************************************** + * Check communication interface: + * - write a pattern in a register + * - reads back the register value + * - return ERR_IO in case the read value is different + */ + st25r3916WriteRegister(ST25R3916_REG_BIT_RATE, ST25R3916_TEST_REG_PATTERN); + if(!st25r3916CheckReg( + ST25R3916_REG_BIT_RATE, + (ST25R3916_REG_BIT_RATE_rxrate_mask | ST25R3916_REG_BIT_RATE_txrate_mask), + ST25R3916_TEST_REG_PATTERN)) { + platformErrorHandle(); + return ERR_IO; + } + + /* Restore default value */ + st25r3916WriteRegister(ST25R3916_REG_BIT_RATE, 0x00); + + /* + * Check IRQ Handling: + * - use the Wake-up timer to trigger an IRQ + * - wait the Wake-up timer interrupt + * - return ERR_TIMEOUT when the Wake-up timer interrupt is not received + */ + st25r3916WriteRegister( + ST25R3916_REG_WUP_TIMER_CONTROL, + ST25R3916_REG_WUP_TIMER_CONTROL_wur | ST25R3916_REG_WUP_TIMER_CONTROL_wto); + st25r3916EnableInterrupts(ST25R3916_IRQ_MASK_WT); + st25r3916ExecuteCommand(ST25R3916_CMD_START_WUP_TIMER); + if(st25r3916WaitForInterruptsTimed(ST25R3916_IRQ_MASK_WT, ST25R3916_TEST_WU_TOUT) == 0U) { + platformErrorHandle(); + return ERR_TIMEOUT; + } + st25r3916DisableInterrupts(ST25R3916_IRQ_MASK_WT); + st25r3916WriteRegister(ST25R3916_REG_WUP_TIMER_CONTROL, 0U); + /*******************************************************************************/ +#endif /* ST25R_SELFTEST */ + + /* Enable Oscillator and wait until it gets stable */ + ret = st25r3916OscOn(); + if(ret != ERR_NONE) { + platformErrorHandle(); + return ret; + } + + /* Measure VDD and set sup3V bit according to Power supplied */ + vdd_mV = st25r3916MeasureVoltage(ST25R3916_REG_REGULATOR_CONTROL_mpsv_vdd); + st25r3916ChangeRegisterBits( + ST25R3916_REG_IO_CONF2, + ST25R3916_REG_IO_CONF2_sup3V, + ((vdd_mV < ST25R3916_SUPPLY_THRESHOLD) ? ST25R3916_REG_IO_CONF2_sup3V_3V : + ST25R3916_REG_IO_CONF2_sup3V_5V)); + + /* Make sure Transmitter and Receiver are disabled */ + st25r3916TxRxOff(); + +#ifdef ST25R_SELFTEST_TIMER + /****************************************************************************** + * Check SW timer operation : + * - use the General Purpose timer to measure an amount of time + * - test whether an interrupt is seen when less time was given + * - test whether an interrupt is seen when sufficient time was given + */ + + st25r3916EnableInterrupts(ST25R3916_IRQ_MASK_GPE); + st25r3916SetStartGPTimer( + (uint16_t)ST25R3916_TEST_TMR_TOUT_8FC, ST25R3916_REG_TIMER_EMV_CONTROL_gptc_no_trigger); + if(st25r3916WaitForInterruptsTimed( + ST25R3916_IRQ_MASK_GPE, (ST25R3916_TEST_TMR_TOUT - ST25R3916_TEST_TMR_TOUT_DELTA)) != + 0U) { + platformErrorHandle(); + return ERR_SYSTEM; + } + + /* Stop all activities to stop the GP timer */ + st25r3916ExecuteCommand(ST25R3916_CMD_STOP); + st25r3916ClearAndEnableInterrupts(ST25R3916_IRQ_MASK_GPE); + st25r3916SetStartGPTimer( + (uint16_t)ST25R3916_TEST_TMR_TOUT_8FC, ST25R3916_REG_TIMER_EMV_CONTROL_gptc_no_trigger); + if(st25r3916WaitForInterruptsTimed( + ST25R3916_IRQ_MASK_GPE, (ST25R3916_TEST_TMR_TOUT + ST25R3916_TEST_TMR_TOUT_DELTA)) == + 0U) { + platformErrorHandle(); + return ERR_SYSTEM; + } + + /* Stop all activities to stop the GP timer */ + st25r3916ExecuteCommand(ST25R3916_CMD_STOP); + /*******************************************************************************/ +#endif /* ST25R_SELFTEST_TIMER */ + + /* After reset all interrupts are enabled, so disable them at first */ + st25r3916DisableInterrupts(ST25R3916_IRQ_MASK_ALL); + + /* And clear them, just to be sure */ + st25r3916ClearInterrupts(); + + return ERR_NONE; +} + +/*******************************************************************************/ +void st25r3916Deinitialize(void) { + st25r3916DisableInterrupts(ST25R3916_IRQ_MASK_ALL); + + /* Disable Tx and Rx, Keep OSC On */ + st25r3916TxRxOff(); + + return; +} + +/*******************************************************************************/ +ReturnCode st25r3916OscOn(void) { + /* Check if oscillator is already turned on and stable */ + /* Use ST25R3916_REG_OP_CONTROL_en instead of ST25R3916_REG_AUX_DISPLAY_osc_ok to be on the safe side */ + if(!st25r3916CheckReg( + ST25R3916_REG_OP_CONTROL, ST25R3916_REG_OP_CONTROL_en, ST25R3916_REG_OP_CONTROL_en)) { + /* Clear any eventual previous oscillator IRQ */ + st25r3916GetInterrupt(ST25R3916_IRQ_MASK_OSC); + + /* Enable oscillator frequency stable interrupt */ + st25r3916EnableInterrupts(ST25R3916_IRQ_MASK_OSC); + + /* Enable oscillator and regulator output */ + st25r3916SetRegisterBits(ST25R3916_REG_OP_CONTROL, ST25R3916_REG_OP_CONTROL_en); + + /* Wait for the oscillator interrupt */ + st25r3916WaitForInterruptsTimed(ST25R3916_IRQ_MASK_OSC, ST25R3916_TOUT_OSC_STABLE); + st25r3916DisableInterrupts(ST25R3916_IRQ_MASK_OSC); + } + + if(!st25r3916CheckReg( + ST25R3916_REG_AUX_DISPLAY, + ST25R3916_REG_AUX_DISPLAY_osc_ok, + ST25R3916_REG_AUX_DISPLAY_osc_ok)) { + return ERR_SYSTEM; + } + + return ERR_NONE; +} + +/*******************************************************************************/ +uint8_t st25r3916MeasurePowerSupply(uint8_t mpsv) { + uint8_t result; + + /* Set the source of direct command: Measure Power Supply Voltage */ + st25r3916ChangeRegisterBits( + ST25R3916_REG_REGULATOR_CONTROL, ST25R3916_REG_REGULATOR_CONTROL_mpsv_mask, mpsv); + + /* Execute command: Measure Power Supply Voltage */ + st25r3916ExecuteCommandAndGetResult( + ST25R3916_CMD_MEASURE_VDD, ST25R3916_REG_AD_RESULT, ST25R3916_TOUT_MEASURE_VDD, &result); + + return result; +} + +/*******************************************************************************/ +uint16_t st25r3916MeasureVoltage(uint8_t mpsv) { + uint8_t result; + uint16_t mV; + + result = st25r3916MeasurePowerSupply(mpsv); + + /* Convert cmd output into mV (each step represents 23.4 mV )*/ + mV = ((uint16_t)result) * 23U; + mV += (((((uint16_t)result) * 4U) + 5U) / 10U); + + return mV; +} + +/*******************************************************************************/ +ReturnCode st25r3916AdjustRegulators(uint16_t* result_mV) { + uint8_t result; + + /* Reset logic and set regulated voltages to be defined by result of Adjust Regulators command */ + st25r3916SetRegisterBits( + ST25R3916_REG_REGULATOR_CONTROL, ST25R3916_REG_REGULATOR_CONTROL_reg_s); + st25r3916ClrRegisterBits( + ST25R3916_REG_REGULATOR_CONTROL, ST25R3916_REG_REGULATOR_CONTROL_reg_s); + + /* Execute Adjust regulators cmd and retrieve result */ + st25r3916ExecuteCommandAndGetResult( + ST25R3916_CMD_ADJUST_REGULATORS, + ST25R3916_REG_REGULATOR_RESULT, + ST25R3916_TOUT_ADJUST_REGULATORS, + &result); + + /* Calculate result in mV */ + result >>= ST25R3916_REG_REGULATOR_RESULT_reg_shift; + + if(result_mV != NULL) { + if(st25r3916CheckReg( + ST25R3916_REG_IO_CONF2, + ST25R3916_REG_IO_CONF2_sup3V, + ST25R3916_REG_IO_CONF2_sup3V)) { + result = + MIN(result, + (uint8_t)(result - + 5U)); /* In 3.3V mode [0,4] are not used */ + *result_mV = 2400U; /* Minimum regulated voltage 2.4V in case of 3.3V supply */ + } else { + *result_mV = 3600U; /* Minimum regulated voltage 3.6V in case of 5V supply */ + } + + *result_mV += + (uint16_t)result * 100U; /* 100mV steps in both 3.3V and 5V supply */ + } + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode st25r3916MeasureAmplitude(uint8_t* result) { + return st25r3916ExecuteCommandAndGetResult( + ST25R3916_CMD_MEASURE_AMPLITUDE, + ST25R3916_REG_AD_RESULT, + ST25R3916_TOUT_MEASURE_AMPLITUDE, + result); +} + +/*******************************************************************************/ +ReturnCode st25r3916MeasurePhase(uint8_t* result) { + return st25r3916ExecuteCommandAndGetResult( + ST25R3916_CMD_MEASURE_PHASE, ST25R3916_REG_AD_RESULT, ST25R3916_TOUT_MEASURE_PHASE, result); +} + +/*******************************************************************************/ +ReturnCode st25r3916MeasureCapacitance(uint8_t* result) { + return st25r3916ExecuteCommandAndGetResult( + ST25R3916_CMD_MEASURE_CAPACITANCE, + ST25R3916_REG_AD_RESULT, + ST25R3916_TOUT_MEASURE_CAPACITANCE, + result); +} + +/*******************************************************************************/ +ReturnCode st25r3916CalibrateCapacitiveSensor(uint8_t* result) { + ReturnCode ret; + uint8_t res; + + /* Clear Manual calibration values to enable automatic calibration mode */ + st25r3916ClrRegisterBits( + ST25R3916_REG_CAP_SENSOR_CONTROL, ST25R3916_REG_CAP_SENSOR_CONTROL_cs_mcal_mask); + + /* Execute automatic calibration */ + ret = st25r3916ExecuteCommandAndGetResult( + ST25R3916_CMD_CALIBRATE_C_SENSOR, + ST25R3916_REG_CAP_SENSOR_RESULT, + ST25R3916_TOUT_CALIBRATE_CAP_SENSOR, + &res); + + /* Check whether the calibration was successull */ + if(((res & ST25R3916_REG_CAP_SENSOR_RESULT_cs_cal_end) != + ST25R3916_REG_CAP_SENSOR_RESULT_cs_cal_end) || + ((res & ST25R3916_REG_CAP_SENSOR_RESULT_cs_cal_err) == + ST25R3916_REG_CAP_SENSOR_RESULT_cs_cal_err) || + (ret != ERR_NONE)) { + return ERR_IO; + } + + if(result != NULL) { + (*result) = (uint8_t)(res >> ST25R3916_REG_CAP_SENSOR_RESULT_cs_cal_shift); + } + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode st25r3916SetBitrate(uint8_t txrate, uint8_t rxrate) { + uint8_t reg; + + st25r3916ReadRegister(ST25R3916_REG_BIT_RATE, ®); + if(rxrate != ST25R3916_BR_DO_NOT_SET) { + if(rxrate > ST25R3916_BR_848) { + return ERR_PARAM; + } + + reg = (uint8_t)(reg & ~ST25R3916_REG_BIT_RATE_rxrate_mask); /* MISRA 10.3 */ + reg |= rxrate << ST25R3916_REG_BIT_RATE_rxrate_shift; + } + if(txrate != ST25R3916_BR_DO_NOT_SET) { + if(txrate > ST25R3916_BR_6780) { + return ERR_PARAM; + } + + reg = (uint8_t)(reg & ~ST25R3916_REG_BIT_RATE_txrate_mask); /* MISRA 10.3 */ + reg |= txrate << ST25R3916_REG_BIT_RATE_txrate_shift; + } + return st25r3916WriteRegister(ST25R3916_REG_BIT_RATE, reg); +} + +/*******************************************************************************/ +ReturnCode st25r3916PerformCollisionAvoidance( + uint8_t FieldONCmd, + uint8_t pdThreshold, + uint8_t caThreshold, + uint8_t nTRFW) { + uint8_t treMask; + uint32_t irqs; + ReturnCode err; + + if((FieldONCmd != ST25R3916_CMD_INITIAL_RF_COLLISION) && + (FieldONCmd != ST25R3916_CMD_RESPONSE_RF_COLLISION_N)) { + return ERR_PARAM; + } + + err = ERR_INTERNAL; + + /* Check if new thresholds are to be applied */ + if((pdThreshold != ST25R3916_THRESHOLD_DO_NOT_SET) || + (caThreshold != ST25R3916_THRESHOLD_DO_NOT_SET)) { + treMask = 0; + + if(pdThreshold != ST25R3916_THRESHOLD_DO_NOT_SET) { + treMask |= ST25R3916_REG_FIELD_THRESHOLD_ACTV_trg_mask; + } + + if(caThreshold != ST25R3916_THRESHOLD_DO_NOT_SET) { + treMask |= ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_mask; + } + + /* Set Detection Threshold and|or Collision Avoidance Threshold */ + st25r3916ChangeRegisterBits( + ST25R3916_REG_FIELD_THRESHOLD_ACTV, + treMask, + (pdThreshold & ST25R3916_REG_FIELD_THRESHOLD_ACTV_trg_mask) | + (caThreshold & ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_mask)); + } + + /* Set n x TRFW */ + st25r3916ChangeRegisterBits(ST25R3916_REG_AUX, ST25R3916_REG_AUX_nfc_n_mask, nTRFW); + + /*******************************************************************************/ + /* Enable and clear CA specific interrupts and execute command */ + st25r3916GetInterrupt( + (ST25R3916_IRQ_MASK_CAC | ST25R3916_IRQ_MASK_CAT | ST25R3916_IRQ_MASK_APON)); + st25r3916EnableInterrupts( + (ST25R3916_IRQ_MASK_CAC | ST25R3916_IRQ_MASK_CAT | ST25R3916_IRQ_MASK_APON)); + + st25r3916ExecuteCommand(FieldONCmd); + + /*******************************************************************************/ + /* Wait for initial APON interrupt, indicating anticollision avoidance done and ST25R3916's + * field is now on, or a CAC indicating a collision */ + irqs = st25r3916WaitForInterruptsTimed( + (ST25R3916_IRQ_MASK_CAC | ST25R3916_IRQ_MASK_APON), ST25R3916_TOUT_CA); + + if((ST25R3916_IRQ_MASK_CAC & irqs) != 0U) /* Collision occurred */ + { + err = ERR_RF_COLLISION; + } else if((ST25R3916_IRQ_MASK_APON & irqs) != 0U) { + /* After APON wait for CAT interrupt, indication field was switched on minimum guard time has been fulfilled */ + irqs = st25r3916WaitForInterruptsTimed((ST25R3916_IRQ_MASK_CAT), ST25R3916_TOUT_CA); + + if((ST25R3916_IRQ_MASK_CAT & irqs) != 0U) /* No Collision detected, Field On */ + { + err = ERR_NONE; + } + } else { + /* MISRA 15.7 - Empty else */ + } + + /* Clear any previous External Field events and disable CA specific interrupts */ + st25r3916GetInterrupt((ST25R3916_IRQ_MASK_EOF | ST25R3916_IRQ_MASK_EON)); + st25r3916DisableInterrupts( + (ST25R3916_IRQ_MASK_CAC | ST25R3916_IRQ_MASK_CAT | ST25R3916_IRQ_MASK_APON)); + + return err; +} + +/*******************************************************************************/ +void st25r3916SetNumTxBits(uint16_t nBits) { + st25r3916WriteRegister(ST25R3916_REG_NUM_TX_BYTES2, (uint8_t)((nBits >> 0) & 0xFFU)); + st25r3916WriteRegister(ST25R3916_REG_NUM_TX_BYTES1, (uint8_t)((nBits >> 8) & 0xFFU)); +} + +/*******************************************************************************/ +uint16_t st25r3916GetNumFIFOBytes(void) { + uint8_t reg; + uint16_t result; + + st25r3916ReadRegister(ST25R3916_REG_FIFO_STATUS2, ®); + reg = + ((reg & ST25R3916_REG_FIFO_STATUS2_fifo_b_mask) >> + ST25R3916_REG_FIFO_STATUS2_fifo_b_shift); + result = ((uint16_t)reg << 8); + + st25r3916ReadRegister(ST25R3916_REG_FIFO_STATUS1, ®); + result |= (((uint16_t)reg) & 0x00FFU); + + return result; +} + +/*******************************************************************************/ +uint8_t st25r3916GetNumFIFOLastBits(void) { + uint8_t reg; + + st25r3916ReadRegister(ST25R3916_REG_FIFO_STATUS2, ®); + + return ( + (reg & ST25R3916_REG_FIFO_STATUS2_fifo_lb_mask) >> + ST25R3916_REG_FIFO_STATUS2_fifo_lb_shift); +} + +/*******************************************************************************/ +uint32_t st25r3916GetNoResponseTime(void) { + return gST25R3916NRT_64fcs; +} + +/*******************************************************************************/ +ReturnCode st25r3916SetNoResponseTime(uint32_t nrt_64fcs) { + ReturnCode err; + uint8_t nrt_step; + uint32_t tmpNRT; + + tmpNRT = nrt_64fcs; /* MISRA 17.8 */ + err = ERR_NONE; + + gST25R3916NRT_64fcs = tmpNRT; /* Store given NRT value in 64/fc into local var */ + nrt_step = + ST25R3916_REG_TIMER_EMV_CONTROL_nrt_step_64fc; /* Set default NRT in steps of 64/fc */ + + if(tmpNRT > ST25R3916_NRT_MAX) /* Check if the given NRT value fits using 64/fc steps */ + { + nrt_step = + ST25R3916_REG_TIMER_EMV_CONTROL_nrt_step_4096_fc; /* If not, change NRT set to 4096/fc */ + tmpNRT = ((tmpNRT + 63U) / 64U); /* Calculate number of steps in 4096/fc */ + + if(tmpNRT > ST25R3916_NRT_MAX) /* Check if the NRT value fits using 64/fc steps */ + { + tmpNRT = ST25R3916_NRT_MAX; /* Assign the maximum possible */ + err = ERR_PARAM; /* Signal parameter error */ + } + gST25R3916NRT_64fcs = (64U * tmpNRT); + } + + /* Set the ST25R3916 NRT step units and the value */ + st25r3916ChangeRegisterBits( + ST25R3916_REG_TIMER_EMV_CONTROL, ST25R3916_REG_TIMER_EMV_CONTROL_nrt_step, nrt_step); + st25r3916WriteRegister(ST25R3916_REG_NO_RESPONSE_TIMER1, (uint8_t)(tmpNRT >> 8U)); + st25r3916WriteRegister(ST25R3916_REG_NO_RESPONSE_TIMER2, (uint8_t)(tmpNRT & 0xFFU)); + + return err; +} + +/*******************************************************************************/ +ReturnCode st25r3916SetStartNoResponseTimer(uint32_t nrt_64fcs) { + ReturnCode err; + + err = st25r3916SetNoResponseTime(nrt_64fcs); + if(err == ERR_NONE) { + st25r3916ExecuteCommand(ST25R3916_CMD_START_NO_RESPONSE_TIMER); + } + + return err; +} + +/*******************************************************************************/ +void st25r3916SetGPTime(uint16_t gpt_8fcs) { + st25r3916WriteRegister(ST25R3916_REG_GPT1, (uint8_t)(gpt_8fcs >> 8)); + st25r3916WriteRegister(ST25R3916_REG_GPT2, (uint8_t)(gpt_8fcs & 0xFFU)); +} + +/*******************************************************************************/ +ReturnCode st25r3916SetStartGPTimer(uint16_t gpt_8fcs, uint8_t trigger_source) { + st25r3916SetGPTime(gpt_8fcs); + st25r3916ChangeRegisterBits( + ST25R3916_REG_TIMER_EMV_CONTROL, + ST25R3916_REG_TIMER_EMV_CONTROL_gptc_mask, + trigger_source); + + /* If there's no trigger source, start GPT immediately */ + if(trigger_source == ST25R3916_REG_TIMER_EMV_CONTROL_gptc_no_trigger) { + st25r3916ExecuteCommand(ST25R3916_CMD_START_GP_TIMER); + } + + return ERR_NONE; +} + +/*******************************************************************************/ +bool st25r3916CheckChipID(uint8_t* rev) { + uint8_t ID; + + ID = 0; + st25r3916ReadRegister(ST25R3916_REG_IC_IDENTITY, &ID); + + /* Check if IC Identity Register contains ST25R3916's IC type code */ + if((ID & ST25R3916_REG_IC_IDENTITY_ic_type_mask) != + ST25R3916_REG_IC_IDENTITY_ic_type_st25r3916) { + return false; + } + + if(rev != NULL) { + *rev = (ID & ST25R3916_REG_IC_IDENTITY_ic_rev_mask); + } + + return true; +} + +/*******************************************************************************/ +ReturnCode st25r3916GetRegsDump(t_st25r3916Regs* regDump) { + uint8_t regIt; + + if(regDump == NULL) { + return ERR_PARAM; + } + + /* Dump Registers on space A */ + for(regIt = ST25R3916_REG_IO_CONF1; regIt <= ST25R3916_REG_IC_IDENTITY; regIt++) { + st25r3916ReadRegister(regIt, ®Dump->RsA[regIt]); + } + + regIt = 0; + + /* Read non-consecutive Registers on space B */ + st25r3916ReadRegister(ST25R3916_REG_EMD_SUP_CONF, ®Dump->RsB[regIt++]); + st25r3916ReadRegister(ST25R3916_REG_SUBC_START_TIME, ®Dump->RsB[regIt++]); + st25r3916ReadRegister(ST25R3916_REG_P2P_RX_CONF, ®Dump->RsB[regIt++]); + st25r3916ReadRegister(ST25R3916_REG_CORR_CONF1, ®Dump->RsB[regIt++]); + st25r3916ReadRegister(ST25R3916_REG_CORR_CONF2, ®Dump->RsB[regIt++]); + st25r3916ReadRegister(ST25R3916_REG_SQUELCH_TIMER, ®Dump->RsB[regIt++]); + st25r3916ReadRegister(ST25R3916_REG_FIELD_ON_GT, ®Dump->RsB[regIt++]); + st25r3916ReadRegister(ST25R3916_REG_AUX_MOD, ®Dump->RsB[regIt++]); + st25r3916ReadRegister(ST25R3916_REG_TX_DRIVER_TIMING, ®Dump->RsB[regIt++]); + st25r3916ReadRegister(ST25R3916_REG_RES_AM_MOD, ®Dump->RsB[regIt++]); + st25r3916ReadRegister(ST25R3916_REG_TX_DRIVER_STATUS, ®Dump->RsB[regIt++]); + st25r3916ReadRegister(ST25R3916_REG_REGULATOR_RESULT, ®Dump->RsB[regIt++]); + st25r3916ReadRegister(ST25R3916_REG_OVERSHOOT_CONF1, ®Dump->RsB[regIt++]); + st25r3916ReadRegister(ST25R3916_REG_OVERSHOOT_CONF2, ®Dump->RsB[regIt++]); + st25r3916ReadRegister(ST25R3916_REG_UNDERSHOOT_CONF1, ®Dump->RsB[regIt++]); + st25r3916ReadRegister(ST25R3916_REG_UNDERSHOOT_CONF2, ®Dump->RsB[regIt++]); + + return ERR_NONE; +} + +/*******************************************************************************/ +bool st25r3916IsCmdValid(uint8_t cmd) { + if(!((cmd >= ST25R3916_CMD_SET_DEFAULT) && (cmd <= ST25R3916_CMD_RESPONSE_RF_COLLISION_N)) && + !((cmd >= ST25R3916_CMD_GOTO_SENSE) && (cmd <= ST25R3916_CMD_GOTO_SLEEP)) && + !((cmd >= ST25R3916_CMD_MASK_RECEIVE_DATA) && (cmd <= ST25R3916_CMD_MEASURE_AMPLITUDE)) && + !((cmd >= ST25R3916_CMD_RESET_RXGAIN) && (cmd <= ST25R3916_CMD_ADJUST_REGULATORS)) && + !((cmd >= ST25R3916_CMD_CALIBRATE_DRIVER_TIMING) && + (cmd <= ST25R3916_CMD_START_PPON2_TIMER)) && + (cmd != ST25R3916_CMD_SPACE_B_ACCESS) && (cmd != ST25R3916_CMD_STOP_NRT)) { + return false; + } + return true; +} + +/*******************************************************************************/ +ReturnCode st25r3916StreamConfigure(const struct st25r3916StreamConfig* config) { + uint8_t smd; + uint8_t mode; + + smd = 0; + + if(config->useBPSK != 0U) { + mode = ST25R3916_REG_MODE_om_bpsk_stream; + if((config->din < 2U) || (config->din > 4U)) /* not in fc/4 .. fc/16 */ + { + return ERR_PARAM; + } + smd |= ((4U - config->din) << ST25R3916_REG_STREAM_MODE_scf_shift); + } else { + mode = ST25R3916_REG_MODE_om_subcarrier_stream; + if((config->din < 3U) || (config->din > 6U)) /* not in fc/8 .. fc/64 */ + { + return ERR_PARAM; + } + smd |= ((6U - config->din) << ST25R3916_REG_STREAM_MODE_scf_shift); + if(config->report_period_length == 0U) { + return ERR_PARAM; + } + } + + if((config->dout < 1U) || (config->dout > 7U)) /* not in fc/2 .. fc/128 */ + { + return ERR_PARAM; + } + smd |= (7U - config->dout) << ST25R3916_REG_STREAM_MODE_stx_shift; + + if(config->report_period_length > 3U) { + return ERR_PARAM; + } + smd |= (config->report_period_length << ST25R3916_REG_STREAM_MODE_scp_shift); + + st25r3916WriteRegister(ST25R3916_REG_STREAM_MODE, smd); + st25r3916ChangeRegisterBits(ST25R3916_REG_MODE, ST25R3916_REG_MODE_om_mask, mode); + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode st25r3916GetRSSI(uint16_t* amRssi, uint16_t* pmRssi) { + /*******************************************************************************/ + /* MISRA 8.9 An object should be defined at block scope if its identifier only appears in a single function */ + /*< ST25R3916 RSSI Display Reg values: 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + static const uint16_t st25r3916Rssi2mV[] = { + 0, 20, 27, 37, 52, 72, 99, 136, 190, 262, 357, 500, 686, 950, 1150, 1150}; + + /* ST25R3916 2/3 stage gain reduction [dB] 0 0 0 0 0 3 6 9 12 15 18 na na na na na */ + static const uint16_t st25r3916Gain2Percent[] = { + 100, 100, 100, 100, 100, 141, 200, 281, 398, 562, 794, 1, 1, 1, 1, 1}; + /*******************************************************************************/ + + uint8_t rssi; + uint8_t gainRed; + + st25r3916ReadRegister(ST25R3916_REG_RSSI_RESULT, &rssi); + st25r3916ReadRegister(ST25R3916_REG_GAIN_RED_STATE, &gainRed); + + if(amRssi != NULL) { + *amRssi = + (uint16_t)(((uint32_t) + st25r3916Rssi2mV[(rssi >> ST25R3916_REG_RSSI_RESULT_rssi_am_shift)] * + (uint32_t)st25r3916Gain2Percent[( + gainRed >> ST25R3916_REG_GAIN_RED_STATE_gs_am_shift)]) / + 100U); + } + + if(pmRssi != NULL) { + *pmRssi = + (uint16_t)(((uint32_t) + st25r3916Rssi2mV[(rssi & ST25R3916_REG_RSSI_RESULT_rssi_pm_mask)] * + (uint32_t)st25r3916Gain2Percent[( + gainRed & ST25R3916_REG_GAIN_RED_STATE_gs_pm_mask)]) / + 100U); + } + + return ERR_NONE; +} diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/st25r3916.h b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/st25r3916.h new file mode 100644 index 00000000000..39df7d5353f --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/st25r3916.h @@ -0,0 +1,669 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R3916 firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file + * + * \author Gustavo Patricio + * + * \brief ST25R3916 high level interface + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-HAL + * \brief RFAL Hardware Abstraction Layer + * @{ + * + * \addtogroup ST25R3916 + * \brief RFAL ST25R3916 Driver + * @{ + * + * \addtogroup ST25R3916_Driver + * \brief RFAL ST25R3916 Driver + * @{ + * + */ + +#ifndef ST25R3916_H +#define ST25R3916_H + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ +#include "../../platform.h" +#include "../../st_errno.h" +#include "st25r3916_com.h" + +/* +****************************************************************************** +* GLOBAL DATATYPES +****************************************************************************** +*/ + +/*! Struct to represent all regs on ST25R3916 */ +typedef struct { + uint8_t RsA[( + ST25R3916_REG_IC_IDENTITY + 1U)]; /*!< Registers contained on ST25R3916 space A (Rs-A) */ + uint8_t + RsB[ST25R3916_SPACE_B_REG_LEN]; /*!< Registers contained on ST25R3916 space B (Rs-B) */ +} t_st25r3916Regs; + +/*! Parameters how the stream mode should work */ +struct st25r3916StreamConfig { + uint8_t useBPSK; /*!< 0: subcarrier, 1:BPSK */ + uint8_t din; /*!< Divider for the in subcarrier frequency: fc/2^din */ + uint8_t dout; /*!< Divider for the in subcarrier frequency fc/2^dout */ + uint8_t report_period_length; /*!< Length of the reporting period 2^report_period_length*/ +}; + +/* +****************************************************************************** +* GLOBAL DEFINES +****************************************************************************** +*/ + +/* ST25R3916 direct commands */ +#define ST25R3916_CMD_SET_DEFAULT \ + 0xC1U /*!< Puts the chip in default state (same as after power-up) */ +#define ST25R3916_CMD_STOP 0xC2U /*!< Stops all activities and clears FIFO */ +#define ST25R3916_CMD_TRANSMIT_WITH_CRC \ + 0xC4U /*!< Transmit with CRC */ +#define ST25R3916_CMD_TRANSMIT_WITHOUT_CRC \ + 0xC5U /*!< Transmit without CRC */ +#define ST25R3916_CMD_TRANSMIT_REQA \ + 0xC6U /*!< Transmit REQA */ +#define ST25R3916_CMD_TRANSMIT_WUPA \ + 0xC7U /*!< Transmit WUPA */ +#define ST25R3916_CMD_INITIAL_RF_COLLISION \ + 0xC8U /*!< NFC transmit with Initial RF Collision Avoidance */ +#define ST25R3916_CMD_RESPONSE_RF_COLLISION_N \ + 0xC9U /*!< NFC transmit with Response RF Collision Avoidance */ +#define ST25R3916_CMD_GOTO_SENSE \ + 0xCDU /*!< Passive target logic to Sense/Idle state */ +#define ST25R3916_CMD_GOTO_SLEEP \ + 0xCEU /*!< Passive target logic to Sleep/Halt state */ +#define ST25R3916_CMD_MASK_RECEIVE_DATA \ + 0xD0U /*!< Mask receive data */ +#define ST25R3916_CMD_UNMASK_RECEIVE_DATA \ + 0xD1U /*!< Unmask receive data */ +#define ST25R3916_CMD_AM_MOD_STATE_CHANGE \ + 0xD2U /*!< AM Modulation state change */ +#define ST25R3916_CMD_MEASURE_AMPLITUDE \ + 0xD3U /*!< Measure signal amplitude on RFI inputs */ +#define ST25R3916_CMD_RESET_RXGAIN \ + 0xD5U /*!< Reset RX Gain */ +#define ST25R3916_CMD_ADJUST_REGULATORS \ + 0xD6U /*!< Adjust regulators */ +#define ST25R3916_CMD_CALIBRATE_DRIVER_TIMING \ + 0xD8U /*!< Starts the sequence to adjust the driver timing */ +#define ST25R3916_CMD_MEASURE_PHASE \ + 0xD9U /*!< Measure phase between RFO and RFI signal */ +#define ST25R3916_CMD_CLEAR_RSSI \ + 0xDAU /*!< Clear RSSI bits and restart the measurement */ +#define ST25R3916_CMD_CLEAR_FIFO \ + 0xDBU /*!< Clears FIFO, Collision and IRQ status */ +#define ST25R3916_CMD_TRANSPARENT_MODE \ + 0xDCU /*!< Transparent mode */ +#define ST25R3916_CMD_CALIBRATE_C_SENSOR \ + 0xDDU /*!< Calibrate the capacitive sensor */ +#define ST25R3916_CMD_MEASURE_CAPACITANCE \ + 0xDEU /*!< Measure capacitance */ +#define ST25R3916_CMD_MEASURE_VDD \ + 0xDFU /*!< Measure power supply voltage */ +#define ST25R3916_CMD_START_GP_TIMER \ + 0xE0U /*!< Start the general purpose timer */ +#define ST25R3916_CMD_START_WUP_TIMER \ + 0xE1U /*!< Start the wake-up timer */ +#define ST25R3916_CMD_START_MASK_RECEIVE_TIMER \ + 0xE2U /*!< Start the mask-receive timer */ +#define ST25R3916_CMD_START_NO_RESPONSE_TIMER \ + 0xE3U /*!< Start the no-response timer */ +#define ST25R3916_CMD_START_PPON2_TIMER \ + 0xE4U /*!< Start PPon2 timer */ +#define ST25R3916_CMD_STOP_NRT \ + 0xE8U /*!< Stop No Response Timer */ +#define ST25R3916_CMD_SPACE_B_ACCESS \ + 0xFBU /*!< Enable R/W access to the test registers */ +#define ST25R3916_CMD_TEST_ACCESS \ + 0xFCU /*!< Enable R/W access to the test registers */ + +#define ST25R3916_THRESHOLD_DO_NOT_SET \ + 0xFFU /*!< Indicates not to change this Threshold */ + +#define ST25R3916_BR_DO_NOT_SET \ + 0xFFU /*!< Indicates not to change this Bit Rate */ +#define ST25R3916_BR_106 0x00U /*!< ST25R3916 Bit Rate 106 kbit/s (fc/128) */ +#define ST25R3916_BR_212 0x01U /*!< ST25R3916 Bit Rate 212 kbit/s (fc/64) */ +#define ST25R3916_BR_424 0x02U /*!< ST25R3916 Bit Rate 424 kbit/s (fc/32) */ +#define ST25R3916_BR_848 0x03U /*!< ST25R3916 Bit Rate 848 kbit/s (fc/16) */ +#define ST25R3916_BR_1695 0x04U /*!< ST25R3916 Bit Rate 1696 kbit/s (fc/8) */ +#define ST25R3916_BR_3390 0x05U /*!< ST25R3916 Bit Rate 3390 kbit/s (fc/4) */ +#define ST25R3916_BR_6780 0x07U /*!< ST25R3916 Bit Rate 6780 kbit/s (fc/2) */ + +#define ST25R3916_FIFO_DEPTH 512U /*!< Depth of FIFO */ +#define ST25R3916_TOUT_OSC_STABLE \ + 10U /*!< Max timeout for Oscillator to get stable DS: 700us */ + +/* +****************************************************************************** +* GLOBAL MACROS +****************************************************************************** +*/ + +/*! Enables the Transmitter (Field On) and Receiver */ +#define st25r3916TxRxOn() \ + st25r3916SetRegisterBits( \ + ST25R3916_REG_OP_CONTROL, \ + (ST25R3916_REG_OP_CONTROL_rx_en | ST25R3916_REG_OP_CONTROL_tx_en)) + +/*! Disables the Transmitter (Field Off) and Receiver */ +#define st25r3916TxRxOff() \ + st25r3916ClrRegisterBits( \ + ST25R3916_REG_OP_CONTROL, \ + (ST25R3916_REG_OP_CONTROL_rx_en | ST25R3916_REG_OP_CONTROL_tx_en)) + +/*! Disables the Transmitter (Field Off) */ +#define st25r3916TxOff() \ + st25r3916ClrRegisterBits(ST25R3916_REG_OP_CONTROL, ST25R3916_REG_OP_CONTROL_tx_en) + +/*! Checks if General Purpose Timer is still running by reading gpt_on flag */ +#define st25r3916IsGPTRunning() \ + st25r3916CheckReg( \ + ST25R3916_REG_NFCIP1_BIT_RATE, \ + ST25R3916_REG_NFCIP1_BIT_RATE_gpt_on, \ + ST25R3916_REG_NFCIP1_BIT_RATE_gpt_on) + +/*! Checks if External Filed is detected by reading ST25R3916 External Field Detector output */ +#define st25r3916IsExtFieldOn() \ + st25r3916CheckReg( \ + ST25R3916_REG_AUX_DISPLAY, \ + ST25R3916_REG_AUX_DISPLAY_efd_o, \ + ST25R3916_REG_AUX_DISPLAY_efd_o) + +/*! Checks if Transmitter is enabled (Field On) */ +#define st25r3916IsTxEnabled() \ + st25r3916CheckReg( \ + ST25R3916_REG_OP_CONTROL, ST25R3916_REG_OP_CONTROL_tx_en, ST25R3916_REG_OP_CONTROL_tx_en) + +/*! Checks if NRT is in EMV mode */ +#define st25r3916IsNRTinEMV() \ + st25r3916CheckReg( \ + ST25R3916_REG_TIMER_EMV_CONTROL, \ + ST25R3916_REG_TIMER_EMV_CONTROL_nrt_emv, \ + ST25R3916_REG_TIMER_EMV_CONTROL_nrt_emv_on) + +/*! Checks if last FIFO byte is complete */ +#define st25r3916IsLastFIFOComplete() \ + st25r3916CheckReg(ST25R3916_REG_FIFO_STATUS2, ST25R3916_REG_FIFO_STATUS2_fifo_lb_mask, 0) + +/*! Checks if the Oscillator is enabled */ +#define st25r3916IsOscOn() \ + st25r3916CheckReg( \ + ST25R3916_REG_OP_CONTROL, ST25R3916_REG_OP_CONTROL_en, ST25R3916_REG_OP_CONTROL_en) + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +/*! + ***************************************************************************** + * \brief Initialise ST25R3916 driver + * + * This function initialises the ST25R3916 driver. + * + * \return ERR_NONE : Operation successful + * \return ERR_HW_MISMATCH : Expected HW do not match or communication error + * \return ERR_IO : Error during communication selftest. Check communication interface + * \return ERR_TIMEOUT : Timeout during IRQ selftest. Check IRQ handling + * \return ERR_SYSTEM : Failure during oscillator activation or timer error + * + ***************************************************************************** + */ +ReturnCode st25r3916Initialize(void); + +/*! + ***************************************************************************** + * \brief Deinitialize ST25R3916 driver + * + * Calling this function deinitializes the ST25R3916 driver. + * + ***************************************************************************** + */ +void st25r3916Deinitialize(void); + +/*! + ***************************************************************************** + * \brief Turn on Oscillator and Regulator + * + * This function turn on oscillator and regulator and waits for the + * oscillator to become stable + * + * \return ERR_SYSTEM : Failure dusring Oscillator activation + * \return ERR_NONE : No error, Oscillator is active and stable, Regulator is on + * + ***************************************************************************** + */ +ReturnCode st25r3916OscOn(void); + +/*! + ***************************************************************************** + * \brief Sets the bitrate + * + * This function sets the bitrates for rx and tx + * + * \param txrate : speed is 2^txrate * 106 kb/s + * 0xff : don't set txrate (ST25R3916_BR_DO_NOT_SET) + * \param rxrate : speed is 2^rxrate * 106 kb/s + * 0xff : don't set rxrate (ST25R3916_BR_DO_NOT_SET) + * + * \return ERR_PARAM: At least one bit rate was invalid + * \return ERR_NONE : No error, both bit rates were set + * + ***************************************************************************** + */ +ReturnCode st25r3916SetBitrate(uint8_t txrate, uint8_t rxrate); + +/*! + ***************************************************************************** + * \brief Adjusts supply regulators according to the current supply voltage + * + * This function the power level is measured in maximum load conditions and + * the regulated voltage reference is set to 250mV below this level. + * Execution of this function lasts around 5ms. + * + * The regulated voltages will be set to the result of Adjust Regulators + * + * \param [out] result_mV : Result of calibration in milliVolts + * + * \return ERR_IO : Error during communication with ST25R3916 + * \return ERR_NONE : No error + * + ***************************************************************************** + */ +ReturnCode st25r3916AdjustRegulators(uint16_t* result_mV); + +/*! + ***************************************************************************** + * \brief Measure Amplitude + * + * This function measured the amplitude on the RFI inputs and stores the + * result in parameter \a result. + * + * \param[out] result: result of RF measurement. + * + * \return ERR_PARAM : Invalid parameter + * \return ERR_NONE : No error + * + ***************************************************************************** + */ +ReturnCode st25r3916MeasureAmplitude(uint8_t* result); + +/*! + ***************************************************************************** + * \brief Measure Power Supply + * + * This function executes Measure Power Supply and returns the raw value + * + * \param[in] mpsv : one of ST25R3916_REG_REGULATOR_CONTROL_mpsv_vdd + * ST25R3916_REG_REGULATOR_CONTROL_mpsv_vdd_rf + * ST25R3916_REG_REGULATOR_CONTROL_mpsv_vdd_a + * ST25R3916_REG_REGULATOR_CONTROL_mpsv_vdd_d + * ST25R3916_REG_REGULATOR_CONTROL_mpsv_vdd_am + * + * \return the measured voltage in raw format. + * + ***************************************************************************** + */ +uint8_t st25r3916MeasurePowerSupply(uint8_t mpsv); + +/*! + ***************************************************************************** + * \brief Measure Voltage + * + * This function measures the voltage on one of VDD and VDD_* and returns + * the result in mV + * + * \param[in] mpsv : one of ST25R3916_REG_REGULATOR_CONTROL_mpsv_vdd + * ST25R3916_REG_REGULATOR_CONTROL_mpsv_vdd_rf + * ST25R3916_REG_REGULATOR_CONTROL_mpsv_vdd_a + * ST25R3916_REG_REGULATOR_CONTROL_mpsv_vdd_d + * or ST25R3916_REG_REGULATOR_CONTROL_mpsv_vdd_am + * + * \return the measured voltage in mV + * + ***************************************************************************** + */ +uint16_t st25r3916MeasureVoltage(uint8_t mpsv); + +/*! + ***************************************************************************** + * \brief Measure Phase + * + * This function performs a Phase measurement. + * The result is stored in the \a result parameter. + * + * \param[out] result: 8 bit long result of the measurement. + * + * \return ERR_PARAM : Invalid parameter + * \return ERR_NONE : No error + * + ***************************************************************************** + */ +ReturnCode st25r3916MeasurePhase(uint8_t* result); + +/*! + ***************************************************************************** + * \brief Measure Capacitance + * + * This function performs the capacitance measurement and stores the + * result in parameter \a result. + * + * \param[out] result: 8 bit long result of RF measurement. + * + * \return ERR_PARAM : Invalid parameter + * \return ERR_NONE : No error + * + ***************************************************************************** + */ +ReturnCode st25r3916MeasureCapacitance(uint8_t* result); + +/*! + ***************************************************************************** + * \brief Calibrates Capacitive Sensor + * + * This function performs automatic calibration of the capacitive sensor + * and stores the result in parameter \a result. + * + * \warning To avoid interference with Xtal oscillator and reader magnetic + * field, it is strongly recommended to perform calibration + * in Power-down mode only. + * This method does not modify the Oscillator nor transmitter state, + * these should be configured before by user. + * + * \param[out] result: 5 bit long result of the calibration. + * Binary weighted, step 0.1 pF, max 3.1 pF + * + * \return ERR_PARAM : Invalid parameter + * \return ERR_IO : The calibration was not successful + * \return ERR_NONE : No error + * + ***************************************************************************** + */ +ReturnCode st25r3916CalibrateCapacitiveSensor(uint8_t* result); + +/*! + ***************************************************************************** + * \brief Get NRT time + * + * This returns the last value set on the NRT + * + * \warning it does not read chip register, just the sw var that contains the + * last value set before + * + * \return the value of the NRT in 64/fc + */ +uint32_t st25r3916GetNoResponseTime(void); + +/*! + ***************************************************************************** + * \brief Set NRT time + * + * This function sets the No Response Time with the given value + * + * \param [in] nrt_64fcs : no response time in steps of 64/fc (4.72us) + * + * \return ERR_PARAM : Invalid parameter (time is too large) + * \return ERR_NONE : No error + * + ***************************************************************************** + */ +ReturnCode st25r3916SetNoResponseTime(uint32_t nrt_64fcs); + +/*! + ***************************************************************************** + * \brief Set and Start NRT + * + * This function sets the No Response Time with the given value and + * immediately starts it + * Used when needs to add more time before timeout without performing Tx + * + * \param [in] nrt_64fcs : no response time in steps of 64/fc (4.72us) + * + * \return ERR_PARAM : Invalid parameter + * \return ERR_NONE : No error + * + ***************************************************************************** + */ +ReturnCode st25r3916SetStartNoResponseTimer(uint32_t nrt_64fcs); + +/*! + ***************************************************************************** + * \brief Set GPT time + * + * This function sets the General Purpose Timer time registers + * + * \param [in] gpt_8fcs : general purpose timer timeout in steps of 8/fc (590ns) + * + ***************************************************************************** + */ +void st25r3916SetGPTime(uint16_t gpt_8fcs); + +/*! + ***************************************************************************** + * \brief Set and Start GPT + * + * This function sets the General Purpose Timer with the given timeout and + * immediately starts it ONLY if the trigger source is not set to none. + * + * \param [in] gpt_8fcs : general purpose timer timeout in steps of8/fc (590ns) + * \param [in] trigger_source : no trigger, start of Rx, end of Rx, end of Tx in NFC mode + * + * \return ERR_PARAM : Invalid parameter + * \return ERR_NONE : No error + * + ***************************************************************************** + */ +ReturnCode st25r3916SetStartGPTimer(uint16_t gpt_8fcs, uint8_t trigger_source); + +/*! + ***************************************************************************** + * \brief Sets the number Tx Bits + * + * Sets ST25R3916 internal registers with correct number of complete bytes and + * bits to be sent + * + * \param [in] nBits : number of bits to be set/transmitted + * + ***************************************************************************** + */ +void st25r3916SetNumTxBits(uint16_t nBits); + +/*! + ***************************************************************************** + * \brief Get amount of bytes in FIFO + * + * Gets the number of bytes currently in the FIFO + * + * \return the number of bytes currently in the FIFO + * + ***************************************************************************** + */ +uint16_t st25r3916GetNumFIFOBytes(void); + +/*! + ***************************************************************************** + * \brief Get amount of bits of the last FIFO byte if incomplete + * + * Gets the number of bits of the last FIFO byte if incomplete + * + * \return the number of bits of the last FIFO byte if incomplete, 0 if + * the last byte is complete + * + ***************************************************************************** + */ +uint8_t st25r3916GetNumFIFOLastBits(void); + +/*! + ***************************************************************************** + * \brief Perform Collision Avoidance + * + * Performs Collision Avoidance with the given threshold and with the + * n number of TRFW + * + * \param[in] FieldONCmd : Field ON command to be executed ST25R3916_CMD_INITIAL_RF_COLLISION + * or ST25R3916_CMD_RESPONSE_RF_COLLISION_N + * \param[in] pdThreshold : Peer Detection Threshold (ST25R3916_REG_FIELD_THRESHOLD_trg_xx) + * 0xff : don't set Threshold (ST25R3916_THRESHOLD_DO_NOT_SET) + * \param[in] caThreshold : Collision Avoidance Threshold (ST25R3916_REG_FIELD_THRESHOLD_rfe_xx) + * 0xff : don't set Threshold (ST25R3916_THRESHOLD_DO_NOT_SET) + * \param[in] nTRFW : Number of TRFW + * + * \return ERR_PARAM : Invalid parameter + * \return ERR_RF_COLLISION : Collision detected + * \return ERR_NONE : No collision detected + * + ***************************************************************************** + */ +ReturnCode st25r3916PerformCollisionAvoidance( + uint8_t FieldONCmd, + uint8_t pdThreshold, + uint8_t caThreshold, + uint8_t nTRFW); + +/*! + ***************************************************************************** + * \brief Check Identity + * + * Checks if the chip ID is as expected. + * + * 5 bit IC type code for ST25R3916: 00101 + * The 3 lsb contain the IC revision code + * + * \param[out] rev : the IC revision code + * + * \return true when IC type is as expected + * \return false otherwise + */ +bool st25r3916CheckChipID(uint8_t* rev); + +/*! + ***************************************************************************** + * \brief Retrieves all internal registers from ST25R3916 + * + * \param[out] regDump : pointer to the struct/buffer where the reg dump + * will be written + * + * \return ERR_PARAM : Invalid parameter + * \return ERR_NONE : No error + ***************************************************************************** + */ +ReturnCode st25r3916GetRegsDump(t_st25r3916Regs* regDump); + +/*! + ***************************************************************************** + * \brief Check if command is valid + * + * Checks if the given command is a valid ST25R3916 command + * + * \param[in] cmd: Command to check + * + * \return true if is a valid command + * \return false otherwise + * + ***************************************************************************** + */ +bool st25r3916IsCmdValid(uint8_t cmd); + +/*! + ***************************************************************************** + * \brief Configure the stream mode of ST25R3916 + * + * This function initializes the stream with the given parameters + * + * \param[in] config : all settings for bitrates, type, etc. + * + * \return ERR_PARAM : Invalid parameter + * \return ERR_NONE : No error, stream mode driver initialized + * + ***************************************************************************** + */ +ReturnCode st25r3916StreamConfigure(const struct st25r3916StreamConfig* config); + +/*! + ***************************************************************************** + * \brief Executes a direct command and returns the result + * + * This function executes the direct command given by \a cmd waits for + * \a sleeptime for I_dct and returns the result read from register \a resreg. + * The value of cmd is not checked. + * + * \param[in] cmd : direct command to execute + * \param[in] resReg: address of the register containing the result + * \param[in] tout : time in milliseconds to wait before reading the result + * \param[out] result: result + * + * \return ERR_NONE : No error + * + ***************************************************************************** + */ +ReturnCode + st25r3916ExecuteCommandAndGetResult(uint8_t cmd, uint8_t resReg, uint8_t tout, uint8_t* result); + +/*! + ***************************************************************************** + * \brief Gets the RSSI values + * + * This function gets the RSSI value of the previous reception taking into + * account the gain reductions that were used. + * RSSI value for both AM and PM channel can be retrieved. + * + * \param[out] amRssi: the RSSI on the AM channel expressed in mV + * \param[out] pmRssi: the RSSI on the PM channel expressed in mV + * + * \return ERR_PARAM : Invalid parameter + * \return ERR_NONE : No error + * + ***************************************************************************** + */ +ReturnCode st25r3916GetRSSI(uint16_t* amRssi, uint16_t* pmRssi); +#endif /* ST25R3916_H */ + +/** + * @} + * + * @} + * + * @} + * + * @} + */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/st25r3916_aat.c b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/st25r3916_aat.c new file mode 100644 index 00000000000..75b24744d19 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/st25r3916_aat.c @@ -0,0 +1,366 @@ +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R3916 firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file st25r3916_aat.c + * + * \author + * + * \brief ST25R3916 Antenna Tuning + * + * The antenna tuning algorithm tries to find the optimal settings for + * the AAT_A and AAT_B registers, which are connected to variable capacitors + * to tune the antenna matching. + * + */ + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ +#include "st25r3916_aat.h" +#include "../../utils.h" +#include "../../st_errno.h" +#include "st25r3916.h" +#include "st25r3916_com.h" +#include "../../platform.h" +#include "../../include/rfal_chip.h" + +/* +****************************************************************************** +* GLOBAL DEFINES +****************************************************************************** +*/ +#define ST25R3916_AAT_CAP_DELAY_MAX 10 /*!< Max Variable Capacitor settle delay */ + +/* +****************************************************************************** +* GLOBAL MACROS +****************************************************************************** +*/ +#define st25r3916AatLog(...) /* platformLog(__VA_ARGS__) */ /*!< Logging macro */ + +/* +****************************************************************************** +* LOCAL FUNCTION PROTOTYPES +****************************************************************************** +*/ +static ReturnCode aatHillClimb( + const struct st25r3916AatTuneParams* tuningParams, + struct st25r3916AatTuneResult* tuningStatus); +static int32_t aatGreedyDescent( + uint32_t* f_min, + const struct st25r3916AatTuneParams* tuningParams, + struct st25r3916AatTuneResult* tuningStatus, + int32_t previousDir); +static int32_t aatSteepestDescent( + uint32_t* f_min, + const struct st25r3916AatTuneParams* tuningParams, + struct st25r3916AatTuneResult* tuningStatus, + int32_t previousDir, + int32_t previousDir2); + +static ReturnCode aatMeasure( + uint8_t serCap, + uint8_t parCap, + uint8_t* amplitude, + uint8_t* phase, + uint16_t* measureCnt); +static uint32_t + aatCalcF(const struct st25r3916AatTuneParams* tuningParams, uint8_t amplitude, uint8_t phase); +static ReturnCode aatStepDacVals( + const struct st25r3916AatTuneParams* tuningParams, + uint8_t* a, + uint8_t* b, + int32_t dir); + +/*******************************************************************************/ +ReturnCode st25r3916AatTune( + const struct st25r3916AatTuneParams* tuningParams, + struct st25r3916AatTuneResult* tuningStatus) { + ReturnCode err; + const struct st25r3916AatTuneParams* tp = tuningParams; + struct st25r3916AatTuneResult* ts = tuningStatus; + struct st25r3916AatTuneParams defaultTuningParams = { + .aat_a_min = 0, + .aat_a_max = 255, + .aat_a_start = 127, + .aat_a_stepWidth = 32, + .aat_b_min = 0, + .aat_b_max = 255, + .aat_b_start = 127, + .aat_b_stepWidth = 32, + + .phaTarget = 128, + .phaWeight = 2, + .ampTarget = 196, + .ampWeight = 1, + + .doDynamicSteps = true, + .measureLimit = 50, + }; + struct st25r3916AatTuneResult defaultTuneResult; + + if((NULL != tp) && ((tp->aat_a_min > tp->aat_a_max) || (tp->aat_a_start < tp->aat_a_min) || + (tp->aat_a_start > tp->aat_a_max) || (tp->aat_b_min > tp->aat_b_max) || + (tp->aat_b_start < tp->aat_b_min) || (tp->aat_b_start > tp->aat_b_max))) { + return ERR_PARAM; + } + + if(NULL == tp) { /* Start from current caps with default params */ + st25r3916ReadRegister(ST25R3916_REG_ANT_TUNE_A, &defaultTuningParams.aat_a_start); + st25r3916ReadRegister(ST25R3916_REG_ANT_TUNE_B, &defaultTuningParams.aat_b_start); + tp = &defaultTuningParams; + } + + if(NULL == ts) { + ts = &defaultTuneResult; + } + + ts->measureCnt = 0; /* Clear current measure count */ + + err = aatHillClimb(tp, ts); + + return err; +} + +/*******************************************************************************/ +static ReturnCode aatHillClimb( + const struct st25r3916AatTuneParams* tuningParams, + struct st25r3916AatTuneResult* tuningStatus) { + ReturnCode err = ERR_NONE; + uint32_t f_min; + int32_t direction, gdirection; + uint8_t amp, phs; + struct st25r3916AatTuneParams tp = *tuningParams; // local copy to obey const + + tuningStatus->aat_a = tuningParams->aat_a_start; + tuningStatus->aat_b = tuningParams->aat_b_start; + + /* Get a proper start value */ + aatMeasure(tuningStatus->aat_a, tuningStatus->aat_b, &, &phs, &tuningStatus->measureCnt); + f_min = aatCalcF(&tp, amp, phs); + direction = 0; + + st25r3916AatLog("%d %d: %d***\n", tuningStatus->aat_a, tuningStatus->aat_b, f_min); + + do { + direction = + 0; /* Initially and after reducing step sizes we don't have a previous direction */ + do { + /* With the greedy step below always executed aftwards the -direction does never need to be investigated */ + direction = aatSteepestDescent(&f_min, &tp, tuningStatus, direction, -direction); + if(tuningStatus->measureCnt > tp.measureLimit) { + err = ERR_OVERRUN; + break; + } + do { + gdirection = aatGreedyDescent(&f_min, &tp, tuningStatus, direction); + if(tuningStatus->measureCnt > tp.measureLimit) { + err = ERR_OVERRUN; + break; + } + } while(0 != gdirection); + } while(0 != direction); + tp.aat_a_stepWidth /= 2U; /* Reduce step sizes */ + tp.aat_b_stepWidth /= 2U; + } while(tp.doDynamicSteps && ((tp.aat_a_stepWidth > 0U) || (tp.aat_b_stepWidth > 0U))); + + return err; +} + +/*******************************************************************************/ +static int32_t aatSteepestDescent( + uint32_t* f_min, + const struct st25r3916AatTuneParams* tuningParams, + struct st25r3916AatTuneResult* tuningStatus, + int32_t previousDir, + int32_t previousDir2) { + int32_t i; + uint8_t amp, phs; + uint32_t f; + int32_t bestdir = + 0; /* Negative direction: decrease, Positive: increase. (-)1: aat_a, (-)2: aat_b */ + + for(i = -2; i <= 2; i++) { + uint8_t a = tuningStatus->aat_a, b = tuningStatus->aat_b; + + if((0 == i) || (i == -previousDir) || + (i == -previousDir2)) { /* Skip no direction and avoid going backwards */ + continue; + } + if(0U != aatStepDacVals( + tuningParams, + &a, + &b, + i)) { /* If stepping did not change the value, omit this direction */ + continue; + } + + aatMeasure(a, b, &, &phs, &tuningStatus->measureCnt); + f = aatCalcF(tuningParams, amp, phs); + st25r3916AatLog("%d : %d %d: %d", i, a, b, f); + if(f < *f_min) { /* Value is better than all previous ones */ + st25r3916AatLog("*"); + *f_min = f; + bestdir = i; + } + st25r3916AatLog("\n"); + } + if(0 != bestdir) { /* Walk into the best direction */ + aatStepDacVals(tuningParams, &tuningStatus->aat_a, &tuningStatus->aat_b, bestdir); + } + return bestdir; +} + +/*******************************************************************************/ +static int32_t aatGreedyDescent( + uint32_t* f_min, + const struct st25r3916AatTuneParams* tuningParams, + struct st25r3916AatTuneResult* tuningStatus, + int32_t previousDir) { + uint8_t amp, phs; + uint32_t f; + uint8_t a = tuningStatus->aat_a, b = tuningStatus->aat_b; + + if(0U != aatStepDacVals( + tuningParams, + &a, + &b, + previousDir)) { /* If stepping did not change the value, omit this direction */ + return 0; + } + + aatMeasure(a, b, &, &phs, &tuningStatus->measureCnt); + f = aatCalcF(tuningParams, amp, phs); + st25r3916AatLog("g : %d %d: %d", a, b, f); + if(f < *f_min) { /* Value is better than previous one */ + st25r3916AatLog("*\n"); + tuningStatus->aat_a = a; + tuningStatus->aat_b = b; + *f_min = f; + return previousDir; + } + + st25r3916AatLog("\n"); + return 0; +} + +/*******************************************************************************/ +static uint32_t + aatCalcF(const struct st25r3916AatTuneParams* tuningParams, uint8_t amplitude, uint8_t phase) { + /* f(amp, pha) = (ampWeight * |amp - ampTarget|) + (phaWeight * |pha - phaTarget|) */ + uint8_t ampTarget = tuningParams->ampTarget; + uint8_t phaTarget = tuningParams->phaTarget; + + uint32_t ampWeight = tuningParams->ampWeight; + uint32_t phaWeight = tuningParams->phaWeight; + + /* Temp variables to avoid MISRA R10.8 (cast on composite expression) */ + uint8_t ad = ((amplitude > ampTarget) ? (amplitude - ampTarget) : (ampTarget - amplitude)); + uint8_t pd = ((phase > phaTarget) ? (phase - phaTarget) : (phaTarget - phase)); + + uint32_t ampDelta = (uint32_t)ad; + uint32_t phaDelta = (uint32_t)pd; + + return ((ampWeight * ampDelta) + (phaWeight * phaDelta)); +} + +/*******************************************************************************/ +static ReturnCode aatStepDacVals( + const struct st25r3916AatTuneParams* tuningParams, + uint8_t* a, + uint8_t* b, + int32_t dir) { + int16_t aat_a = (int16_t)*a, aat_b = (int16_t)*b; + + switch(abs(dir)) { /* Advance by steps size in requested direction */ + case 1: + aat_a = (dir < 0) ? (aat_a - (int16_t)tuningParams->aat_a_stepWidth) : + (aat_a + (int16_t)tuningParams->aat_a_stepWidth); + if(aat_a < (int16_t)tuningParams->aat_a_min) { + aat_a = (int16_t)tuningParams->aat_a_min; + } + if(aat_a > (int16_t)tuningParams->aat_a_max) { + aat_a = (int16_t)tuningParams->aat_a_max; + } + if((int16_t)*a == aat_a) { + return ERR_PARAM; + } + break; + case 2: + aat_b = (dir < 0) ? (aat_b - (int16_t)tuningParams->aat_b_stepWidth) : + (aat_b + (int16_t)tuningParams->aat_b_stepWidth); + if(aat_b < (int16_t)tuningParams->aat_b_min) { + aat_b = (int16_t)tuningParams->aat_b_min; + } + if(aat_b > (int16_t)tuningParams->aat_b_max) { + aat_b = (int16_t)tuningParams->aat_b_max; + } + if((int16_t)*b == aat_b) { + return ERR_PARAM; + } + break; + default: + return ERR_REQUEST; + } + /* We only get here if actual values have changed. In all other cases an error is returned */ + *a = (uint8_t)aat_a; + *b = (uint8_t)aat_b; + + return ERR_NONE; +} + +/*******************************************************************************/ +static ReturnCode aatMeasure( + uint8_t serCap, + uint8_t parCap, + uint8_t* amplitude, + uint8_t* phase, + uint16_t* measureCnt) { + ReturnCode err; + + *amplitude = 0; + *phase = 0; + + st25r3916WriteRegister(ST25R3916_REG_ANT_TUNE_A, serCap); + st25r3916WriteRegister(ST25R3916_REG_ANT_TUNE_B, parCap); + + /* Wait till caps have settled.. */ + platformDelay(ST25R3916_AAT_CAP_DELAY_MAX); + + /* Get amplitude and phase .. */ + err = rfalChipMeasureAmplitude(amplitude); + if(ERR_NONE == err) { + err = rfalChipMeasurePhase(phase); + } + + if(measureCnt != NULL) { + (*measureCnt)++; + } + return err; +} diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/st25r3916_aat.h b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/st25r3916_aat.h new file mode 100644 index 00000000000..f1b34e4b603 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/st25r3916_aat.h @@ -0,0 +1,109 @@ +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R3916 firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file st25r3916_aat.h + * + * \author + * + * \brief ST25R3916 Antenna Tuning + * + * The antenna tuning algorithm tries to find the optimal settings for + * the AAT_A and AAT_B registers, which are connected to variable capacitors + * to tune the antenna matching. + * + */ + +#ifndef ST25R3916_AAT_H +#define ST25R3916_AAT_H + +#include "../../platform.h" +#include "../../st_errno.h" + +/* +****************************************************************************** +* GLOBAL DATATYPES +****************************************************************************** +*/ + +/*! + * struct representing input parameters for the antenna tuning + */ +struct st25r3916AatTuneParams { + uint8_t aat_a_min; /*!< min value of A cap */ + uint8_t aat_a_max; /*!< max value of A cap */ + uint8_t aat_a_start; /*!< start value of A cap */ + uint8_t aat_a_stepWidth; /*!< increment stepWidth for A cap */ + uint8_t aat_b_min; /*!< min value of B cap */ + uint8_t aat_b_max; /*!< max value of B cap */ + uint8_t aat_b_start; /*!< start value of B cap */ + uint8_t aat_b_stepWidth; /*!< increment stepWidth for B cap */ + + uint8_t phaTarget; /*!< target phase */ + uint8_t phaWeight; /*!< weight of target phase */ + uint8_t ampTarget; /*!< target amplitude */ + uint8_t ampWeight; /*!< weight of target amplitude */ + + bool doDynamicSteps; /*!< dynamically reduce step size in algo */ + uint8_t measureLimit; /*!< max number of allowed steps/measurements */ +}; + +/*! + * struct representing out parameters for the antenna tuning + */ +struct st25r3916AatTuneResult { + uint8_t aat_a; /*!< serial cap after tuning */ + uint8_t aat_b; /*!< parallel cap after tuning */ + uint8_t pha; /*!< phase after tuning */ + uint8_t amp; /*!< amplitude after tuning */ + uint16_t measureCnt; /*!< number of measures performed */ +}; + +/*! + ***************************************************************************** + * \brief Perform antenna tuning + * + * This function starts an antenna tuning procedure by modifying the serial + * and parallel capacitors of the antenna matching circuit via the AAT_A + * and AAT_B registers. + * + * \param[in] tuningParams : Input parameters for the tuning algorithm. If NULL + * default values will be used. + * \param[out] tuningStatus : Result information of performed tuning. If NULL + * no further information is returned, only registers + * ST25R3916 (AAT_A,B) will be adapted. + * + * \return ERR_IO : Error during communication. + * \return ERR_PARAM : Invalid input parameters + * \return ERR_NONE : No error. + * + ***************************************************************************** + */ +extern ReturnCode st25r3916AatTune( + const struct st25r3916AatTuneParams* tuningParams, + struct st25r3916AatTuneResult* tuningStatus); + +#endif /* ST25R3916_AAT_H */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/st25r3916_com.c b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/st25r3916_com.c new file mode 100644 index 00000000000..e05768a5604 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/st25r3916_com.c @@ -0,0 +1,618 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R3916 firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file + * + * \author Gustavo Patricio + * + * \brief Implementation of ST25R3916 communication + * + */ + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ + +#include "st25r3916.h" +#include "st25r3916_com.h" +#include "st25r3916_led.h" +#include "../../st_errno.h" +#include "../../platform.h" +#include "../../utils.h" + +/* +****************************************************************************** +* LOCAL DEFINES +****************************************************************************** +*/ + +#define ST25R3916_OPTIMIZE \ + true /*!< Optimization switch: false always write value to register */ +#define ST25R3916_I2C_ADDR \ + (0xA0U >> 1) /*!< ST25R3916's default I2C address */ +#define ST25R3916_REG_LEN 1U /*!< Byte length of a ST25R3916 register */ + +#define ST25R3916_WRITE_MODE \ + (0U << 6) /*!< ST25R3916 Operation Mode: Write */ +#define ST25R3916_READ_MODE \ + (1U << 6) /*!< ST25R3916 Operation Mode: Read */ +#define ST25R3916_CMD_MODE \ + (3U << 6) /*!< ST25R3916 Operation Mode: Direct Command */ +#define ST25R3916_FIFO_LOAD \ + (0x80U) /*!< ST25R3916 Operation Mode: FIFO Load */ +#define ST25R3916_FIFO_READ \ + (0x9FU) /*!< ST25R3916 Operation Mode: FIFO Read */ +#define ST25R3916_PT_A_CONFIG_LOAD \ + (0xA0U) /*!< ST25R3916 Operation Mode: Passive Target Memory A-Config Load */ +#define ST25R3916_PT_F_CONFIG_LOAD \ + (0xA8U) /*!< ST25R3916 Operation Mode: Passive Target Memory F-Config Load */ +#define ST25R3916_PT_TSN_DATA_LOAD \ + (0xACU) /*!< ST25R3916 Operation Mode: Passive Target Memory TSN Load */ +#define ST25R3916_PT_MEM_READ \ + (0xBFU) /*!< ST25R3916 Operation Mode: Passive Target Memory Read */ + +#define ST25R3916_CMD_LEN \ + (1U) /*!< ST25R3916 CMD length */ +#define ST25R3916_BUF_LEN \ + (ST25R3916_CMD_LEN + \ + ST25R3916_FIFO_DEPTH) /*!< ST25R3916 communication buffer: CMD + FIFO length */ + +/* +****************************************************************************** +* MACROS +****************************************************************************** +*/ +#ifdef RFAL_USE_I2C +#define st25r3916I2CStart() \ + platformI2CStart() /*!< ST25R3916 HAL I2C driver macro to start a I2C transfer */ +#define st25r3916I2CStop() \ + platformI2CStop() /*!< ST25R3916 HAL I2C driver macro to stop a I2C transfer */ +#define st25r3916I2CRepeatStart() \ + platformI2CRepeatStart() /*!< ST25R3916 HAL I2C driver macro to repeat Start */ +#define st25r3916I2CSlaveAddrWR(sA) \ + platformI2CSlaveAddrWR( \ + sA) /*!< ST25R3916 HAL I2C driver macro to repeat Start */ +#define st25r3916I2CSlaveAddrRD(sA) \ + platformI2CSlaveAddrRD( \ + sA) /*!< ST25R3916 HAL I2C driver macro to repeat Start */ +#endif /* RFAL_USE_I2C */ + +#if defined(ST25R_COM_SINGLETXRX) && !defined(RFAL_USE_I2C) +static uint8_t + comBuf[ST25R3916_BUF_LEN]; /*!< ST25R3916 communication buffer */ +static uint16_t comBufIt; /*!< ST25R3916 communication buffer iterator */ +#endif /* ST25R_COM_SINGLETXRX */ + +/* + ****************************************************************************** + * LOCAL FUNCTION PROTOTYPES + ****************************************************************************** + */ + +/*! + ****************************************************************************** + * \brief ST25R3916 communication Start + * + * This method performs the required actions to start communications with + * ST25R3916, either by SPI or I2C + ****************************************************************************** + */ +static void st25r3916comStart(void); + +/*! + ****************************************************************************** + * \brief ST25R3916 communication Stop + * + * This method performs the required actions to terminate communications with + * ST25R3916, either by SPI or I2C + ****************************************************************************** + */ +static void st25r3916comStop(void); + +/*! + ****************************************************************************** + * \brief ST25R3916 communication Repeat Start + * + * This method performs the required actions to repeat start a transmission + * with ST25R3916, either by SPI or I2C + ****************************************************************************** + */ +#ifdef RFAL_USE_I2C +static void st25r3916comRepeatStart(void); +#else +#define st25r3916comRepeatStart() +#endif /* RFAL_USE_I2C */ + +/*! + ****************************************************************************** + * \brief ST25R3916 communication Tx + * + * This method performs the required actions to transmit the given buffer + * to ST25R3916, either by SPI or I2C + * + * \param[in] txBuf : the buffer to transmit + * \param[in] txLen : the length of the buffer to transmit + * \param[in] last : true if last data to be transmitted + * \param[in] txOnly : true no reception is to be performed + * + ****************************************************************************** + */ +static void st25r3916comTx(const uint8_t* txBuf, uint16_t txLen, bool last, bool txOnly); + +/*! + ****************************************************************************** + * \brief ST25R3916 communication Rx + * + * This method performs the required actions to receive from ST25R3916 the given + * amount of bytes, either by SPI or I2C + * + * \param[out] rxBuf : the buffer place the received bytes + * \param[in] rxLen : the length to receive + * + ****************************************************************************** + */ +static void st25r3916comRx(uint8_t* rxBuf, uint16_t rxLen); + +/*! + ****************************************************************************** + * \brief ST25R3916 communication Tx Byte + * + * This helper method transmits a byte passed by value and not by reference + * + * \param[in] txByte : the value of the byte to be transmitted + * \param[in] last : true if last byte to be transmitted + * \param[in] txOnly : true no reception is to be performed + * + ****************************************************************************** + */ +static void st25r3916comTxByte(uint8_t txByte, bool last, bool txOnly); + +/* + ****************************************************************************** + * LOCAL FUNCTION + ****************************************************************************** + */ +static void st25r3916comStart(void) { + /* Make this operation atomic, disabling ST25R3916 interrupt during communications*/ + platformProtectST25RComm(); + +#ifdef RFAL_USE_I2C + /* I2C Start and send Slave Address */ + st25r3916I2CStart(); + st25r3916I2CSlaveAddrWR(ST25R3916_I2C_ADDR); +#else + /* Perform the chip select */ + platformSpiSelect(); + +#if defined(ST25R_COM_SINGLETXRX) + comBufIt = 0; /* reset local buffer position */ +#endif /* ST25R_COM_SINGLETXRX */ + +#endif /* RFAL_USE_I2C */ +} + +/*******************************************************************************/ +static void st25r3916comStop(void) { +#ifdef RFAL_USE_I2C + /* Generate Stop signal */ + st25r3916I2CStop(); +#else + /* Release the chip select */ + platformSpiDeselect(); +#endif /* RFAL_USE_I2C */ + + /* reEnable the ST25R3916 interrupt */ + platformUnprotectST25RComm(); +} + +/*******************************************************************************/ +#ifdef RFAL_USE_I2C +static void st25r3916comRepeatStart(void) { + st25r3916I2CRepeatStart(); + st25r3916I2CSlaveAddrRD(ST25R3916_I2C_ADDR); +} +#endif /* RFAL_USE_I2C */ + +/*******************************************************************************/ +static void st25r3916comTx(const uint8_t* txBuf, uint16_t txLen, bool last, bool txOnly) { + NO_WARNING(last); + NO_WARNING(txOnly); + + if(txLen > 0U) { +#ifdef RFAL_USE_I2C + platformI2CTx(txBuf, txLen, last, txOnly); +#else /* RFAL_USE_I2C */ + +#ifdef ST25R_COM_SINGLETXRX + + ST_MEMCPY( + &comBuf[comBufIt], + txBuf, + MIN(txLen, + (ST25R3916_BUF_LEN - + comBufIt))); /* copy tx data to local buffer */ + comBufIt += + MIN(txLen, + (ST25R3916_BUF_LEN - + comBufIt)); /* store position on local buffer */ + + if(last && txOnly) /* only perform SPI transaction if no Rx will follow */ + { + platformSpiTxRx(comBuf, NULL, comBufIt); + } + +#else + platformSpiTxRx(txBuf, NULL, txLen); +#endif /* ST25R_COM_SINGLETXRX */ + +#endif /* RFAL_USE_I2C */ + } +} + +/*******************************************************************************/ +static void st25r3916comRx(uint8_t* rxBuf, uint16_t rxLen) { + if(rxLen > 0U) { +#ifdef RFAL_USE_I2C + platformI2CRx(rxBuf, rxLen); +#else /* RFAL_USE_I2C */ + +#ifdef ST25R_COM_SINGLETXRX + ST_MEMSET( + &comBuf[comBufIt], + 0x00, + MIN(rxLen, + (ST25R3916_BUF_LEN - + comBufIt))); /* clear outgoing buffer */ + platformSpiTxRx( + comBuf, + comBuf, + MIN((comBufIt + rxLen), + ST25R3916_BUF_LEN)); /* transceive as a single SPI call */ + ST_MEMCPY( + rxBuf, + &comBuf[comBufIt], + MIN(rxLen, + (ST25R3916_BUF_LEN - + comBufIt))); /* copy from local buf to output buffer and skip cmd byte */ +#else + if(rxBuf != NULL) { + ST_MEMSET( + rxBuf, 0x00, rxLen); /* clear outgoing buffer */ + } + platformSpiTxRx(NULL, rxBuf, rxLen); +#endif /* ST25R_COM_SINGLETXRX */ +#endif /* RFAL_USE_I2C */ + } +} + +/*******************************************************************************/ +static void st25r3916comTxByte(uint8_t txByte, bool last, bool txOnly) { + uint8_t val = txByte; /* MISRA 17.8: use intermediate variable */ + st25r3916comTx(&val, ST25R3916_REG_LEN, last, txOnly); +} + +/* +****************************************************************************** +* GLOBAL FUNCTIONS +****************************************************************************** +*/ + +/*******************************************************************************/ +ReturnCode st25r3916ReadRegister(uint8_t reg, uint8_t* val) { + return st25r3916ReadMultipleRegisters(reg, val, ST25R3916_REG_LEN); +} + +/*******************************************************************************/ +ReturnCode st25r3916ReadMultipleRegisters(uint8_t reg, uint8_t* values, uint8_t length) { + if(length > 0U) { + st25r3916comStart(); + + /* If is a space-B register send a direct command first */ + if((reg & ST25R3916_SPACE_B) != 0U) { + st25r3916comTxByte(ST25R3916_CMD_SPACE_B_ACCESS, false, false); + } + + st25r3916comTxByte(((reg & ~ST25R3916_SPACE_B) | ST25R3916_READ_MODE), true, false); + st25r3916comRepeatStart(); + st25r3916comRx(values, length); + st25r3916comStop(); + } + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode st25r3916WriteRegister(uint8_t reg, uint8_t val) { + uint8_t value = val; /* MISRA 17.8: use intermediate variable */ + return st25r3916WriteMultipleRegisters(reg, &value, ST25R3916_REG_LEN); +} + +/*******************************************************************************/ +ReturnCode st25r3916WriteMultipleRegisters(uint8_t reg, const uint8_t* values, uint8_t length) { + if(length > 0U) { + st25r3916comStart(); + + if((reg & ST25R3916_SPACE_B) != 0U) { + st25r3916comTxByte(ST25R3916_CMD_SPACE_B_ACCESS, false, true); + } + + st25r3916comTxByte(((reg & ~ST25R3916_SPACE_B) | ST25R3916_WRITE_MODE), false, true); + st25r3916comTx(values, length, true, true); + st25r3916comStop(); + + /* Send a WriteMultiReg event to LED handling */ + st25r3916ledEvtWrMultiReg(reg, values, length); + } + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode st25r3916WriteFifo(const uint8_t* values, uint16_t length) { + if(length > ST25R3916_FIFO_DEPTH) { + return ERR_PARAM; + } + + if(length > 0U) { + st25r3916comStart(); + st25r3916comTxByte(ST25R3916_FIFO_LOAD, false, true); + st25r3916comTx(values, length, true, true); + st25r3916comStop(); + } + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode st25r3916ReadFifo(uint8_t* buf, uint16_t length) { + if(length > 0U) { + st25r3916comStart(); + st25r3916comTxByte(ST25R3916_FIFO_READ, true, false); + + st25r3916comRepeatStart(); + st25r3916comRx(buf, length); + st25r3916comStop(); + } + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode st25r3916WritePTMem(const uint8_t* values, uint16_t length) { + if(length > ST25R3916_PTM_LEN) { + return ERR_PARAM; + } + + if(length > 0U) { + st25r3916comStart(); + st25r3916comTxByte(ST25R3916_PT_A_CONFIG_LOAD, false, true); + st25r3916comTx(values, length, true, true); + st25r3916comStop(); + } + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode st25r3916ReadPTMem(uint8_t* values, uint16_t length) { + uint8_t + tmp[ST25R3916_REG_LEN + + ST25R3916_PTM_LEN]; /* local buffer to handle prepended byte on I2C and SPI */ + + if(length > 0U) { + if(length > ST25R3916_PTM_LEN) { + return ERR_PARAM; + } + + st25r3916comStart(); + st25r3916comTxByte(ST25R3916_PT_MEM_READ, true, false); + + st25r3916comRepeatStart(); + st25r3916comRx(tmp, (ST25R3916_REG_LEN + length)); /* skip prepended byte */ + st25r3916comStop(); + + /* Copy PTMem content without prepended byte */ + ST_MEMCPY(values, (tmp + ST25R3916_REG_LEN), length); + } + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode st25r3916WritePTMemF(const uint8_t* values, uint16_t length) { + if(length > (ST25R3916_PTM_F_LEN + ST25R3916_PTM_TSN_LEN)) { + return ERR_PARAM; + } + + if(length > 0U) { + st25r3916comStart(); + st25r3916comTxByte(ST25R3916_PT_F_CONFIG_LOAD, false, true); + st25r3916comTx(values, length, true, true); + st25r3916comStop(); + } + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode st25r3916WritePTMemTSN(const uint8_t* values, uint16_t length) { + if(length > ST25R3916_PTM_TSN_LEN) { + return ERR_PARAM; + } + + if(length > 0U) { + st25r3916comStart(); + st25r3916comTxByte(ST25R3916_PT_TSN_DATA_LOAD, false, true); + st25r3916comTx(values, length, true, true); + st25r3916comStop(); + } + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode st25r3916ExecuteCommand(uint8_t cmd) { + st25r3916comStart(); + st25r3916comTxByte((cmd | ST25R3916_CMD_MODE), true, true); + st25r3916comStop(); + + /* Send a cmd event to LED handling */ + st25r3916ledEvtCmd(cmd); + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode st25r3916ReadTestRegister(uint8_t reg, uint8_t* val) { + st25r3916comStart(); + st25r3916comTxByte(ST25R3916_CMD_TEST_ACCESS, false, false); + st25r3916comTxByte((reg | ST25R3916_READ_MODE), true, false); + st25r3916comRepeatStart(); + st25r3916comRx(val, ST25R3916_REG_LEN); + st25r3916comStop(); + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode st25r3916WriteTestRegister(uint8_t reg, uint8_t val) { + uint8_t value = val; /* MISRA 17.8: use intermediate variable */ + + st25r3916comStart(); + st25r3916comTxByte(ST25R3916_CMD_TEST_ACCESS, false, true); + st25r3916comTxByte((reg | ST25R3916_WRITE_MODE), false, true); + st25r3916comTx(&value, ST25R3916_REG_LEN, true, true); + st25r3916comStop(); + + return ERR_NONE; +} + +/*******************************************************************************/ +ReturnCode st25r3916ClrRegisterBits(uint8_t reg, uint8_t clr_mask) { + ReturnCode ret; + uint8_t rdVal; + + /* Read current reg value */ + EXIT_ON_ERR(ret, st25r3916ReadRegister(reg, &rdVal)); + + /* Only perform a Write if value to be written is different */ + if(ST25R3916_OPTIMIZE && (rdVal == (uint8_t)(rdVal & ~clr_mask))) { + return ERR_NONE; + } + + /* Write new reg value */ + return st25r3916WriteRegister(reg, (uint8_t)(rdVal & ~clr_mask)); +} + +/*******************************************************************************/ +ReturnCode st25r3916SetRegisterBits(uint8_t reg, uint8_t set_mask) { + ReturnCode ret; + uint8_t rdVal; + + /* Read current reg value */ + EXIT_ON_ERR(ret, st25r3916ReadRegister(reg, &rdVal)); + + /* Only perform a Write if the value to be written is different */ + if(ST25R3916_OPTIMIZE && (rdVal == (rdVal | set_mask))) { + return ERR_NONE; + } + + /* Write new reg value */ + return st25r3916WriteRegister(reg, (rdVal | set_mask)); +} + +/*******************************************************************************/ +ReturnCode st25r3916ChangeRegisterBits(uint8_t reg, uint8_t valueMask, uint8_t value) { + return st25r3916ModifyRegister(reg, valueMask, (valueMask & value)); +} + +/*******************************************************************************/ +ReturnCode st25r3916ModifyRegister(uint8_t reg, uint8_t clr_mask, uint8_t set_mask) { + ReturnCode ret; + uint8_t rdVal; + uint8_t wrVal; + + /* Read current reg value */ + EXIT_ON_ERR(ret, st25r3916ReadRegister(reg, &rdVal)); + + /* Compute new value */ + wrVal = (uint8_t)(rdVal & ~clr_mask); + wrVal |= set_mask; + + /* Only perform a Write if the value to be written is different */ + if(ST25R3916_OPTIMIZE && (rdVal == wrVal)) { + return ERR_NONE; + } + + /* Write new reg value */ + return st25r3916WriteRegister(reg, wrVal); +} + +/*******************************************************************************/ +ReturnCode st25r3916ChangeTestRegisterBits(uint8_t reg, uint8_t valueMask, uint8_t value) { + ReturnCode ret; + uint8_t rdVal; + uint8_t wrVal; + + /* Read current reg value */ + EXIT_ON_ERR(ret, st25r3916ReadTestRegister(reg, &rdVal)); + + /* Compute new value */ + wrVal = (uint8_t)(rdVal & ~valueMask); + wrVal |= (uint8_t)(value & valueMask); + + /* Only perform a Write if the value to be written is different */ + if(ST25R3916_OPTIMIZE && (rdVal == wrVal)) { + return ERR_NONE; + } + + /* Write new reg value */ + return st25r3916WriteTestRegister(reg, wrVal); +} + +/*******************************************************************************/ +bool st25r3916CheckReg(uint8_t reg, uint8_t mask, uint8_t val) { + uint8_t regVal; + + regVal = 0; + st25r3916ReadRegister(reg, ®Val); + + return ((regVal & mask) == val); +} + +/*******************************************************************************/ +bool st25r3916IsRegValid(uint8_t reg) { +#pragma GCC diagnostic ignored "-Wtype-limits" + if(!(((int16_t)reg >= (int32_t)ST25R3916_REG_IO_CONF1) && + (reg <= (ST25R3916_SPACE_B | ST25R3916_REG_IC_IDENTITY)))) { + return false; + } + return true; +} diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/st25r3916_com.h b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/st25r3916_com.h new file mode 100644 index 00000000000..177bd3ff3ae --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/st25r3916_com.h @@ -0,0 +1,1384 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R3916 firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file + * + * \author Gustavo Patricio + * + * \brief ST25R3916 communication declaration file + * + * This driver provides basic abstraction for communication with the ST25R3916 + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-HAL + * \brief RFAL Hardware Abstraction Layer + * @{ + * + * \addtogroup ST25R3916 + * \brief RFAL ST25R3916 Driver + * @{ + * + * \addtogroup ST25R3916_COM + * \brief RFAL ST25R3916 Communications + * @{ + * + */ + +#ifndef ST25R3916_COM_H +#define ST25R3916_COM_H + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ +#include "../../platform.h" +#include "../../st_errno.h" + +/* +****************************************************************************** +* GLOBAL DEFINES +****************************************************************************** +*/ +#define ST25R3916_SPACE_B 0x40U /*!< ST25R3916 Space-B indicator */ +#define ST25R3916_SPACE_B_REG_LEN 16U /*!< Number of register in the space B */ + +#define ST25R3916_FIFO_STATUS_LEN 2 /*!< Number of FIFO Status Register */ + +#define ST25R3916_PTM_A_LEN 15U /*!< Passive target memory A config length */ +#define ST25R3916_PTM_B_LEN 0U /*!< Passive target memory B config length */ +#define ST25R3916_PTM_F_LEN 21U /*!< Passive target memory F config length */ +#define ST25R3916_PTM_TSN_LEN 12U /*!< Passive target memory TSN data length */ + +/*! Full Passive target memory length */ +#define ST25R3916_PTM_LEN \ + (ST25R3916_PTM_A_LEN + ST25R3916_PTM_B_LEN + ST25R3916_PTM_F_LEN + ST25R3916_PTM_TSN_LEN) + +/* IO configuration registers */ +#define ST25R3916_REG_IO_CONF1 0x00U /*!< RW IO Configuration Register 1 */ +#define ST25R3916_REG_IO_CONF2 0x01U /*!< RW IO Configuration Register 2 */ + +/* Operation control and mode definition registers */ +#define ST25R3916_REG_OP_CONTROL 0x02U /*!< RW Operation Control Register */ +#define ST25R3916_REG_MODE 0x03U /*!< RW Mode Definition Register */ +#define ST25R3916_REG_BIT_RATE 0x04U /*!< RW Bit Rate Definition Register */ + +/* Protocol Configuration registers */ +#define ST25R3916_REG_ISO14443A_NFC \ + 0x05U /*!< RW ISO14443A and NFC 106 kBit/s Settings Register */ +#define ST25R3916_REG_EMD_SUP_CONF \ + (ST25R3916_SPACE_B | 0x05U) /*!< RW EMD Suppression Configuration Register */ +#define ST25R3916_REG_ISO14443B_1 \ + 0x06U /*!< RW ISO14443B Settings Register 1 */ +#define ST25R3916_REG_SUBC_START_TIME \ + (ST25R3916_SPACE_B | 0x06U) /*!< RW Subcarrier Start Time Register */ +#define ST25R3916_REG_ISO14443B_2 \ + 0x07U /*!< RW ISO14443B Settings Register 2 */ +#define ST25R3916_REG_PASSIVE_TARGET \ + 0x08U /*!< RW Passive Target Definition Register */ +#define ST25R3916_REG_STREAM_MODE \ + 0x09U /*!< RW Stream Mode Definition Register */ +#define ST25R3916_REG_AUX 0x0AU /*!< RW Auxiliary Definition Register */ + +/* Receiver Configuration registers */ +#define ST25R3916_REG_RX_CONF1 0x0BU /*!< RW Receiver Configuration Register 1 */ +#define ST25R3916_REG_RX_CONF2 0x0CU /*!< RW Receiver Configuration Register 2 */ +#define ST25R3916_REG_RX_CONF3 0x0DU /*!< RW Receiver Configuration Register 3 */ +#define ST25R3916_REG_RX_CONF4 0x0EU /*!< RW Receiver Configuration Register 4 */ +#define ST25R3916_REG_P2P_RX_CONF \ + (ST25R3916_SPACE_B | 0x0BU) /*!< RW P2P Receiver Configuration Register 1 */ +#define ST25R3916_REG_CORR_CONF1 \ + (ST25R3916_SPACE_B | 0x0CU) /*!< RW Correlator configuration register 1 */ +#define ST25R3916_REG_CORR_CONF2 \ + (ST25R3916_SPACE_B | 0x0DU) /*!< RW Correlator configuration register 2 */ + +/* Timer definition registers */ +#define ST25R3916_REG_MASK_RX_TIMER \ + 0x0FU /*!< RW Mask Receive Timer Register */ +#define ST25R3916_REG_NO_RESPONSE_TIMER1 \ + 0x10U /*!< RW No-response Timer Register 1 */ +#define ST25R3916_REG_NO_RESPONSE_TIMER2 \ + 0x11U /*!< RW No-response Timer Register 2 */ +#define ST25R3916_REG_TIMER_EMV_CONTROL \ + 0x12U /*!< RW Timer and EMV Control */ +#define ST25R3916_REG_GPT1 0x13U /*!< RW General Purpose Timer Register 1 */ +#define ST25R3916_REG_GPT2 0x14U /*!< RW General Purpose Timer Register 2 */ +#define ST25R3916_REG_PPON2 0x15U /*!< RW PPON2 Field waiting Timer Register */ +#define ST25R3916_REG_SQUELCH_TIMER \ + (ST25R3916_SPACE_B | 0x0FU) /*!< RW Squelch timeout Register */ +#define ST25R3916_REG_FIELD_ON_GT \ + (ST25R3916_SPACE_B | 0x15U) /*!< RW NFC Field on guard time */ + +/* Interrupt and associated reporting registers */ +#define ST25R3916_REG_IRQ_MASK_MAIN \ + 0x16U /*!< RW Mask Main Interrupt Register */ +#define ST25R3916_REG_IRQ_MASK_TIMER_NFC \ + 0x17U /*!< RW Mask Timer and NFC Interrupt Register */ +#define ST25R3916_REG_IRQ_MASK_ERROR_WUP \ + 0x18U /*!< RW Mask Error and Wake-up Interrupt Register */ +#define ST25R3916_REG_IRQ_MASK_TARGET \ + 0x19U /*!< RW Mask 3916 Target Interrupt Register */ +#define ST25R3916_REG_IRQ_MAIN 0x1AU /*!< R Main Interrupt Register */ +#define ST25R3916_REG_IRQ_TIMER_NFC \ + 0x1BU /*!< R Timer and NFC Interrupt Register */ +#define ST25R3916_REG_IRQ_ERROR_WUP \ + 0x1CU /*!< R Error and Wake-up Interrupt Register */ +#define ST25R3916_REG_IRQ_TARGET 0x1DU /*!< R ST25R3916 Target Interrupt Register */ +#define ST25R3916_REG_FIFO_STATUS1 \ + 0x1EU /*!< R FIFO Status Register 1 */ +#define ST25R3916_REG_FIFO_STATUS2 \ + 0x1FU /*!< R FIFO Status Register 2 */ +#define ST25R3916_REG_COLLISION_STATUS \ + 0x20U /*!< R Collision Display Register */ +#define ST25R3916_REG_PASSIVE_TARGET_STATUS \ + 0x21U /*!< R Passive target state status */ + +/* Definition of number of transmitted bytes */ +#define ST25R3916_REG_NUM_TX_BYTES1 \ + 0x22U /*!< RW Number of Transmitted Bytes Register 1 */ +#define ST25R3916_REG_NUM_TX_BYTES2 \ + 0x23U /*!< RW Number of Transmitted Bytes Register 2 */ + +/* NFCIP Bit Rate Display Register */ +#define ST25R3916_REG_NFCIP1_BIT_RATE \ + 0x24U /*!< R NFCIP Bit Rate Detection Display Register */ + +/* A/D Converter Output Register */ +#define ST25R3916_REG_AD_RESULT 0x25U /*!< R A/D Converter Output Register */ + +/* Antenna tuning registers */ +#define ST25R3916_REG_ANT_TUNE_A 0x26U /*!< RW Antenna Tuning Control (AAT-A) Register 1 */ +#define ST25R3916_REG_ANT_TUNE_B 0x27U /*!< RW Antenna Tuning Control (AAT-B) Register 2 */ + +/* Antenna Driver and Modulation registers */ +#define ST25R3916_REG_TX_DRIVER 0x28U /*!< RW TX driver register */ +#define ST25R3916_REG_PT_MOD 0x29U /*!< RW PT modulation Register */ +#define ST25R3916_REG_AUX_MOD \ + (ST25R3916_SPACE_B | 0x28U) /*!< RW Aux Modulation setting Register */ +#define ST25R3916_REG_TX_DRIVER_TIMING \ + (ST25R3916_SPACE_B | 0x29U) /*!< RW TX driver timing Register */ +#define ST25R3916_REG_RES_AM_MOD \ + (ST25R3916_SPACE_B | 0x2AU) /*!< RW Resistive AM modulation register */ +#define ST25R3916_REG_TX_DRIVER_STATUS \ + (ST25R3916_SPACE_B | 0x2BU) /*!< R TX driver timing readout Register */ + +/* External Field Detector Threshold Registers */ +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV \ + 0x2AU /*!< RW External Field Detector Activation Threshold Reg */ +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV \ + 0x2BU /*!< RW External Field Detector Deactivation Threshold Reg*/ + +/* Regulator registers */ +#define ST25R3916_REG_REGULATOR_CONTROL \ + 0x2CU /*!< RW Regulated Voltage Control Register */ +#define ST25R3916_REG_REGULATOR_RESULT \ + (ST25R3916_SPACE_B | 0x2CU) /*!< R Regulator Display Register */ + +/* Receiver State Display Register */ +#define ST25R3916_REG_RSSI_RESULT \ + 0x2DU /*!< R RSSI Display Register */ +#define ST25R3916_REG_GAIN_RED_STATE \ + 0x2EU /*!< R Gain Reduction State Register */ +#define ST25R3916_REG_CAP_SENSOR_CONTROL \ + 0x2FU /*!< RW Capacitive Sensor Control Register */ +#define ST25R3916_REG_CAP_SENSOR_RESULT \ + 0x30U /*!< R Capacitive Sensor Display Register */ +#define ST25R3916_REG_AUX_DISPLAY \ + 0x31U /*!< R Auxiliary Display Register */ + +/* Over/Undershoot Protection Configuration Registers */ +#define ST25R3916_REG_OVERSHOOT_CONF1 \ + (ST25R3916_SPACE_B | 0x30U) /*!< RW Overshoot Protection Configuration Register 1 */ +#define ST25R3916_REG_OVERSHOOT_CONF2 \ + (ST25R3916_SPACE_B | 0x31U) /*!< RW Overshoot Protection Configuration Register 2 */ +#define ST25R3916_REG_UNDERSHOOT_CONF1 \ + (ST25R3916_SPACE_B | 0x32U) /*!< RW Undershoot Protection Configuration Register 1 */ +#define ST25R3916_REG_UNDERSHOOT_CONF2 \ + (ST25R3916_SPACE_B | 0x33U) /*!< RW Undershoot Protection Configuration Register 2 */ + +/* Detection of card presence */ +#define ST25R3916_REG_WUP_TIMER_CONTROL \ + 0x32U /*!< RW Wake-up Timer Control Register */ +#define ST25R3916_REG_AMPLITUDE_MEASURE_CONF \ + 0x33U /*!< RW Amplitude Measurement Configuration Register */ +#define ST25R3916_REG_AMPLITUDE_MEASURE_REF \ + 0x34U /*!< RW Amplitude Measurement Reference Register */ +#define ST25R3916_REG_AMPLITUDE_MEASURE_AA_RESULT \ + 0x35U /*!< R Amplitude Measurement Auto Averaging Display Reg */ +#define ST25R3916_REG_AMPLITUDE_MEASURE_RESULT \ + 0x36U /*!< R Amplitude Measurement Display Register */ +#define ST25R3916_REG_PHASE_MEASURE_CONF \ + 0x37U /*!< RW Phase Measurement Configuration Register */ +#define ST25R3916_REG_PHASE_MEASURE_REF \ + 0x38U /*!< RW Phase Measurement Reference Register */ +#define ST25R3916_REG_PHASE_MEASURE_AA_RESULT \ + 0x39U /*!< R Phase Measurement Auto Averaging Display Register */ +#define ST25R3916_REG_PHASE_MEASURE_RESULT \ + 0x3AU /*!< R Phase Measurement Display Register */ +#define ST25R3916_REG_CAPACITANCE_MEASURE_CONF \ + 0x3BU /*!< RW Capacitance Measurement Configuration Register */ +#define ST25R3916_REG_CAPACITANCE_MEASURE_REF \ + 0x3CU /*!< RW Capacitance Measurement Reference Register */ +#define ST25R3916_REG_CAPACITANCE_MEASURE_AA_RESULT \ + 0x3DU /*!< R Capacitance Measurement Auto Averaging Display Reg*/ +#define ST25R3916_REG_CAPACITANCE_MEASURE_RESULT \ + 0x3EU /*!< R Capacitance Measurement Display Register */ + +/* IC identity */ +#define ST25R3916_REG_IC_IDENTITY \ + 0x3FU /*!< R Chip Id: 0 for old silicon, v2 silicon: 0x09 */ + +/*! Register bit definitions \cond DOXYGEN_SUPRESS */ + +#define ST25R3916_REG_IO_CONF1_single (1U << 7) +#define ST25R3916_REG_IO_CONF1_rfo2 (1U << 6) +#define ST25R3916_REG_IO_CONF1_i2c_thd1 (1U << 5) +#define ST25R3916_REG_IO_CONF1_i2c_thd0 (1U << 4) +#define ST25R3916_REG_IO_CONF1_i2c_thd_mask (3U << 4) +#define ST25R3916_REG_IO_CONF1_i2c_thd_shift (4U) +#define ST25R3916_REG_IO_CONF1_rfu (1U << 3) +#define ST25R3916_REG_IO_CONF1_out_cl1 (1U << 2) +#define ST25R3916_REG_IO_CONF1_out_cl0 (1U << 1) +#define ST25R3916_REG_IO_CONF1_out_cl_disabled (3U << 1) +#define ST25R3916_REG_IO_CONF1_out_cl_13_56MHZ (2U << 1) +#define ST25R3916_REG_IO_CONF1_out_cl_4_78MHZ (1U << 1) +#define ST25R3916_REG_IO_CONF1_out_cl_3_39MHZ (0U << 1) +#define ST25R3916_REG_IO_CONF1_out_cl_mask (3U << 1) +#define ST25R3916_REG_IO_CONF1_out_cl_shift (1U) +#define ST25R3916_REG_IO_CONF1_lf_clk_off (1U << 0) +#define ST25R3916_REG_IO_CONF1_lf_clk_off_on (1U << 0) +#define ST25R3916_REG_IO_CONF1_lf_clk_off_off (0U << 0) + +#define ST25R3916_REG_IO_CONF2_sup3V (1U << 7) +#define ST25R3916_REG_IO_CONF2_sup3V_3V (1U << 7) +#define ST25R3916_REG_IO_CONF2_sup3V_5V (0U << 7) +#define ST25R3916_REG_IO_CONF2_vspd_off (1U << 6) +#define ST25R3916_REG_IO_CONF2_aat_en (1U << 5) +#define ST25R3916_REG_IO_CONF2_miso_pd2 (1U << 4) +#define ST25R3916_REG_IO_CONF2_miso_pd1 (1U << 3) +#define ST25R3916_REG_IO_CONF2_io_drv_lvl (1U << 2) +#define ST25R3916_REG_IO_CONF2_slow_up (1U << 0) + +#define ST25R3916_REG_OP_CONTROL_en (1U << 7) +#define ST25R3916_REG_OP_CONTROL_rx_en (1U << 6) +#define ST25R3916_REG_OP_CONTROL_rx_chn (1U << 5) +#define ST25R3916_REG_OP_CONTROL_rx_man (1U << 4) +#define ST25R3916_REG_OP_CONTROL_tx_en (1U << 3) +#define ST25R3916_REG_OP_CONTROL_wu (1U << 2) +#define ST25R3916_REG_OP_CONTROL_en_fd_c1 (1U << 1) +#define ST25R3916_REG_OP_CONTROL_en_fd_c0 (1U << 0) +#define ST25R3916_REG_OP_CONTROL_en_fd_efd_off (0U << 0) +#define ST25R3916_REG_OP_CONTROL_en_fd_manual_efd_ca (1U << 0) +#define ST25R3916_REG_OP_CONTROL_en_fd_manual_efd_pdt (2U << 0) +#define ST25R3916_REG_OP_CONTROL_en_fd_auto_efd (3U << 0) +#define ST25R3916_REG_OP_CONTROL_en_fd_shift (0U) +#define ST25R3916_REG_OP_CONTROL_en_fd_mask (3U << 0) + +#define ST25R3916_REG_MODE_targ (1U << 7) +#define ST25R3916_REG_MODE_targ_targ (1U << 7) +#define ST25R3916_REG_MODE_targ_init (0U << 7) +#define ST25R3916_REG_MODE_om3 (1U << 6) +#define ST25R3916_REG_MODE_om2 (1U << 5) +#define ST25R3916_REG_MODE_om1 (1U << 4) +#define ST25R3916_REG_MODE_om0 (1U << 3) +#define ST25R3916_REG_MODE_om_bpsk_stream (0xfU << 3) +#define ST25R3916_REG_MODE_om_subcarrier_stream (0xeU << 3) +#define ST25R3916_REG_MODE_om_topaz (0x4U << 3) +#define ST25R3916_REG_MODE_om_felica (0x3U << 3) +#define ST25R3916_REG_MODE_om_iso14443b (0x2U << 3) +#define ST25R3916_REG_MODE_om_iso14443a (0x1U << 3) +#define ST25R3916_REG_MODE_om_targ_nfca (0x1U << 3) +#define ST25R3916_REG_MODE_om_targ_nfcb (0x2U << 3) +#define ST25R3916_REG_MODE_om_targ_nfcf (0x4U << 3) +#define ST25R3916_REG_MODE_om_targ_nfcip (0x7U << 3) +#define ST25R3916_REG_MODE_om_nfc (0x0U << 3) +#define ST25R3916_REG_MODE_om_mask (0xfU << 3) +#define ST25R3916_REG_MODE_om_shift (3U) +#define ST25R3916_REG_MODE_tr_am (1U << 2) +#define ST25R3916_REG_MODE_tr_am_ook (0U << 2) +#define ST25R3916_REG_MODE_tr_am_am (1U << 2) +#define ST25R3916_REG_MODE_nfc_ar1 (1U << 1) +#define ST25R3916_REG_MODE_nfc_ar0 (1U << 0) +#define ST25R3916_REG_MODE_nfc_ar_off (0U << 0) +#define ST25R3916_REG_MODE_nfc_ar_auto_rx (1U << 0) +#define ST25R3916_REG_MODE_nfc_ar_eof (2U << 0) +#define ST25R3916_REG_MODE_nfc_ar_rfu (3U << 0) +#define ST25R3916_REG_MODE_nfc_ar_mask (3U << 0) +#define ST25R3916_REG_MODE_nfc_ar_shift (0U) + +#define ST25R3916_REG_BIT_RATE_txrate_106 (0x0U << 4) +#define ST25R3916_REG_BIT_RATE_txrate_212 (0x1U << 4) +#define ST25R3916_REG_BIT_RATE_txrate_424 (0x2U << 4) +#define ST25R3916_REG_BIT_RATE_txrate_848 (0x3U << 4) +#define ST25R3916_REG_BIT_RATE_txrate_mask (0x3U << 4) +#define ST25R3916_REG_BIT_RATE_txrate_shift (4U) +#define ST25R3916_REG_BIT_RATE_rxrate_106 (0x0U << 0) +#define ST25R3916_REG_BIT_RATE_rxrate_212 (0x1U << 0) +#define ST25R3916_REG_BIT_RATE_rxrate_424 (0x2U << 0) +#define ST25R3916_REG_BIT_RATE_rxrate_848 (0x3U << 0) +#define ST25R3916_REG_BIT_RATE_rxrate_mask (0x3U << 0) +#define ST25R3916_REG_BIT_RATE_rxrate_shift (0U) + +#define ST25R3916_REG_ISO14443A_NFC_no_tx_par (1U << 7) +#define ST25R3916_REG_ISO14443A_NFC_no_tx_par_off (0U << 7) +#define ST25R3916_REG_ISO14443A_NFC_no_rx_par (1U << 6) +#define ST25R3916_REG_ISO14443A_NFC_no_rx_par_off (0U << 6) +#define ST25R3916_REG_ISO14443A_NFC_nfc_f0 (1U << 5) +#define ST25R3916_REG_ISO14443A_NFC_nfc_f0_off (0U << 5) +#define ST25R3916_REG_ISO14443A_NFC_p_len3 (1U << 4) +#define ST25R3916_REG_ISO14443A_NFC_p_len2 (1U << 3) +#define ST25R3916_REG_ISO14443A_NFC_p_len1 (1U << 2) +#define ST25R3916_REG_ISO14443A_NFC_p_len0 (1U << 1) +#define ST25R3916_REG_ISO14443A_NFC_p_len_mask (0xfU << 1) +#define ST25R3916_REG_ISO14443A_NFC_p_len_shift (1U) +#define ST25R3916_REG_ISO14443A_NFC_antcl (1U << 0) + +#define ST25R3916_REG_EMD_SUP_CONF_emd_emv (1U << 7) +#define ST25R3916_REG_EMD_SUP_CONF_emd_emv_on (1U << 7) +#define ST25R3916_REG_EMD_SUP_CONF_emd_emv_off (0U << 7) +#define ST25R3916_REG_EMD_SUP_CONF_rx_start_emv (1U << 6) +#define ST25R3916_REG_EMD_SUP_CONF_rx_start_emv_on (1U << 6) +#define ST25R3916_REG_EMD_SUP_CONF_rx_start_emv_off (0U << 6) +#define ST25R3916_REG_EMD_SUP_CONF_rfu1 (1U << 5) +#define ST25R3916_REG_EMD_SUP_CONF_rfu0 (1U << 4) +#define ST25R3916_REG_EMD_SUP_CONF_emd_thld3 (1U << 3) +#define ST25R3916_REG_EMD_SUP_CONF_emd_thld2 (1U << 2) +#define ST25R3916_REG_EMD_SUP_CONF_emd_thld1 (1U << 1) +#define ST25R3916_REG_EMD_SUP_CONF_emd_thld0 (1U << 0) +#define ST25R3916_REG_EMD_SUP_CONF_emd_thld_mask (0xfU << 0) +#define ST25R3916_REG_EMD_SUP_CONF_emd_thld_shift (0U) + +#define ST25R3916_REG_SUBC_START_TIME_rfu2 (1U << 7) +#define ST25R3916_REG_SUBC_START_TIME_rfu1 (1U << 6) +#define ST25R3916_REG_SUBC_START_TIME_rfu0 (1U << 5) +#define ST25R3916_REG_SUBC_START_TIME_sst4 (1U << 4) +#define ST25R3916_REG_SUBC_START_TIME_sst3 (1U << 3) +#define ST25R3916_REG_SUBC_START_TIME_sst2 (1U << 2) +#define ST25R3916_REG_SUBC_START_TIME_sst1 (1U << 1) +#define ST25R3916_REG_SUBC_START_TIME_sst0 (1U << 0) +#define ST25R3916_REG_SUBC_START_TIME_sst_mask (0x1fU << 0) +#define ST25R3916_REG_SUBC_START_TIME_sst_shift (0U) + +#define ST25R3916_REG_ISO14443B_1_egt2 (1U << 7) +#define ST25R3916_REG_ISO14443B_1_egt1 (1U << 6) +#define ST25R3916_REG_ISO14443B_1_egt0 (1U << 5) +#define ST25R3916_REG_ISO14443B_1_egt_shift (5U) +#define ST25R3916_REG_ISO14443B_1_egt_mask (7U << 5) +#define ST25R3916_REG_ISO14443B_1_sof_1 (1U << 3) +#define ST25R3916_REG_ISO14443B_1_sof_1_3etu (1U << 3) +#define ST25R3916_REG_ISO14443B_1_sof_1_2etu (0U << 3) +#define ST25R3916_REG_ISO14443B_1_sof_0 (1U << 4) +#define ST25R3916_REG_ISO14443B_1_sof_0_11etu (1U << 4) +#define ST25R3916_REG_ISO14443B_1_sof_0_10etu (0U << 4) +#define ST25R3916_REG_ISO14443B_1_sof_mask (3U << 3) +#define ST25R3916_REG_ISO14443B_1_eof (1U << 2) +#define ST25R3916_REG_ISO14443B_1_eof_11etu (1U << 2) +#define ST25R3916_REG_ISO14443B_1_eof_10etu (0U << 2) +#define ST25R3916_REG_ISO14443B_1_half (1U << 1) +#define ST25R3916_REG_ISO14443B_1_rx_st_om (1U << 0) + +#define ST25R3916_REG_ISO14443B_2_tr1_1 (1U << 7) +#define ST25R3916_REG_ISO14443B_2_tr1_0 (1U << 6) +#define ST25R3916_REG_ISO14443B_2_tr1_64fs32fs (1U << 6) +#define ST25R3916_REG_ISO14443B_2_tr1_80fs80fs (0U << 6) +#define ST25R3916_REG_ISO14443B_2_tr1_mask (3U << 6) +#define ST25R3916_REG_ISO14443B_2_tr1_shift (6U) +#define ST25R3916_REG_ISO14443B_2_no_sof (1U << 5) +#define ST25R3916_REG_ISO14443B_2_no_eof (1U << 4) +#define ST25R3916_REG_ISO14443B_rfu1 (1U << 3) +#define ST25R3916_REG_ISO14443B_rfu0 (1U << 2) +#define ST25R3916_REG_ISO14443B_2_f_p1 (1U << 1) +#define ST25R3916_REG_ISO14443B_2_f_p0 (1U << 0) +#define ST25R3916_REG_ISO14443B_2_f_p_96 (3U << 0) +#define ST25R3916_REG_ISO14443B_2_f_p_80 (2U << 0) +#define ST25R3916_REG_ISO14443B_2_f_p_64 (1U << 0) +#define ST25R3916_REG_ISO14443B_2_f_p_48 (0U << 0) +#define ST25R3916_REG_ISO14443B_2_f_p_mask (3U << 0) +#define ST25R3916_REG_ISO14443B_2_f_p_shift (0U) + +#define ST25R3916_REG_PASSIVE_TARGET_fdel_3 (1U << 7) +#define ST25R3916_REG_PASSIVE_TARGET_fdel_2 (1U << 6) +#define ST25R3916_REG_PASSIVE_TARGET_fdel_1 (1U << 5) +#define ST25R3916_REG_PASSIVE_TARGET_fdel_0 (1U << 4) +#define ST25R3916_REG_PASSIVE_TARGET_fdel_mask (0xfU << 4) +#define ST25R3916_REG_PASSIVE_TARGET_fdel_shift (4U) +#define ST25R3916_REG_PASSIVE_TARGET_d_ac_ap2p (1U << 3) +#define ST25R3916_REG_PASSIVE_TARGET_d_212_424_1r (1U << 2) +#define ST25R3916_REG_PASSIVE_TARGET_rfu (1U << 1) +#define ST25R3916_REG_PASSIVE_TARGET_d_106_ac_a (1U << 0) + +#define ST25R3916_REG_STREAM_MODE_rfu (1U << 7) +#define ST25R3916_REG_STREAM_MODE_scf1 (1U << 6) +#define ST25R3916_REG_STREAM_MODE_scf0 (1U << 5) +#define ST25R3916_REG_STREAM_MODE_scf_sc212 (0U << 5) +#define ST25R3916_REG_STREAM_MODE_scf_sc424 (1U << 5) +#define ST25R3916_REG_STREAM_MODE_scf_sc848 (2U << 5) +#define ST25R3916_REG_STREAM_MODE_scf_sc1695 (3U << 5) +#define ST25R3916_REG_STREAM_MODE_scf_bpsk848 (0U << 5) +#define ST25R3916_REG_STREAM_MODE_scf_bpsk1695 (1U << 5) +#define ST25R3916_REG_STREAM_MODE_scf_bpsk3390 (2U << 5) +#define ST25R3916_REG_STREAM_MODE_scf_bpsk106 (3U << 5) +#define ST25R3916_REG_STREAM_MODE_scf_mask (3U << 5) +#define ST25R3916_REG_STREAM_MODE_scf_shift (5U) +#define ST25R3916_REG_STREAM_MODE_scp1 (1U << 4) +#define ST25R3916_REG_STREAM_MODE_scp0 (1U << 3) +#define ST25R3916_REG_STREAM_MODE_scp_1pulse (0U << 3) +#define ST25R3916_REG_STREAM_MODE_scp_2pulses (1U << 3) +#define ST25R3916_REG_STREAM_MODE_scp_4pulses (2U << 3) +#define ST25R3916_REG_STREAM_MODE_scp_8pulses (3U << 3) +#define ST25R3916_REG_STREAM_MODE_scp_mask (3U << 3) +#define ST25R3916_REG_STREAM_MODE_scp_shift (3U) +#define ST25R3916_REG_STREAM_MODE_stx2 (1U << 2) +#define ST25R3916_REG_STREAM_MODE_stx1 (1U << 1) +#define ST25R3916_REG_STREAM_MODE_stx0 (1U << 0) +#define ST25R3916_REG_STREAM_MODE_stx_106 (0U << 0) +#define ST25R3916_REG_STREAM_MODE_stx_212 (1U << 0) +#define ST25R3916_REG_STREAM_MODE_stx_424 (2U << 0) +#define ST25R3916_REG_STREAM_MODE_stx_848 (3U << 0) +#define ST25R3916_REG_STREAM_MODE_stx_mask (7U << 0) +#define ST25R3916_REG_STREAM_MODE_stx_shift (0U) + +#define ST25R3916_REG_AUX_no_crc_rx (1U << 7) +#define ST25R3916_REG_AUX_rfu (1U << 6) +#define ST25R3916_REG_AUX_nfc_id1 (1U << 5) +#define ST25R3916_REG_AUX_nfc_id0 (1U << 4) +#define ST25R3916_REG_AUX_nfc_id_7bytes (1U << 4) +#define ST25R3916_REG_AUX_nfc_id_4bytes (0U << 4) +#define ST25R3916_REG_AUX_nfc_id_mask (3U << 4) +#define ST25R3916_REG_AUX_nfc_id_shift (4U) +#define ST25R3916_REG_AUX_mfaz_cl90 (1U << 3) +#define ST25R3916_REG_AUX_dis_corr (1U << 2) +#define ST25R3916_REG_AUX_dis_corr_coherent (1U << 2) +#define ST25R3916_REG_AUX_dis_corr_correlator (0U << 2) +#define ST25R3916_REG_AUX_nfc_n1 (1U << 1) +#define ST25R3916_REG_AUX_nfc_n0 (1U << 0) +#define ST25R3916_REG_AUX_nfc_n_mask (3U << 0) +#define ST25R3916_REG_AUX_nfc_n_shift (0U) + +#define ST25R3916_REG_RX_CONF1_ch_sel (1U << 7) +#define ST25R3916_REG_RX_CONF1_ch_sel_PM (1U << 7) +#define ST25R3916_REG_RX_CONF1_ch_sel_AM (0U << 7) +#define ST25R3916_REG_RX_CONF1_lp2 (1U << 6) +#define ST25R3916_REG_RX_CONF1_lp1 (1U << 5) +#define ST25R3916_REG_RX_CONF1_lp0 (1U << 4) +#define ST25R3916_REG_RX_CONF1_lp_1200khz (0U << 4) +#define ST25R3916_REG_RX_CONF1_lp_600khz (1U << 4) +#define ST25R3916_REG_RX_CONF1_lp_300khz (2U << 4) +#define ST25R3916_REG_RX_CONF1_lp_2000khz (4U << 4) +#define ST25R3916_REG_RX_CONF1_lp_7000khz (5U << 4) +#define ST25R3916_REG_RX_CONF1_lp_mask (7U << 4) +#define ST25R3916_REG_RX_CONF1_lp_shift (4U) +#define ST25R3916_REG_RX_CONF1_z600k (1U << 3) +#define ST25R3916_REG_RX_CONF1_h200 (1U << 2) +#define ST25R3916_REG_RX_CONF1_h80 (1U << 1) +#define ST25R3916_REG_RX_CONF1_z12k (1U << 0) +#define ST25R3916_REG_RX_CONF1_hz_60_400khz (0U << 0) +#define ST25R3916_REG_RX_CONF1_hz_60_200khz (4U << 0) +#define ST25R3916_REG_RX_CONF1_hz_40_80khz (2U << 0) +#define ST25R3916_REG_RX_CONF1_hz_12_200khz (1U << 0) +#define ST25R3916_REG_RX_CONF1_hz_12_80khz (3U << 0) +#define ST25R3916_REG_RX_CONF1_hz_12_200khz_alt (5U << 0) +#define ST25R3916_REG_RX_CONF1_hz_600_400khz (8U << 0) +#define ST25R3916_REG_RX_CONF1_hz_600_200khz (12U << 0) +#define ST25R3916_REG_RX_CONF1_hz_mask (0xfU << 0) +#define ST25R3916_REG_RX_CONF1_hz_shift (0U) + +#define ST25R3916_REG_RX_CONF2_demod_mode (1U << 7) +#define ST25R3916_REG_RX_CONF2_amd_sel (1U << 6) +#define ST25R3916_REG_RX_CONF2_amd_sel_mixer (1U << 6) +#define ST25R3916_REG_RX_CONF2_amd_sel_peak (0U << 6) +#define ST25R3916_REG_RX_CONF2_sqm_dyn (1U << 5) +#define ST25R3916_REG_RX_CONF2_pulz_61 (1U << 4) +#define ST25R3916_REG_RX_CONF2_agc_en (1U << 3) +#define ST25R3916_REG_RX_CONF2_agc_m (1U << 2) +#define ST25R3916_REG_RX_CONF2_agc_alg (1U << 1) +#define ST25R3916_REG_RX_CONF2_agc6_3 (1U << 0) + +#define ST25R3916_REG_RX_CONF3_rg1_am2 (1U << 7) +#define ST25R3916_REG_RX_CONF3_rg1_am1 (1U << 6) +#define ST25R3916_REG_RX_CONF3_rg1_am0 (1U << 5) +#define ST25R3916_REG_RX_CONF3_rg1_am_mask (0x7U << 5) +#define ST25R3916_REG_RX_CONF3_rg1_am_shift (5U) +#define ST25R3916_REG_RX_CONF3_rg1_pm2 (1U << 4) +#define ST25R3916_REG_RX_CONF3_rg1_pm1 (1U << 3) +#define ST25R3916_REG_RX_CONF3_rg1_pm0 (1U << 2) +#define ST25R3916_REG_RX_CONF3_rg1_pm_mask (0x7U << 2) +#define ST25R3916_REG_RX_CONF3_rg1_pm_shift (2U) +#define ST25R3916_REG_RX_CONF3_lf_en (1U << 1) +#define ST25R3916_REG_RX_CONF3_lf_op (1U << 0) + +#define ST25R3916_REG_RX_CONF4_rg2_am3 (1U << 7) +#define ST25R3916_REG_RX_CONF4_rg2_am2 (1U << 6) +#define ST25R3916_REG_RX_CONF4_rg2_am1 (1U << 5) +#define ST25R3916_REG_RX_CONF4_rg2_am0 (1U << 4) +#define ST25R3916_REG_RX_CONF4_rg2_am_mask (0xfU << 4) +#define ST25R3916_REG_RX_CONF4_rg2_am_shift (4U) +#define ST25R3916_REG_RX_CONF4_rg2_pm3 (1U << 3) +#define ST25R3916_REG_RX_CONF4_rg2_pm2 (1U << 2) +#define ST25R3916_REG_RX_CONF4_rg2_pm1 (1U << 1) +#define ST25R3916_REG_RX_CONF4_rg2_pm0 (1U << 0) +#define ST25R3916_REG_RX_CONF4_rg2_pm_mask (0xfU << 0) +#define ST25R3916_REG_RX_CONF4_rg2_pm_shift (0U) + +#define ST25R3916_REG_P2P_RX_CONF_ook_fd (1U << 7) +#define ST25R3916_REG_P2P_RX_CONF_ook_rc1 (1U << 6) +#define ST25R3916_REG_P2P_RX_CONF_ook_rc0 (1U << 5) +#define ST25R3916_REG_P2P_RX_CONF_ook_thd1 (1U << 4) +#define ST25R3916_REG_P2P_RX_CONF_ook_thd0 (1U << 3) +#define ST25R3916_REG_P2P_RX_CONF_ask_rc1 (1U << 2) +#define ST25R3916_REG_P2P_RX_CONF_ask_rc0 (1U << 1) +#define ST25R3916_REG_P2P_RX_CONF_ask_thd (1U << 0) + +#define ST25R3916_REG_CORR_CONF1_corr_s7 (1U << 7) +#define ST25R3916_REG_CORR_CONF1_corr_s6 (1U << 6) +#define ST25R3916_REG_CORR_CONF1_corr_s5 (1U << 5) +#define ST25R3916_REG_CORR_CONF1_corr_s4 (1U << 4) +#define ST25R3916_REG_CORR_CONF1_corr_s3 (1U << 3) +#define ST25R3916_REG_CORR_CONF1_corr_s2 (1U << 2) +#define ST25R3916_REG_CORR_CONF1_corr_s1 (1U << 1) +#define ST25R3916_REG_CORR_CONF1_corr_s0 (1U << 0) + +#define ST25R3916_REG_CORR_CONF2_rfu5 (1U << 7) +#define ST25R3916_REG_CORR_CONF2_rfu4 (1U << 6) +#define ST25R3916_REG_CORR_CONF2_rfu3 (1U << 5) +#define ST25R3916_REG_CORR_CONF2_rfu2 (1U << 4) +#define ST25R3916_REG_CORR_CONF2_rfu1 (1U << 3) +#define ST25R3916_REG_CORR_CONF2_rfu0 (1U << 2) +#define ST25R3916_REG_CORR_CONF2_corr_s9 (1U << 1) +#define ST25R3916_REG_CORR_CONF2_corr_s8 (1U << 0) + +#define ST25R3916_REG_TIMER_EMV_CONTROL_gptc2 (1U << 7) +#define ST25R3916_REG_TIMER_EMV_CONTROL_gptc1 (1U << 6) +#define ST25R3916_REG_TIMER_EMV_CONTROL_gptc0 (1U << 5) +#define ST25R3916_REG_TIMER_EMV_CONTROL_gptc_no_trigger (0U << 5) +#define ST25R3916_REG_TIMER_EMV_CONTROL_gptc_erx (1U << 5) +#define ST25R3916_REG_TIMER_EMV_CONTROL_gptc_srx (2U << 5) +#define ST25R3916_REG_TIMER_EMV_CONTROL_gptc_etx_nfc (3U << 5) +#define ST25R3916_REG_TIMER_EMV_CONTROL_gptc_mask (7U << 5) +#define ST25R3916_REG_TIMER_EMV_CONTROL_gptc_shift (5U) +#define ST25R3916_REG_TIMER_EMV_CONTROL_rfu (1U << 4) +#define ST25R3916_REG_TIMER_EMV_CONTROL_mrt_step (1U << 3) +#define ST25R3916_REG_TIMER_EMV_CONTROL_mrt_step_512 (1U << 3) +#define ST25R3916_REG_TIMER_EMV_CONTROL_mrt_step_64 (0U << 3) +#define ST25R3916_REG_TIMER_EMV_CONTROL_nrt_nfc (1U << 2) +#define ST25R3916_REG_TIMER_EMV_CONTROL_nrt_nfc_on (1U << 2) +#define ST25R3916_REG_TIMER_EMV_CONTROL_nrt_nfc_off (0U << 2) +#define ST25R3916_REG_TIMER_EMV_CONTROL_nrt_emv (1U << 1) +#define ST25R3916_REG_TIMER_EMV_CONTROL_nrt_emv_on (1U << 1) +#define ST25R3916_REG_TIMER_EMV_CONTROL_nrt_emv_off (0U << 1) +#define ST25R3916_REG_TIMER_EMV_CONTROL_nrt_step (1U << 0) +#define ST25R3916_REG_TIMER_EMV_CONTROL_nrt_step_64fc (0U << 0) +#define ST25R3916_REG_TIMER_EMV_CONTROL_nrt_step_4096_fc (1U << 0) + +#define ST25R3916_REG_FIFO_STATUS2_fifo_b9 (1U << 7) +#define ST25R3916_REG_FIFO_STATUS2_fifo_b8 (1U << 6) +#define ST25R3916_REG_FIFO_STATUS2_fifo_b_mask (3U << 6) +#define ST25R3916_REG_FIFO_STATUS2_fifo_b_shift (6U) +#define ST25R3916_REG_FIFO_STATUS2_fifo_unf (1U << 5) +#define ST25R3916_REG_FIFO_STATUS2_fifo_ovr (1U << 4) +#define ST25R3916_REG_FIFO_STATUS2_fifo_lb2 (1U << 3) +#define ST25R3916_REG_FIFO_STATUS2_fifo_lb1 (1U << 2) +#define ST25R3916_REG_FIFO_STATUS2_fifo_lb0 (1U << 1) +#define ST25R3916_REG_FIFO_STATUS2_fifo_lb_mask (7U << 1) +#define ST25R3916_REG_FIFO_STATUS2_fifo_lb_shift (1U) +#define ST25R3916_REG_FIFO_STATUS2_np_lb (1U << 0) + +#define ST25R3916_REG_COLLISION_STATUS_c_byte3 (1U << 7) +#define ST25R3916_REG_COLLISION_STATUS_c_byte2 (1U << 6) +#define ST25R3916_REG_COLLISION_STATUS_c_byte1 (1U << 5) +#define ST25R3916_REG_COLLISION_STATUS_c_byte0 (1U << 4) +#define ST25R3916_REG_COLLISION_STATUS_c_byte_mask (0xfU << 4) +#define ST25R3916_REG_COLLISION_STATUS_c_byte_shift (4U) +#define ST25R3916_REG_COLLISION_STATUS_c_bit2 (1U << 3) +#define ST25R3916_REG_COLLISION_STATUS_c_bit1 (1U << 2) +#define ST25R3916_REG_COLLISION_STATUS_c_bit0 (1U << 1) +#define ST25R3916_REG_COLLISION_STATUS_c_pb (1U << 0) +#define ST25R3916_REG_COLLISION_STATUS_c_bit_mask (3U << 1) +#define ST25R3916_REG_COLLISION_STATUS_c_bit_shift (1U) + +#define ST25R3916_REG_PASSIVE_TARGET_STATUS_rfu (1U << 7) +#define ST25R3916_REG_PASSIVE_TARGET_STATUS_rfu1 (1U << 6) +#define ST25R3916_REG_PASSIVE_TARGET_STATUS_rfu2 (1U << 5) +#define ST25R3916_REG_PASSIVE_TARGET_STATUS_rfu3 (1U << 4) +#define ST25R3916_REG_PASSIVE_TARGET_STATUS_pta_state3 (1U << 3) +#define ST25R3916_REG_PASSIVE_TARGET_STATUS_pta_state2 (1U << 2) +#define ST25R3916_REG_PASSIVE_TARGET_STATUS_pta_state1 (1U << 1) +#define ST25R3916_REG_PASSIVE_TARGET_STATUS_pta_state0 (1U << 0) +#define ST25R3916_REG_PASSIVE_TARGET_STATUS_pta_st_power_off (0x0U << 0) +#define ST25R3916_REG_PASSIVE_TARGET_STATUS_pta_st_idle (0x1U << 0) +#define ST25R3916_REG_PASSIVE_TARGET_STATUS_pta_st_ready_l1 (0x2U << 0) +#define ST25R3916_REG_PASSIVE_TARGET_STATUS_pta_st_ready_l2 (0x3U << 0) +#define ST25R3916_REG_PASSIVE_TARGET_STATUS_pta_st_rfu4 (0x4U << 0) +#define ST25R3916_REG_PASSIVE_TARGET_STATUS_pta_st_active (0x5U << 0) +#define ST25R3916_REG_PASSIVE_TARGET_STATUS_pta_st_rfu6 (0x6U << 0) +#define ST25R3916_REG_PASSIVE_TARGET_STATUS_pta_st_rfu7 (0x7U << 0) +#define ST25R3916_REG_PASSIVE_TARGET_STATUS_pta_st_rfu8 (0x8U << 0) +#define ST25R3916_REG_PASSIVE_TARGET_STATUS_pta_st_halt (0x9U << 0) +#define ST25R3916_REG_PASSIVE_TARGET_STATUS_pta_st_ready_l1_x (0xaU << 0) +#define ST25R3916_REG_PASSIVE_TARGET_STATUS_pta_st_ready_l2_x (0xbU << 0) +#define ST25R3916_REG_PASSIVE_TARGET_STATUS_pta_st_rfu12 (0xcU << 0) +#define ST25R3916_REG_PASSIVE_TARGET_STATUS_pta_st_active_x (0xdU << 0) +#define ST25R3916_REG_PASSIVE_TARGET_STATUS_pta_state_mask (0xfU << 0) +#define ST25R3916_REG_PASSIVE_TARGET_STATUS_pta_state_shift (0U) + +#define ST25R3916_REG_NUM_TX_BYTES2_ntx4 (1U << 7) +#define ST25R3916_REG_NUM_TX_BYTES2_ntx3 (1U << 6) +#define ST25R3916_REG_NUM_TX_BYTES2_ntx2 (1U << 5) +#define ST25R3916_REG_NUM_TX_BYTES2_ntx1 (1U << 4) +#define ST25R3916_REG_NUM_TX_BYTES2_ntx0 (1U << 3) +#define ST25R3916_REG_NUM_TX_BYTES2_ntx_mask (0x1fU << 3) +#define ST25R3916_REG_NUM_TX_BYTES2_ntx_shift (3U) +#define ST25R3916_REG_NUM_TX_BYTES2_nbtx2 (1U << 2) +#define ST25R3916_REG_NUM_TX_BYTES2_nbtx1 (1U << 1) +#define ST25R3916_REG_NUM_TX_BYTES2_nbtx0 (1U << 0) +#define ST25R3916_REG_NUM_TX_BYTES2_nbtx_mask (7U << 0) +#define ST25R3916_REG_NUM_TX_BYTES2_nbtx_shift (0U) + +#define ST25R3916_REG_NFCIP1_BIT_RATE_nfc_rfu1 (1U << 7) +#define ST25R3916_REG_NFCIP1_BIT_RATE_nfc_rfu0 (1U << 6) +#define ST25R3916_REG_NFCIP1_BIT_RATE_nfc_rate1 (1U << 5) +#define ST25R3916_REG_NFCIP1_BIT_RATE_nfc_rate0 (1U << 4) +#define ST25R3916_REG_NFCIP1_BIT_RATE_nfc_rate_mask (0x3U << 4) +#define ST25R3916_REG_NFCIP1_BIT_RATE_nfc_rate_shift (4U) +#define ST25R3916_REG_NFCIP1_BIT_RATE_ppt2_on (1U << 3) +#define ST25R3916_REG_NFCIP1_BIT_RATE_gpt_on (1U << 2) +#define ST25R3916_REG_NFCIP1_BIT_RATE_nrt_on (1U << 1) +#define ST25R3916_REG_NFCIP1_BIT_RATE_mrt_on (1U << 0) + +#define ST25R3916_REG_TX_DRIVER_am_mod3 (1U << 7) +#define ST25R3916_REG_TX_DRIVER_am_mod2 (1U << 6) +#define ST25R3916_REG_TX_DRIVER_am_mod1 (1U << 5) +#define ST25R3916_REG_TX_DRIVER_am_mod0 (1U << 4) +#define ST25R3916_REG_TX_DRIVER_am_mod_5percent (0x0U << 4) +#define ST25R3916_REG_TX_DRIVER_am_mod_6percent (0x1U << 4) +#define ST25R3916_REG_TX_DRIVER_am_mod_7percent (0x2U << 4) +#define ST25R3916_REG_TX_DRIVER_am_mod_8percent (0x3U << 4) +#define ST25R3916_REG_TX_DRIVER_am_mod_9percent (0x4U << 4) +#define ST25R3916_REG_TX_DRIVER_am_mod_10percent (0x5U << 4) +#define ST25R3916_REG_TX_DRIVER_am_mod_11percent (0x6U << 4) +#define ST25R3916_REG_TX_DRIVER_am_mod_12percent (0x7U << 4) +#define ST25R3916_REG_TX_DRIVER_am_mod_13percent (0x8U << 4) +#define ST25R3916_REG_TX_DRIVER_am_mod_14percent (0x9U << 4) +#define ST25R3916_REG_TX_DRIVER_am_mod_15percent (0xaU << 4) +#define ST25R3916_REG_TX_DRIVER_am_mod_17percent (0xbU << 4) +#define ST25R3916_REG_TX_DRIVER_am_mod_19percent (0xcU << 4) +#define ST25R3916_REG_TX_DRIVER_am_mod_22percent (0xdU << 4) +#define ST25R3916_REG_TX_DRIVER_am_mod_26percent (0xeU << 4) +#define ST25R3916_REG_TX_DRIVER_am_mod_40percent (0xfU << 4) +#define ST25R3916_REG_TX_DRIVER_am_mod_mask (0xfU << 4) +#define ST25R3916_REG_TX_DRIVER_am_mod_shift (4U) +#define ST25R3916_REG_TX_DRIVER_d_res3 (1U << 3) +#define ST25R3916_REG_TX_DRIVER_d_res2 (1U << 2) +#define ST25R3916_REG_TX_DRIVER_d_res1 (1U << 1) +#define ST25R3916_REG_TX_DRIVER_d_res0 (1U << 0) +#define ST25R3916_REG_TX_DRIVER_d_res_mask (0xfU << 0) +#define ST25R3916_REG_TX_DRIVER_d_res_shift (0U) + +#define ST25R3916_REG_PT_MOD_ptm_res3 (1U << 7) +#define ST25R3916_REG_PT_MOD_ptm_res2 (1U << 6) +#define ST25R3916_REG_PT_MOD_ptm_res1 (1U << 5) +#define ST25R3916_REG_PT_MOD_ptm_res0 (1U << 4) +#define ST25R3916_REG_PT_MOD_ptm_res_mask (0xfU << 4) +#define ST25R3916_REG_PT_MOD_ptm_res_shift (4U) +#define ST25R3916_REG_PT_MOD_pt_res3 (1U << 3) +#define ST25R3916_REG_PT_MOD_pt_res2 (1U << 2) +#define ST25R3916_REG_PT_MOD_pt_res1 (1U << 1) +#define ST25R3916_REG_PT_MOD_pt_res0 (1U << 0) +#define ST25R3916_REG_PT_MOD_pt_res_mask (0xfU << 0) +#define ST25R3916_REG_PT_MOD_pt_res_shift (0U) + +#define ST25R3916_REG_AUX_MOD_dis_reg_am (1U << 7) +#define ST25R3916_REG_AUX_MOD_lm_ext_pol (1U << 6) +#define ST25R3916_REG_AUX_MOD_lm_ext (1U << 5) +#define ST25R3916_REG_AUX_MOD_lm_dri (1U << 4) +#define ST25R3916_REG_AUX_MOD_res_am (1U << 3) +#define ST25R3916_REG_AUX_MOD_rfu2 (1U << 2) +#define ST25R3916_REG_AUX_MOD_rfu1 (1U << 1) +#define ST25R3916_REG_AUX_MOD_rfu0 (1U << 0) + +#define ST25R3916_REG_TX_DRIVER_TIMING_d_rat_t3 (1U << 7) +#define ST25R3916_REG_TX_DRIVER_TIMING_d_rat_t2 (1U << 6) +#define ST25R3916_REG_TX_DRIVER_TIMING_d_rat_t1 (1U << 5) +#define ST25R3916_REG_TX_DRIVER_TIMING_d_rat_t0 (1U << 4) +#define ST25R3916_REG_TX_DRIVER_TIMING_d_rat_mask (0xfU << 4) +#define ST25R3916_REG_TX_DRIVER_TIMING_d_rat_shift (4U) +#define ST25R3916_REG_TX_DRIVER_TIMING_rfu (1U << 3) +#define ST25R3916_REG_TX_DRIVER_TIMING_d_tim_m2 (1U << 2) +#define ST25R3916_REG_TX_DRIVER_TIMING_d_tim_m1 (1U << 1) +#define ST25R3916_REG_TX_DRIVER_TIMING_d_tim_m0 (1U << 0) +#define ST25R3916_REG_TX_DRIVER_TIMING_d_tim_m_mask (0x7U << 0) +#define ST25R3916_REG_TX_DRIVER_TIMING_d_tim_m_shift (0U) + +#define ST25R3916_REG_RES_AM_MOD_fa3_f (1U << 7) +#define ST25R3916_REG_RES_AM_MOD_md_res6 (1U << 6) +#define ST25R3916_REG_RES_AM_MOD_md_res5 (1U << 5) +#define ST25R3916_REG_RES_AM_MOD_md_res4 (1U << 4) +#define ST25R3916_REG_RES_AM_MOD_md_res3 (1U << 3) +#define ST25R3916_REG_RES_AM_MOD_md_res2 (1U << 2) +#define ST25R3916_REG_RES_AM_MOD_md_res1 (1U << 1) +#define ST25R3916_REG_RES_AM_MOD_md_res0 (1U << 0) +#define ST25R3916_REG_RES_AM_MOD_md_res_mask (0x7FU << 0) +#define ST25R3916_REG_RES_AM_MOD_md_res_shift (0U) + +#define ST25R3916_REG_TX_DRIVER_STATUS_d_rat_r3 (1U << 7) +#define ST25R3916_REG_TX_DRIVER_STATUS_d_rat_r2 (1U << 6) +#define ST25R3916_REG_TX_DRIVER_STATUS_d_rat_r1 (1U << 5) +#define ST25R3916_REG_TX_DRIVER_STATUS_d_rat_r0 (1U << 4) +#define ST25R3916_REG_TX_DRIVER_STATUS_d_rat_mask (0xfU << 4) +#define ST25R3916_REG_TX_DRIVER_STATUS_d_rat_shift (4U) +#define ST25R3916_REG_TX_DRIVER_STATUS_rfu (1U << 3) +#define ST25R3916_REG_TX_DRIVER_STATUS_d_tim_r2 (1U << 2) +#define ST25R3916_REG_TX_DRIVER_STATUS_d_tim_r1 (1U << 1) +#define ST25R3916_REG_TX_DRIVER_STATUS_d_tim_r0 (1U << 0) +#define ST25R3916_REG_TX_DRIVER_STATUS_d_tim_mask (0x7U << 0) +#define ST25R3916_REG_TX_DRIVER_STATUS_d_tim_shift (0U) + +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_trg_l2a (1U << 6) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_trg_l1a (1U << 5) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_trg_l0a (1U << 4) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_trg_75mV (0x0U << 4) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_trg_105mV (0x1U << 4) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_trg_150mV (0x2U << 4) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_trg_205mV (0x3U << 4) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_trg_290mV (0x4U << 4) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_trg_400mV (0x5U << 4) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_trg_560mV (0x6U << 4) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_trg_800mV (0x7U << 4) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_trg_mask (7U << 4) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_trg_shift (4U) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_t3a (1U << 3) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_t2a (1U << 2) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_t1a (1U << 1) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_t0a (1U << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_75mV (0x0U << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_105mV (0x1U << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_150mV (0x2U << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_205mV (0x3U << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_290mV (0x4U << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_400mV (0x5U << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_560mV (0x6U << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_800mV (0x7U << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_25mV (0x8U << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_33mV (0x9U << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_47mV (0xAU << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_64mV (0xBU << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_90mV (0xCU << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_125mV (0xDU << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_175mV (0xEU << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_250mV (0xFU << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_mask (0xfU << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_ACTV_rfe_shift (0U) + +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_trg_l2d (1U << 6) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_trg_l1d (1U << 5) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_trg_l0d (1U << 4) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_trg_75mV (0x0U << 4) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_trg_105mV (0x1U << 4) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_trg_150mV (0x2U << 4) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_trg_205mV (0x3U << 4) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_trg_290mV (0x4U << 4) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_trg_400mV (0x5U << 4) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_trg_560mV (0x6U << 4) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_trg_800mV (0x7U << 4) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_trg_mask (7U << 4) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_trg_shift (4U) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_rfe_t3d (1U << 3) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_rfe_t2d (1U << 2) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_rfe_t1d (1U << 1) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_rfe_t0d (1U << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_rfe_75mV (0x0U << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_rfe_105mV (0x1U << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_rfe_150mV (0x2U << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_rfe_205mV (0x3U << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_rfe_290mV (0x4U << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_rfe_400mV (0x5U << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_rfe_560mV (0x6U << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_rfe_800mV (0x7U << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_rfe_25mV (0x8U << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_rfe_33mV (0x9U << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_rfe_47mV (0xAU << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_rfe_64mV (0xBU << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_rfe_90mV (0xCU << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_rfe_125mV (0xDU << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_rfe_175mV (0xEU << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_rfe_250mV (0xFU << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_rfe_mask (0xfU << 0) +#define ST25R3916_REG_FIELD_THRESHOLD_DEACTV_rfe_shift (0U) + +#define ST25R3916_REG_REGULATOR_CONTROL_reg_s (1U << 7) +#define ST25R3916_REG_REGULATOR_CONTROL_rege_3 (1U << 6) +#define ST25R3916_REG_REGULATOR_CONTROL_rege_2 (1U << 5) +#define ST25R3916_REG_REGULATOR_CONTROL_rege_1 (1U << 4) +#define ST25R3916_REG_REGULATOR_CONTROL_rege_0 (1U << 3) +#define ST25R3916_REG_REGULATOR_CONTROL_rege_mask (0xfU << 3) +#define ST25R3916_REG_REGULATOR_CONTROL_rege_shift (3U) +#define ST25R3916_REG_REGULATOR_CONTROL_mpsv2 (2U << 2) +#define ST25R3916_REG_REGULATOR_CONTROL_mpsv1 (1U << 1) +#define ST25R3916_REG_REGULATOR_CONTROL_mpsv0 (1U << 0) +#define ST25R3916_REG_REGULATOR_CONTROL_mpsv_vdd (0U) +#define ST25R3916_REG_REGULATOR_CONTROL_mpsv_vdd_a (1U) +#define ST25R3916_REG_REGULATOR_CONTROL_mpsv_vdd_d (2U) +#define ST25R3916_REG_REGULATOR_CONTROL_mpsv_vdd_rf (3U) +#define ST25R3916_REG_REGULATOR_CONTROL_mpsv_vdd_am (4U) +#define ST25R3916_REG_REGULATOR_CONTROL_rfu (5U) +#define ST25R3916_REG_REGULATOR_CONTROL_rfu1 (6U) +#define ST25R3916_REG_REGULATOR_CONTROL_rfu2 (7U) +#define ST25R3916_REG_REGULATOR_CONTROL_mpsv_mask (7U) +#define ST25R3916_REG_REGULATOR_CONTROL_mpsv_shift (0U) + +#define ST25R3916_REG_REGULATOR_RESULT_reg_3 (1U << 7) +#define ST25R3916_REG_REGULATOR_RESULT_reg_2 (1U << 6) +#define ST25R3916_REG_REGULATOR_RESULT_reg_1 (1U << 5) +#define ST25R3916_REG_REGULATOR_RESULT_reg_0 (1U << 4) +#define ST25R3916_REG_REGULATOR_RESULT_reg_mask (0xfU << 4) +#define ST25R3916_REG_REGULATOR_RESULT_reg_shift (4U) +#define ST25R3916_REG_REGULATOR_RESULT_i_lim (1U << 0) + +#define ST25R3916_REG_RSSI_RESULT_rssi_am_3 (1U << 7) +#define ST25R3916_REG_RSSI_RESULT_rssi_am_2 (1U << 6) +#define ST25R3916_REG_RSSI_RESULT_rssi_am_1 (1U << 5) +#define ST25R3916_REG_RSSI_RESULT_rssi_am_0 (1U << 4) +#define ST25R3916_REG_RSSI_RESULT_rssi_am_mask (0xfU << 4) +#define ST25R3916_REG_RSSI_RESULT_rssi_am_shift (4U) +#define ST25R3916_REG_RSSI_RESULT_rssi_pm3 (1U << 3) +#define ST25R3916_REG_RSSI_RESULT_rssi_pm2 (1U << 2) +#define ST25R3916_REG_RSSI_RESULT_rssi_pm1 (1U << 1) +#define ST25R3916_REG_RSSI_RESULT_rssi_pm0 (1U << 0) +#define ST25R3916_REG_RSSI_RESULT_rssi_pm_mask (0xfU << 0) +#define ST25R3916_REG_RSSI_RESULT_rssi_pm_shift (0U) + +#define ST25R3916_REG_GAIN_RED_STATE_gs_am_3 (1U << 7) +#define ST25R3916_REG_GAIN_RED_STATE_gs_am_2 (1U << 6) +#define ST25R3916_REG_GAIN_RED_STATE_gs_am_1 (1U << 5) +#define ST25R3916_REG_GAIN_RED_STATE_gs_am_0 (1U << 4) +#define ST25R3916_REG_GAIN_RED_STATE_gs_am_mask (0xfU << 4) +#define ST25R3916_REG_GAIN_RED_STATE_gs_am_shift (4U) +#define ST25R3916_REG_GAIN_RED_STATE_gs_pm_3 (1U << 3) +#define ST25R3916_REG_GAIN_RED_STATE_gs_pm_2 (1U << 2) +#define ST25R3916_REG_GAIN_RED_STATE_gs_pm_1 (1U << 1) +#define ST25R3916_REG_GAIN_RED_STATE_gs_pm_0 (1U << 0) +#define ST25R3916_REG_GAIN_RED_STATE_gs_pm_mask (0xfU << 0) +#define ST25R3916_REG_GAIN_RED_STATE_gs_pm_shift (0U) + +#define ST25R3916_REG_CAP_SENSOR_CONTROL_cs_mcal4 (1U << 7) +#define ST25R3916_REG_CAP_SENSOR_CONTROL_cs_mcal3 (1U << 6) +#define ST25R3916_REG_CAP_SENSOR_CONTROL_cs_mcal2 (1U << 5) +#define ST25R3916_REG_CAP_SENSOR_CONTROL_cs_mcal1 (1U << 4) +#define ST25R3916_REG_CAP_SENSOR_CONTROL_cs_mcal0 (1U << 3) +#define ST25R3916_REG_CAP_SENSOR_CONTROL_cs_mcal_mask (0x1fU << 3) +#define ST25R3916_REG_CAP_SENSOR_CONTROL_cs_mcal_shift (3U) +#define ST25R3916_REG_CAP_SENSOR_CONTROL_cs_g2 (1U << 2) +#define ST25R3916_REG_CAP_SENSOR_CONTROL_cs_g1 (1U << 1) +#define ST25R3916_REG_CAP_SENSOR_CONTROL_cs_g0 (1U << 0) +#define ST25R3916_REG_CAP_SENSOR_CONTROL_cs_g_mask (7U << 0) +#define ST25R3916_REG_CAP_SENSOR_CONTROL_cs_g_shift (0U) + +#define ST25R3916_REG_CAP_SENSOR_RESULT_cs_cal4 (1U << 7) +#define ST25R3916_REG_CAP_SENSOR_RESULT_cs_cal3 (1U << 6) +#define ST25R3916_REG_CAP_SENSOR_RESULT_cs_cal2 (1U << 5) +#define ST25R3916_REG_CAP_SENSOR_RESULT_cs_cal1 (1U << 4) +#define ST25R3916_REG_CAP_SENSOR_RESULT_cs_cal0 (1U << 3) +#define ST25R3916_REG_CAP_SENSOR_RESULT_cs_cal_mask (0x1fU << 3) +#define ST25R3916_REG_CAP_SENSOR_RESULT_cs_cal_shift (3U) +#define ST25R3916_REG_CAP_SENSOR_RESULT_cs_cal_end (1U << 2) +#define ST25R3916_REG_CAP_SENSOR_RESULT_cs_cal_err (1U << 1) + +#define ST25R3916_REG_AUX_DISPLAY_a_cha (1U << 7) +#define ST25R3916_REG_AUX_DISPLAY_efd_o (1U << 6) +#define ST25R3916_REG_AUX_DISPLAY_tx_on (1U << 5) +#define ST25R3916_REG_AUX_DISPLAY_osc_ok (1U << 4) +#define ST25R3916_REG_AUX_DISPLAY_rx_on (1U << 3) +#define ST25R3916_REG_AUX_DISPLAY_rx_act (1U << 2) +#define ST25R3916_REG_AUX_DISPLAY_en_peer (1U << 1) +#define ST25R3916_REG_AUX_DISPLAY_en_ac (1U << 0) + +#define ST25R3916_REG_OVERSHOOT_CONF1_ov_tx_mode1 (1U << 7) +#define ST25R3916_REG_OVERSHOOT_CONF1_ov_tx_mode0 (1U << 6) +#define ST25R3916_REG_OVERSHOOT_CONF1_ov_pattern13 (1U << 5) +#define ST25R3916_REG_OVERSHOOT_CONF1_ov_pattern12 (1U << 4) +#define ST25R3916_REG_OVERSHOOT_CONF1_ov_pattern11 (1U << 3) +#define ST25R3916_REG_OVERSHOOT_CONF1_ov_pattern10 (1U << 2) +#define ST25R3916_REG_OVERSHOOT_CONF1_ov_pattern9 (1U << 1) +#define ST25R3916_REG_OVERSHOOT_CONF1_ov_pattern8 (1U << 0) + +#define ST25R3916_REG_OVERSHOOT_CONF2_ov_pattern7 (1U << 7) +#define ST25R3916_REG_OVERSHOOT_CONF2_ov_pattern6 (1U << 6) +#define ST25R3916_REG_OVERSHOOT_CONF2_ov_pattern5 (1U << 5) +#define ST25R3916_REG_OVERSHOOT_CONF2_ov_pattern4 (1U << 4) +#define ST25R3916_REG_OVERSHOOT_CONF2_ov_pattern3 (1U << 3) +#define ST25R3916_REG_OVERSHOOT_CONF2_ov_pattern2 (1U << 2) +#define ST25R3916_REG_OVERSHOOT_CONF2_ov_pattern1 (1U << 1) +#define ST25R3916_REG_OVERSHOOT_CONF2_ov_pattern0 (1U << 0) + +#define ST25R3916_REG_UNDERSHOOT_CONF1_un_tx_mode1 (1U << 7) +#define ST25R3916_REG_UNDERSHOOT_CONF1_un_tx_mode0 (1U << 6) +#define ST25R3916_REG_UNDERSHOOT_CONF1_un_pattern13 (1U << 5) +#define ST25R3916_REG_UNDERSHOOT_CONF1_un_pattern12 (1U << 4) +#define ST25R3916_REG_UNDERSHOOT_CONF1_un_pattern11 (1U << 3) +#define ST25R3916_REG_UNDERSHOOT_CONF1_un_pattern10 (1U << 2) +#define ST25R3916_REG_UNDERSHOOT_CONF1_un_pattern9 (1U << 1) +#define ST25R3916_REG_UNDERSHOOT_CONF1_un_pattern8 (1U << 0) + +#define ST25R3916_REG_UNDERSHOOT_CONF2_un_pattern7 (1U << 7) +#define ST25R3916_REG_UNDERSHOOT_CONF2_un_pattern6 (1U << 6) +#define ST25R3916_REG_UNDERSHOOT_CONF2_un_pattern5 (1U << 5) +#define ST25R3916_REG_UNDERSHOOT_CONF2_un_pattern4 (1U << 4) +#define ST25R3916_REG_UNDERSHOOT_CONF2_un_pattern3 (1U << 3) +#define ST25R3916_REG_UNDERSHOOT_CONF2_un_pattern2 (1U << 2) +#define ST25R3916_REG_UNDERSHOOT_CONF2_un_pattern1 (1U << 1) +#define ST25R3916_REG_UNDERSHOOT_CONF2_un_pattern0 (1U << 0) + +#define ST25R3916_REG_WUP_TIMER_CONTROL_wur (1U << 7) +#define ST25R3916_REG_WUP_TIMER_CONTROL_wut2 (1U << 6) +#define ST25R3916_REG_WUP_TIMER_CONTROL_wut1 (1U << 5) +#define ST25R3916_REG_WUP_TIMER_CONTROL_wut0 (1U << 4) +#define ST25R3916_REG_WUP_TIMER_CONTROL_wut_mask (7U << 4) +#define ST25R3916_REG_WUP_TIMER_CONTROL_wut_shift (4U) +#define ST25R3916_REG_WUP_TIMER_CONTROL_wto (1U << 3) +#define ST25R3916_REG_WUP_TIMER_CONTROL_wam (1U << 2) +#define ST25R3916_REG_WUP_TIMER_CONTROL_wph (1U << 1) +#define ST25R3916_REG_WUP_TIMER_CONTROL_wcap (1U << 0) + +#define ST25R3916_REG_AMPLITUDE_MEASURE_CONF_am_d3 (1U << 7) +#define ST25R3916_REG_AMPLITUDE_MEASURE_CONF_am_d2 (1U << 6) +#define ST25R3916_REG_AMPLITUDE_MEASURE_CONF_am_d1 (1U << 5) +#define ST25R3916_REG_AMPLITUDE_MEASURE_CONF_am_d0 (1U << 4) +#define ST25R3916_REG_AMPLITUDE_MEASURE_CONF_am_d_mask (0xfU << 4) +#define ST25R3916_REG_AMPLITUDE_MEASURE_CONF_am_d_shift (4U) +#define ST25R3916_REG_AMPLITUDE_MEASURE_CONF_am_aam (1U << 3) +#define ST25R3916_REG_AMPLITUDE_MEASURE_CONF_am_aew1 (1U << 2) +#define ST25R3916_REG_AMPLITUDE_MEASURE_CONF_am_aew0 (1U << 1) +#define ST25R3916_REG_AMPLITUDE_MEASURE_CONF_am_aew_mask (0x3U << 1) +#define ST25R3916_REG_AMPLITUDE_MEASURE_CONF_am_aew_shift (1U) +#define ST25R3916_REG_AMPLITUDE_MEASURE_CONF_am_ae (1U << 0) + +#define ST25R3916_REG_PHASE_MEASURE_CONF_pm_d3 (1U << 7) +#define ST25R3916_REG_PHASE_MEASURE_CONF_pm_d2 (1U << 6) +#define ST25R3916_REG_PHASE_MEASURE_CONF_pm_d1 (1U << 5) +#define ST25R3916_REG_PHASE_MEASURE_CONF_pm_d0 (1U << 4) +#define ST25R3916_REG_PHASE_MEASURE_CONF_pm_d_mask (0xfU << 4) +#define ST25R3916_REG_PHASE_MEASURE_CONF_pm_d_shift (4U) +#define ST25R3916_REG_PHASE_MEASURE_CONF_pm_aam (1U << 3) +#define ST25R3916_REG_PHASE_MEASURE_CONF_pm_aew1 (1U << 2) +#define ST25R3916_REG_PHASE_MEASURE_CONF_pm_aew0 (1U << 1) +#define ST25R3916_REG_PHASE_MEASURE_CONF_pm_aew_mask (0x3U << 1) +#define ST25R3916_REG_PHASE_MEASURE_CONF_pm_aew_shift (1U) +#define ST25R3916_REG_PHASE_MEASURE_CONF_pm_ae (1U << 0) + +#define ST25R3916_REG_CAPACITANCE_MEASURE_CONF_cm_d3 (1U << 7) +#define ST25R3916_REG_CAPACITANCE_MEASURE_CONF_cm_d2 (1U << 6) +#define ST25R3916_REG_CAPACITANCE_MEASURE_CONF_cm_d1 (1U << 5) +#define ST25R3916_REG_CAPACITANCE_MEASURE_CONF_cm_d0 (1U << 4) +#define ST25R3916_REG_CAPACITANCE_MEASURE_CONF_cm_d_mask (0xfU << 4) +#define ST25R3916_REG_CAPACITANCE_MEASURE_CONF_cm_d_shift (4U) +#define ST25R3916_REG_CAPACITANCE_MEASURE_CONF_cm_aam (1U << 3) +#define ST25R3916_REG_CAPACITANCE_MEASURE_CONF_cm_aew1 (1U << 2) +#define ST25R3916_REG_CAPACITANCE_MEASURE_CONF_cm_aew0 (1U << 1) +#define ST25R3916_REG_CAPACITANCE_MEASURE_CONF_cm_aew_mask (0x3U << 1) +#define ST25R3916_REG_CAPACITANCE_MEASURE_CONF_cm_aew_shift (1U) +#define ST25R3916_REG_CAPACITANCE_MEASURE_CONF_cm_ae (1U << 0) + +#define ST25R3916_REG_IC_IDENTITY_ic_type4 (1U << 7) +#define ST25R3916_REG_IC_IDENTITY_ic_type3 (1U << 6) +#define ST25R3916_REG_IC_IDENTITY_ic_type2 (1U << 5) +#define ST25R3916_REG_IC_IDENTITY_ic_type1 (1U << 4) +#define ST25R3916_REG_IC_IDENTITY_ic_type0 (1U << 3) +#define ST25R3916_REG_IC_IDENTITY_ic_type_st25r3916 (5U << 3) +#define ST25R3916_REG_IC_IDENTITY_ic_type_mask (0x1fU << 3) +#define ST25R3916_REG_IC_IDENTITY_ic_type_shift (3U) +#define ST25R3916_REG_IC_IDENTITY_ic_rev2 (1U << 2) +#define ST25R3916_REG_IC_IDENTITY_ic_rev1 (1U << 1) +#define ST25R3916_REG_IC_IDENTITY_ic_rev0 (1U << 0) +#define ST25R3916_REG_IC_IDENTITY_ic_rev_v0 (0U << 0) +#define ST25R3916_REG_IC_IDENTITY_ic_rev_mask (7U << 0) +#define ST25R3916_REG_IC_IDENTITY_ic_rev_shift (0U) + +/*! \endcond DOXYGEN_SUPRESS */ + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +/*! + ***************************************************************************** + * \brief Returns the content of a register within the ST25R3916 + * + * This function is used to read out the content of ST25R3916 registers. + * + * \param[in] reg: Address of register to read. + * \param[out] val: Returned value. + * + * \return ERR_NONE : Operation successful + * \return ERR_PARAM : Invalid parameter + * \return ERR_SEND : Transmission error or acknowledge not received + ***************************************************************************** + */ +ReturnCode st25r3916ReadRegister(uint8_t reg, uint8_t* val); + +/*! + ***************************************************************************** + * \brief Reads from multiple ST25R3916 registers + * + * This function is used to read from multiple registers using the + * auto-increment feature. That is, after each read the address pointer + * inside the ST25R3916 gets incremented automatically. + * + * \param[in] reg: Address of the first register to read from. + * \param[in] values: pointer to a buffer where the result shall be written to. + * \param[in] length: Number of registers to be read out. + * + * \return ERR_NONE : Operation successful + * \return ERR_PARAM : Invalid parameter + * \return ERR_SEND : Transmission error or acknowledge not received + ***************************************************************************** + */ +ReturnCode st25r3916ReadMultipleRegisters(uint8_t reg, uint8_t* values, uint8_t length); + +/*! + ***************************************************************************** + * \brief Writes a given value to a register within the ST25R3916 + * + * This function is used to write \a val to address \a reg within the ST25R3916. + * + * \param[in] reg: Address of the register to write. + * \param[in] val: Value to be written. + * + * \return ERR_NONE : Operation successful + * \return ERR_PARAM : Invalid parameter + * \return ERR_SEND : Transmission error or acknowledge not received + ***************************************************************************** + */ +ReturnCode st25r3916WriteRegister(uint8_t reg, uint8_t val); + +/*! + ***************************************************************************** + * \brief Writes multiple values to ST25R3916 registers + * + * This function is used to write multiple values to the ST25R3916 using the + * auto-increment feature. That is, after each write the address pointer + * inside the ST25R3916 gets incremented automatically. + * + * \param[in] reg: Address of the first register to write. + * \param[in] values: pointer to a buffer containing the values to be written. + * \param[in] length: Number of values to be written. + * + * \return ERR_NONE : Operation successful + * \return ERR_PARAM : Invalid parameter + * \return ERR_SEND : Transmission error or acknowledge not received + ***************************************************************************** + */ +ReturnCode st25r3916WriteMultipleRegisters(uint8_t reg, const uint8_t* values, uint8_t length); + +/*! + ***************************************************************************** + * \brief Writes values to ST25R3916 FIFO + * + * This function needs to be called in order to write to the ST25R3916 FIFO. + * + * \param[in] values: pointer to a buffer containing the values to be written + * to the FIFO. + * \param[in] length: Number of values to be written. + * + * \return ERR_NONE : Operation successful + * \return ERR_PARAM : Invalid parameter + * \return ERR_SEND : Transmission error or acknowledge not received + ***************************************************************************** + */ +ReturnCode st25r3916WriteFifo(const uint8_t* values, uint16_t length); + +/*! + ***************************************************************************** + * \brief Read values from ST25R3916 FIFO + * + * This function needs to be called in order to read from ST25R3916 FIFO. + * + * \param[out] buf: pointer to a buffer where the FIFO content shall be + * written to. + * \param[in] length: Number of bytes to read. + * + * \note: This function doesn't check whether \a length is really the + * number of available bytes in FIFO + * + * \return ERR_NONE : Operation successful + * \return ERR_PARAM : Invalid parameter + * \return ERR_SEND : Transmission error or acknowledge not received + ***************************************************************************** + */ +ReturnCode st25r3916ReadFifo(uint8_t* buf, uint16_t length); + +/*! + ***************************************************************************** + * \brief Writes values to ST25R3916 PTM + * + * Accesses to the begging of ST25R3916 Passive Target Memory (PTM A Config) + * and writes the given values + * + * \param[in] values: pointer to a buffer containing the values to be written + * to the Passive Target Memory. + * \param[in] length: Number of values to be written. + * + * \return ERR_NONE : Operation successful + * \return ERR_PARAM : Invalid parameter + * \return ERR_SEND : Transmission error or acknowledge not received + ***************************************************************************** + */ +ReturnCode st25r3916WritePTMem(const uint8_t* values, uint16_t length); + +/*! + ***************************************************************************** + * \brief Reads the ST25R3916 PTM + * + * Accesses to the begging of ST25R3916 Passive Target Memory (PTM A Config) + * and reads the memory for the given length + * + * \param[out] values: pointer to a buffer where the PTM content shall be + * written to. + * \param[in] length: Number of bytes to read. + * + * \return ERR_NONE : Operation successful + * \return ERR_PARAM : Invalid parameter + * \return ERR_SEND : Transmission error or acknowledge not received + ***************************************************************************** + */ +ReturnCode st25r3916ReadPTMem(uint8_t* values, uint16_t length); + +/*! + ***************************************************************************** + * \brief Writes values to ST25R3916 PTM F config + * + * Accesses ST25R3916 Passive Target Memory F config and writes the given values + * + * \param[in] values: pointer to a buffer containing the values to be written + * to the Passive Target Memory + * \param[in] length: Number of values to be written. + * + * \return ERR_NONE : Operation successful + * \return ERR_PARAM : Invalid parameter + * \return ERR_SEND : Transmission error or acknowledge not received + ***************************************************************************** + */ +ReturnCode st25r3916WritePTMemF(const uint8_t* values, uint16_t length); + +/*! + ***************************************************************************** + * \brief Writes values to ST25R3916 PTM TSN Data + * + * Accesses ST25R3916 Passive Target Memory TSN data and writes the given values + * + * \param[in] values: pointer to a buffer containing the values to be written + * to the Passive Target Memory. + * \param[in] length: Number of values to be written. + * + * \return ERR_NONE : Operation successful + * \return ERR_PARAM : Invalid parameter + * \return ERR_SEND : Transmission error or acknowledge not received + ***************************************************************************** + */ +ReturnCode st25r3916WritePTMemTSN(const uint8_t* values, uint16_t length); + +/*! + ***************************************************************************** + * \brief Execute a direct command + * + * This function is used to start so-called direct command. These commands + * are implemented inside the chip and each command has unique code (see + * datasheet). + * + * \param[in] cmd : code of the direct command to be executed. + * + * \return ERR_NONE : Operation successful + * \return ERR_PARAM : Invalid parameter + * \return ERR_SEND : Transmission error or acknowledge not received + ***************************************************************************** + */ +ReturnCode st25r3916ExecuteCommand(uint8_t cmd); + +/*! + ***************************************************************************** + * \brief Read a test register within the ST25R3916 + * + * This function is used to read the content of test address \a reg within the ST25R3916 + * + * \param[in] reg: Address of the register to read + * \param[out] val: Returned read value + * + * \return ERR_NONE : Operation successful + * \return ERR_PARAM : Invalid parameter + * \return ERR_SEND : Transmission error or acknowledge not received + ***************************************************************************** + */ +ReturnCode st25r3916ReadTestRegister(uint8_t reg, uint8_t* val); + +/*! + ***************************************************************************** + * \brief Writes a given value to a test register within the ST25R3916 + * + * This function is used to write \a val to test address \a reg within the ST25R3916 + * + * \param[in] reg: Address of the register to write + * \param[in] val: Value to be written + * + * \return ERR_NONE : Operation successful + * \return ERR_PARAM : Invalid parameter + * \return ERR_SEND : Transmission error or acknowledge not received + ***************************************************************************** + */ +ReturnCode st25r3916WriteTestRegister(uint8_t reg, uint8_t val); + +/*! + ***************************************************************************** + * \brief Cleart bits on Register + * + * This function clears the given bitmask on the register + * + * \param[in] reg: Address of the register clear + * \param[in] clr_mask: Bitmask of bit to be cleared + * + * \return ERR_NONE : Operation successful + * \return ERR_PARAM : Invalid parameter + * \return ERR_SEND : Transmission error or acknowledge not received + ***************************************************************************** + */ +ReturnCode st25r3916ClrRegisterBits(uint8_t reg, uint8_t clr_mask); + +/*! + ***************************************************************************** + * \brief Set bits on Register + * + * This function sets the given bitmask on the register + * + * \param[in] reg: Address of the register clear + * \param[in] set_mask: Bitmask of bit to be cleared + * + * \return ERR_NONE : Operation successful + * \return ERR_PARAM : Invalid parameter + * \return ERR_SEND : Transmission error or acknowledge not received + ***************************************************************************** + */ +ReturnCode st25r3916SetRegisterBits(uint8_t reg, uint8_t set_mask); + +/*! + ***************************************************************************** + * \brief Changes the given bits on a ST25R3916 register + * + * This function is used if only a particular bits should be changed within + * an ST25R3916 register. + * + * \param[in] reg: Address of the register to change. + * \param[in] valueMask: bitmask of bits to be changed + * \param[in] value: the bits to be written on the enabled valueMask bits + * + * \return ERR_NONE : Operation successful + * \return ERR_PARAM : Invalid parameter + * \return ERR_SEND : Transmission error or acknowledge not received + ***************************************************************************** + */ +ReturnCode st25r3916ChangeRegisterBits(uint8_t reg, uint8_t valueMask, uint8_t value); + +/*! + ***************************************************************************** + * \brief Modifies a value within a ST25R3916 register + * + * This function is used if only a particular bits should be changed within + * an ST25R3916 register. + * + * \param[in] reg: Address of the register to write. + * \param[in] clr_mask: bitmask of bits to be cleared to 0. + * \param[in] set_mask: bitmask of bits to be set to 1. + * + * \return ERR_NONE : Operation successful + * \return ERR_PARAM : Invalid parameter + * \return ERR_SEND : Transmission error or acknowledge not received + ***************************************************************************** + */ +ReturnCode st25r3916ModifyRegister(uint8_t reg, uint8_t clr_mask, uint8_t set_mask); + +/*! + ***************************************************************************** + * \brief Changes the given bits on a ST25R3916 Test register + * + * This function is used if only a particular bits should be changed within + * an ST25R3916 register. + * + * \param[in] reg: Address of the Test register to change. + * \param[in] valueMask: bitmask of bits to be changed + * \param[in] value: the bits to be written on the enabled valueMask bits + * + * \return ERR_NONE : Operation successful + * \return ERR_PARAM : Invalid parameter + * \return ERR_SEND : Transmission error or acknowledge not received + ***************************************************************************** + */ +ReturnCode st25r3916ChangeTestRegisterBits(uint8_t reg, uint8_t valueMask, uint8_t value); + +/*! + ***************************************************************************** + * \brief Checks if register contains a expected value + * + * This function checks if the given reg contains a value that once masked + * equals the expected value + * + * \param reg : the register to check the value + * \param mask : the mask apply on register value + * \param val : expected value to be compared to + * + * \return true when reg contains the expected value | false otherwise + */ +bool st25r3916CheckReg(uint8_t reg, uint8_t mask, uint8_t val); + +/*! + ***************************************************************************** + * \brief Check if register ID is valid + * + * Checks if the given register ID a valid ST25R3916 register + * + * \param[in] reg: Address of register to check + * + * \return true if is a valid register ID + * \return false otherwise + * + ***************************************************************************** + */ +bool st25r3916IsRegValid(uint8_t reg); + +#endif /* ST25R3916_COM_H */ + +/** + * @} + * + * @} + * + * @} + * + * @} + */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/st25r3916_irq.c b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/st25r3916_irq.c new file mode 100644 index 00000000000..13e186e9f53 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/st25r3916_irq.c @@ -0,0 +1,231 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R3916 firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file + * + * \author Gustavo Patricio + * + * \brief ST25R3916 Interrupt handling + * + */ + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ + +#include "st25r3916_irq.h" +#include "st25r3916_com.h" +#include "st25r3916_led.h" +#include "st25r3916.h" +#include "../../utils.h" + +/* + ****************************************************************************** + * LOCAL DATA TYPES + ****************************************************************************** + */ + +/*! Holds current and previous interrupt callback pointer as well as current Interrupt status and mask */ +typedef struct { + void (*prevCallback)(void); /*!< call back function for ST25R3916 interrupt */ + void (*callback)(void); /*!< call back function for ST25R3916 interrupt */ + uint32_t status; /*!< latest interrupt status */ + uint32_t mask; /*!< Interrupt mask. Negative mask = ST25R3916 mask regs */ +} st25r3916Interrupt; + +/* +****************************************************************************** +* GLOBAL DEFINES +****************************************************************************** +*/ + +/*! Length of the interrupt registers */ +#define ST25R3916_INT_REGS_LEN ((ST25R3916_REG_IRQ_TARGET - ST25R3916_REG_IRQ_MAIN) + 1U) + +/* +****************************************************************************** +* GLOBAL VARIABLES +****************************************************************************** +*/ + +static volatile st25r3916Interrupt st25r3916interrupt; /*!< Instance of ST25R3916 interrupt */ + +/* +****************************************************************************** +* GLOBAL FUNCTIONS +****************************************************************************** +*/ +void st25r3916InitInterrupts(void) { + platformIrqST25RPinInitialize(); + platformIrqST25RSetCallback(st25r3916Isr); + + st25r3916interrupt.callback = NULL; + st25r3916interrupt.prevCallback = NULL; + st25r3916interrupt.status = ST25R3916_IRQ_MASK_NONE; + st25r3916interrupt.mask = ST25R3916_IRQ_MASK_NONE; +} + +/*******************************************************************************/ +void st25r3916Isr(void) { + st25r3916CheckForReceivedInterrupts(); + + // Check if callback is set and run it + if(NULL != st25r3916interrupt.callback) { + st25r3916interrupt.callback(); + } +} + +/*******************************************************************************/ +void st25r3916CheckForReceivedInterrupts(void) { + uint8_t iregs[ST25R3916_INT_REGS_LEN]; + uint32_t irqStatus; + + /* Initialize iregs */ + irqStatus = ST25R3916_IRQ_MASK_NONE; + ST_MEMSET(iregs, (int32_t)(ST25R3916_IRQ_MASK_ALL & 0xFFU), ST25R3916_INT_REGS_LEN); + + /* In case the IRQ is Edge (not Level) triggered read IRQs until done */ + while(platformGpioIsHigh(ST25R_INT_PORT, ST25R_INT_PIN)) { + st25r3916ReadMultipleRegisters(ST25R3916_REG_IRQ_MAIN, iregs, ST25R3916_INT_REGS_LEN); + + irqStatus |= (uint32_t)iregs[0]; + irqStatus |= (uint32_t)iregs[1] << 8; + irqStatus |= (uint32_t)iregs[2] << 16; + irqStatus |= (uint32_t)iregs[3] << 24; + } + + /* Forward all interrupts, even masked ones to application */ + platformProtectST25RIrqStatus(); + st25r3916interrupt.status |= irqStatus; + platformUnprotectST25RIrqStatus(); + + /* Send an IRQ event to LED handling */ + st25r3916ledEvtIrq(st25r3916interrupt.status); +} + +/*******************************************************************************/ +void st25r3916ModifyInterrupts(uint32_t clr_mask, uint32_t set_mask) { + uint8_t i; + uint32_t old_mask; + uint32_t new_mask; + + old_mask = st25r3916interrupt.mask; + new_mask = ((~old_mask & set_mask) | (old_mask & clr_mask)); + st25r3916interrupt.mask &= ~clr_mask; + st25r3916interrupt.mask |= set_mask; + + for(i = 0; i < ST25R3916_INT_REGS_LEN; i++) { + if(((new_mask >> (8U * i)) & 0xFFU) == 0U) { + continue; + } + + st25r3916WriteRegister( + ST25R3916_REG_IRQ_MASK_MAIN + i, + (uint8_t)((st25r3916interrupt.mask >> (8U * i)) & 0xFFU)); + } + return; +} + +/*******************************************************************************/ +uint32_t st25r3916WaitForInterruptsTimed(uint32_t mask, uint16_t tmo) { + uint32_t tmrDelay; + uint32_t status; + + tmrDelay = platformTimerCreate(tmo); + + /* Run until specific interrupt has happen or the timer has expired */ + do { + status = (st25r3916interrupt.status & mask); + } while((!platformTimerIsExpired(tmrDelay) || (tmo == 0U)) && (status == 0U)); + + platformTimerDestroy(tmrDelay); + + status = st25r3916interrupt.status & mask; + + platformProtectST25RIrqStatus(); + st25r3916interrupt.status &= ~status; + platformUnprotectST25RIrqStatus(); + + return status; +} + +/*******************************************************************************/ +uint32_t st25r3916GetInterrupt(uint32_t mask) { + uint32_t irqs; + + irqs = (st25r3916interrupt.status & mask); + if(irqs != ST25R3916_IRQ_MASK_NONE) { + platformProtectST25RIrqStatus(); + st25r3916interrupt.status &= ~irqs; + platformUnprotectST25RIrqStatus(); + } + + return irqs; +} + +/*******************************************************************************/ +void st25r3916ClearAndEnableInterrupts(uint32_t mask) { + st25r3916GetInterrupt(mask); + st25r3916EnableInterrupts(mask); +} + +/*******************************************************************************/ +void st25r3916EnableInterrupts(uint32_t mask) { + st25r3916ModifyInterrupts(mask, 0); +} + +/*******************************************************************************/ +void st25r3916DisableInterrupts(uint32_t mask) { + st25r3916ModifyInterrupts(0, mask); +} + +/*******************************************************************************/ +void st25r3916ClearInterrupts(void) { + uint8_t iregs[ST25R3916_INT_REGS_LEN]; + + st25r3916ReadMultipleRegisters(ST25R3916_REG_IRQ_MAIN, iregs, ST25R3916_INT_REGS_LEN); + + platformProtectST25RIrqStatus(); + st25r3916interrupt.status = ST25R3916_IRQ_MASK_NONE; + platformUnprotectST25RIrqStatus(); + return; +} + +/*******************************************************************************/ +void st25r3916IRQCallbackSet(void (*cb)(void)) { + st25r3916interrupt.prevCallback = st25r3916interrupt.callback; + st25r3916interrupt.callback = cb; +} + +/*******************************************************************************/ +void st25r3916IRQCallbackRestore(void) { + st25r3916interrupt.callback = st25r3916interrupt.prevCallback; + st25r3916interrupt.prevCallback = NULL; +} diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/st25r3916_irq.h b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/st25r3916_irq.h new file mode 100644 index 00000000000..49ea8dd5ee9 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/st25r3916_irq.h @@ -0,0 +1,296 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R3916 firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file + * + * \author Gustavo Patricio + * + * \brief ST25R3916 Interrupt handling + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-HAL + * \brief RFAL Hardware Abstraction Layer + * @{ + * + * \addtogroup ST25R3916 + * \brief RFAL ST25R3916 Driver + * @{ + * + * \addtogroup ST25R3916_IRQ + * \brief RFAL ST25R3916 IRQ + * @{ + * + */ + +#ifndef ST25R3916_IRQ_H +#define ST25R3916_IRQ_H + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ + +#include "../../platform.h" + +/* +****************************************************************************** +* GLOBAL DEFINES +****************************************************************************** +*/ + +#define ST25R3916_IRQ_MASK_ALL \ + (uint32_t)(0xFFFFFFFFUL) /*!< All ST25R3916 interrupt sources */ +#define ST25R3916_IRQ_MASK_NONE \ + (uint32_t)(0x00000000UL) /*!< No ST25R3916 interrupt source */ + +/* Main interrupt register */ +#define ST25R3916_IRQ_MASK_OSC \ + (uint32_t)(0x00000080U) /*!< ST25R3916 oscillator stable interrupt */ +#define ST25R3916_IRQ_MASK_FWL \ + (uint32_t)(0x00000040U) /*!< ST25R3916 FIFO water level interrupt */ +#define ST25R3916_IRQ_MASK_RXS \ + (uint32_t)(0x00000020U) /*!< ST25R3916 start of receive interrupt */ +#define ST25R3916_IRQ_MASK_RXE \ + (uint32_t)(0x00000010U) /*!< ST25R3916 end of receive interrupt */ +#define ST25R3916_IRQ_MASK_TXE \ + (uint32_t)(0x00000008U) /*!< ST25R3916 end of transmission interrupt */ +#define ST25R3916_IRQ_MASK_COL \ + (uint32_t)(0x00000004U) /*!< ST25R3916 bit collision interrupt */ +#define ST25R3916_IRQ_MASK_RX_REST \ + (uint32_t)(0x00000002U) /*!< ST25R3916 automatic reception restart interrupt */ +#define ST25R3916_IRQ_MASK_RFU \ + (uint32_t)(0x00000001U) /*!< ST25R3916 RFU interrupt */ + +/* Timer and NFC interrupt register */ +#define ST25R3916_IRQ_MASK_DCT \ + (uint32_t)(0x00008000U) /*!< ST25R3916 termination of direct command interrupt. */ +#define ST25R3916_IRQ_MASK_NRE \ + (uint32_t)(0x00004000U) /*!< ST25R3916 no-response timer expired interrupt */ +#define ST25R3916_IRQ_MASK_GPE \ + (uint32_t)(0x00002000U) /*!< ST25R3916 general purpose timer expired interrupt */ +#define ST25R3916_IRQ_MASK_EON \ + (uint32_t)(0x00001000U) /*!< ST25R3916 external field on interrupt */ +#define ST25R3916_IRQ_MASK_EOF \ + (uint32_t)(0x00000800U) /*!< ST25R3916 external field off interrupt */ +#define ST25R3916_IRQ_MASK_CAC \ + (uint32_t)(0x00000400U) /*!< ST25R3916 collision during RF collision avoidance interrupt */ +#define ST25R3916_IRQ_MASK_CAT \ + (uint32_t)(0x00000200U) /*!< ST25R3916 minimum guard time expired interrupt */ +#define ST25R3916_IRQ_MASK_NFCT \ + (uint32_t)(0x00000100U) /*!< ST25R3916 initiator bit rate recognised interrupt */ + +/* Error and wake-up interrupt register */ +#define ST25R3916_IRQ_MASK_CRC \ + (uint32_t)(0x00800000U) /*!< ST25R3916 CRC error interrupt */ +#define ST25R3916_IRQ_MASK_PAR \ + (uint32_t)(0x00400000U) /*!< ST25R3916 parity error interrupt */ +#define ST25R3916_IRQ_MASK_ERR2 \ + (uint32_t)(0x00200000U) /*!< ST25R3916 soft framing error interrupt */ +#define ST25R3916_IRQ_MASK_ERR1 \ + (uint32_t)(0x00100000U) /*!< ST25R3916 hard framing error interrupt */ +#define ST25R3916_IRQ_MASK_WT \ + (uint32_t)(0x00080000U) /*!< ST25R3916 wake-up interrupt */ +#define ST25R3916_IRQ_MASK_WAM \ + (uint32_t)(0x00040000U) /*!< ST25R3916 wake-up due to amplitude interrupt */ +#define ST25R3916_IRQ_MASK_WPH \ + (uint32_t)(0x00020000U) /*!< ST25R3916 wake-up due to phase interrupt */ +#define ST25R3916_IRQ_MASK_WCAP \ + (uint32_t)(0x00010000U) /*!< ST25R3916 wake-up due to capacitance measurement */ + +/* Passive Target Interrupt Register */ +#define ST25R3916_IRQ_MASK_PPON2 \ + (uint32_t)(0x80000000U) /*!< ST25R3916 PPON2 Field on waiting Timer interrupt */ +#define ST25R3916_IRQ_MASK_SL_WL \ + (uint32_t)(0x40000000U) /*!< ST25R3916 Passive target slot number water level interrupt */ +#define ST25R3916_IRQ_MASK_APON \ + (uint32_t)(0x20000000U) /*!< ST25R3916 Anticollision done and Field On interrupt */ +#define ST25R3916_IRQ_MASK_RXE_PTA \ + (uint32_t)(0x10000000U) /*!< ST25R3916 RXE with an automatic response interrupt */ +#define ST25R3916_IRQ_MASK_WU_F \ + (uint32_t)(0x08000000U) /*!< ST25R3916 212/424b/s Passive target interrupt: Active */ +#define ST25R3916_IRQ_MASK_RFU2 \ + (uint32_t)(0x04000000U) /*!< ST25R3916 RFU2 interrupt */ +#define ST25R3916_IRQ_MASK_WU_A_X \ + (uint32_t)(0x02000000U) /*!< ST25R3916 106kb/s Passive target state interrupt: Active* */ +#define ST25R3916_IRQ_MASK_WU_A \ + (uint32_t)(0x01000000U) /*!< ST25R3916 106kb/s Passive target state interrupt: Active */ + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +/*! + ***************************************************************************** + * \brief Wait until an ST25R3916 interrupt occurs + * + * This function is used to access the ST25R3916 interrupt flags. Use this + * to wait for max. \a tmo milliseconds for the \b first interrupt indicated + * with mask \a mask to occur. + * + * \param[in] mask : mask indicating the interrupts to wait for. + * \param[in] tmo : time in milliseconds until timeout occurs. If set to 0 + * the functions waits forever. + * + * \return : 0 if timeout occurred otherwise a mask indicating the cleared + * interrupts. + * + ***************************************************************************** + */ +uint32_t st25r3916WaitForInterruptsTimed(uint32_t mask, uint16_t tmo); + +/*! + ***************************************************************************** + * \brief Get status for the given interrupt + * + * This function is used to check whether the interrupt given by \a mask + * has occurred. If yes the interrupt gets cleared. This function returns + * only status bits which are inside \a mask. + * + * \param[in] mask : mask indicating the interrupt to check for. + * + * \return the mask of the interrupts occurred + * + ***************************************************************************** + */ +uint32_t st25r3916GetInterrupt(uint32_t mask); + +/*! + ***************************************************************************** + * \brief Init the 3916 interrupt + * + * This function is used to check whether the interrupt given by \a mask + * has occurred. + * + ***************************************************************************** + */ +void st25r3916InitInterrupts(void); + +/*! + ***************************************************************************** + * \brief Modifies the Interrupt + * + * This function modifies the interrupt + * + * \param[in] clr_mask : bit mask to be cleared on the interrupt mask + * \param[in] set_mask : bit mask to be set on the interrupt mask + ***************************************************************************** + */ +void st25r3916ModifyInterrupts(uint32_t clr_mask, uint32_t set_mask); + +/*! + ***************************************************************************** + * \brief Checks received interrupts + * + * Checks received interrupts and saves the result into global params + ***************************************************************************** + */ +void st25r3916CheckForReceivedInterrupts(void); + +/*! + ***************************************************************************** + * \brief ISR Service routine + * + * This function modiefies the interrupt + ***************************************************************************** + */ +void st25r3916Isr(void); + +/*! + ***************************************************************************** + * \brief Enable a given ST25R3916 Interrupt source + * + * This function enables all interrupts given by \a mask, + * ST25R3916_IRQ_MASK_ALL enables all interrupts. + * + * \param[in] mask: mask indicating the interrupts to be enabled + * + ***************************************************************************** + */ +void st25r3916EnableInterrupts(uint32_t mask); + +/*! + ***************************************************************************** + * \brief Disable one or more a given ST25R3916 Interrupt sources + * + * This function disables all interrupts given by \a mask. 0xff disables all. + * + * \param[in] mask: mask indicating the interrupts to be disabled. + * + ***************************************************************************** + */ +void st25r3916DisableInterrupts(uint32_t mask); + +/*! + ***************************************************************************** + * \brief Clear all ST25R3916 irq flags + * + ***************************************************************************** + */ +void st25r3916ClearInterrupts(void); + +/*! + ***************************************************************************** + * \brief Clears and then enables the given ST25R3916 Interrupt sources + * + * \param[in] mask: mask indicating the interrupts to be cleared and enabled + ***************************************************************************** + */ +void st25r3916ClearAndEnableInterrupts(uint32_t mask); + +/*! + ***************************************************************************** + * \brief Sets IRQ callback for the ST25R3916 interrupt + * + ***************************************************************************** + */ +void st25r3916IRQCallbackSet(void (*cb)(void)); + +/*! + ***************************************************************************** + * \brief Sets IRQ callback for the ST25R3916 interrupt + * + ***************************************************************************** + */ +void st25r3916IRQCallbackRestore(void); + +#endif /* ST25R3916_IRQ_H */ + +/** + * @} + * + * @} + * + * @} + * + * @} + */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/st25r3916_led.c b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/st25r3916_led.c new file mode 100644 index 00000000000..9737337ca34 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/st25r3916_led.c @@ -0,0 +1,148 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R3916 firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file + * + * \author Gustavo Patricio + * + * \brief ST25R3916 LEDs handling + * + */ + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ + +#include "st25r3916_led.h" +#include "st25r3916_irq.h" +#include "st25r3916_com.h" +#include "st25r3916.h" + +/* +****************************************************************************** +* MACROS +****************************************************************************** +*/ + +#ifdef PLATFORM_LED_RX_PIN +#define st25r3916ledRxOn() \ + platformLedOn( \ + PLATFORM_LED_RX_PORT, \ + PLATFORM_LED_RX_PIN); /*!< LED Rx Pin On from system HAL */ +#define st25r3916ledRxOff() \ + platformLedOff( \ + PLATFORM_LED_RX_PORT, \ + PLATFORM_LED_RX_PIN); /*!< LED Rx Pin Off from system HAL */ +#else /* PLATFORM_LED_RX_PIN */ +#define st25r3916ledRxOn() +#define st25r3916ledRxOff() +#endif /* PLATFORM_LED_RX_PIN */ + +#ifdef PLATFORM_LED_FIELD_PIN +#define st25r3916ledFieldOn() \ + platformLedOn( \ + PLATFORM_LED_FIELD_PORT, \ + PLATFORM_LED_FIELD_PIN); /*!< LED Field Pin On from system HAL */ +#define st25r3916ledFieldOff() \ + platformLedOff( \ + PLATFORM_LED_FIELD_PORT, \ + PLATFORM_LED_FIELD_PIN); /*!< LED Field Pin Off from system HAL */ +#else /* PLATFORM_LED_FIELD_PIN */ +#define st25r3916ledFieldOn() +#define st25r3916ledFieldOff() +#endif /* PLATFORM_LED_FIELD_PIN */ + +/* +****************************************************************************** +* GLOBAL FUNCTIONS +****************************************************************************** +*/ + +void st25r3916ledInit(void) { + /* Initialize LEDs if existing and defined */ + platformLedsInitialize(); + + st25r3916ledRxOff(); + st25r3916ledFieldOff(); +} + +/*******************************************************************************/ +void st25r3916ledEvtIrq(uint32_t irqs) { + if((irqs & (ST25R3916_IRQ_MASK_TXE | ST25R3916_IRQ_MASK_CAT)) != 0U) { + st25r3916ledFieldOn(); + } + + if((irqs & (ST25R3916_IRQ_MASK_RXS | ST25R3916_IRQ_MASK_NFCT)) != 0U) { + st25r3916ledRxOn(); + } + + if((irqs & (ST25R3916_IRQ_MASK_RXE | ST25R3916_IRQ_MASK_NRE | ST25R3916_IRQ_MASK_RX_REST | + ST25R3916_IRQ_MASK_RXE_PTA | ST25R3916_IRQ_MASK_WU_A | ST25R3916_IRQ_MASK_WU_A_X | + ST25R3916_IRQ_MASK_WU_F | ST25R3916_IRQ_MASK_RFU2)) != 0U) { + st25r3916ledRxOff(); + } +} + +/*******************************************************************************/ +void st25r3916ledEvtWrReg(uint8_t reg, uint8_t val) { + if(reg == ST25R3916_REG_OP_CONTROL) { + if((ST25R3916_REG_OP_CONTROL_tx_en & val) != 0U) { + st25r3916ledFieldOn(); + } else { + st25r3916ledFieldOff(); + } + } +} + +/*******************************************************************************/ +void st25r3916ledEvtWrMultiReg(uint8_t reg, const uint8_t* vals, uint8_t len) { + uint8_t i; + + for(i = 0; i < (len); i++) { + st25r3916ledEvtWrReg((reg + i), vals[i]); + } +} + +/*******************************************************************************/ +void st25r3916ledEvtCmd(uint8_t cmd) { + if((cmd >= ST25R3916_CMD_TRANSMIT_WITH_CRC) && + (cmd <= ST25R3916_CMD_RESPONSE_RF_COLLISION_N)) { + st25r3916ledFieldOff(); + } + + if(cmd == ST25R3916_CMD_UNMASK_RECEIVE_DATA) { + st25r3916ledRxOff(); + } + + if(cmd == ST25R3916_CMD_SET_DEFAULT) { + st25r3916ledFieldOff(); + st25r3916ledRxOff(); + } +} diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/st25r3916_led.h b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/st25r3916_led.h new file mode 100644 index 00000000000..236e850ef6c --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/source/st25r3916/st25r3916_led.h @@ -0,0 +1,151 @@ + +/****************************************************************************** + * \attention + * + *

© COPYRIGHT 2020 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: ST25R3916 firmware + * Revision: + * LANGUAGE: ISO C99 + */ + +/*! \file + * + * \author Gustavo Patricio + * + * \brief ST25R3916 LEDs handling + * + * + * \addtogroup RFAL + * @{ + * + * \addtogroup RFAL-HAL + * \brief RFAL Hardware Abstraction Layer + * @{ + * + * \addtogroup ST25R3916 + * \brief RFAL ST25R3916 Driver + * @{ + * + * \addtogroup ST25R3916_LED + * \brief RFAL ST25R3916 LED + * @{ + * + */ + +#ifndef ST25R3916_LED_H +#define ST25R3916_LED_H + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ + +#include "../../platform.h" + +/* +****************************************************************************** +* GLOBAL DEFINES +****************************************************************************** +*/ + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +/*! + ***************************************************************************** + * \brief ST25R3916 LED Initialize + * + * This function initializes the LEDs that represent ST25R3916 activity + * + ***************************************************************************** + */ +void st25r3916ledInit(void); + +/*! + ***************************************************************************** + * \brief ST25R3916 LED Event Interrupt + * + * This function should be called upon a ST25R3916 Interrupt, providing + * the interrupt event with ST25R3916 irq flags to update LEDs + * + * \param[in] irqs: ST25R3916 irqs mask + * + ***************************************************************************** + */ +void st25r3916ledEvtIrq(uint32_t irqs); + +/*! + ***************************************************************************** + * \brief ST25R3916 LED Event Write Register + * + * This function should be called on a ST25R3916 Write Register operation + * providing the event with the register and value to update LEDs + * + * \param[in] reg: ST25R3916 register to be written + * \param[in] val: value to be written on the register + * + ***************************************************************************** + */ +void st25r3916ledEvtWrReg(uint8_t reg, uint8_t val); + +/*! + ***************************************************************************** + * \brief ST25R3916 LED Event Write Multiple Register + * + * This function should be called upon a ST25R3916 Write Multiple Registers, + * providing the event with the registers and values to update LEDs + * + * \param[in] reg : ST25R3916 first register written + * \param[in] vals: pointer to the values written + * \param[in] len : number of registers written + * + ***************************************************************************** + */ +void st25r3916ledEvtWrMultiReg(uint8_t reg, const uint8_t* vals, uint8_t len); + +/*! + ***************************************************************************** + * \brief ST25R3916 LED Event Direct Command + * + * This function should be called upon a ST25R3916 direct command, providing + * the event with the command executed + * + * \param[in] cmd: ST25R3916 cmd executed + * + ***************************************************************************** + */ +void st25r3916ledEvtCmd(uint8_t cmd); + +#endif /* ST25R3916_LED_H */ + +/** + * @} + * + * @} + * + * @} + * + * @} + */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/st_errno.h b/esubghz_chat/lib/nfclegacy/ST25RFAL002/st_errno.h new file mode 100644 index 00000000000..cd706b3d4c5 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/st_errno.h @@ -0,0 +1,158 @@ + +/****************************************************************************** + * @attention + * + *

© COPYRIGHT 2018 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: STxxxx firmware + * LANGUAGE: ISO C99 + */ + +/*! \file st_errno.h + * + * \author + * + * \brief Main error codes + * + */ + +#ifndef ST_ERRNO_H +#define ST_ERRNO_H + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ + +#include + +/* +****************************************************************************** +* GLOBAL DATA TYPES +****************************************************************************** +*/ + +typedef uint16_t ReturnCode; /*!< Standard Return Code type from function. */ + +/* +****************************************************************************** +* DEFINES +****************************************************************************** +*/ + +/* + * Error codes to be used within the application. + * They are represented by an uint8_t + */ +enum { + ERR_NONE = 0, /*!< no error occurred */ + ERR_NOMEM = 1, /*!< not enough memory to perform the requested operation */ + ERR_BUSY = 2, /*!< device or resource busy */ + ERR_IO = 3, /*!< generic IO error */ + ERR_TIMEOUT = 4, /*!< error due to timeout */ + ERR_REQUEST = 5, /*!< invalid request or requested function can't be executed at the moment */ + ERR_NOMSG = 6, /*!< No message of desired type */ + ERR_PARAM = 7, /*!< Parameter error */ + ERR_SYSTEM = 8, /*!< System error */ + ERR_FRAMING = 9, /*!< Framing error */ + ERR_OVERRUN = 10, /*!< lost one or more received bytes */ + ERR_PROTO = 11, /*!< protocol error */ + ERR_INTERNAL = 12, /*!< Internal Error */ + ERR_AGAIN = 13, /*!< Call again */ + ERR_MEM_CORRUPT = 14, /*!< memory corruption */ + ERR_NOT_IMPLEMENTED = 15, /*!< not implemented */ + ERR_PC_CORRUPT = + 16, /*!< Program Counter has been manipulated or spike/noise trigger illegal operation */ + ERR_SEND = 17, /*!< error sending*/ + ERR_IGNORE = 18, /*!< indicates error detected but to be ignored */ + ERR_SEMANTIC = 19, /*!< indicates error in state machine (unexpected cmd) */ + ERR_SYNTAX = 20, /*!< indicates error in state machine (unknown cmd) */ + ERR_CRC = 21, /*!< crc error */ + ERR_NOTFOUND = 22, /*!< transponder not found */ + ERR_NOTUNIQUE = 23, /*!< transponder not unique - more than one transponder in field */ + ERR_NOTSUPP = 24, /*!< requested operation not supported */ + ERR_WRITE = 25, /*!< write error */ + ERR_FIFO = 26, /*!< fifo over or underflow error */ + ERR_PAR = 27, /*!< parity error */ + ERR_DONE = 28, /*!< transfer has already finished */ + ERR_RF_COLLISION = + 29, /*!< collision error (Bit Collision or during RF Collision avoidance ) */ + ERR_HW_OVERRUN = 30, /*!< lost one or more received bytes */ + ERR_RELEASE_REQ = 31, /*!< device requested release */ + ERR_SLEEP_REQ = 32, /*!< device requested sleep */ + ERR_WRONG_STATE = 33, /*!< incorrent state for requested operation */ + ERR_MAX_RERUNS = 34, /*!< blocking procedure reached maximum runs */ + ERR_DISABLED = 35, /*!< operation aborted due to disabled configuration */ + ERR_HW_MISMATCH = 36, /*!< expected hw do not match */ + ERR_LINK_LOSS = + 37, /*!< Other device's field didn't behave as expected: turned off by Initiator in Passive mode, or AP2P did not turn on field */ + ERR_INVALID_HANDLE = 38, /*!< invalid or not initalized device handle */ + + ERR_INCOMPLETE_BYTE = 40, /*!< Incomplete byte rcvd */ + ERR_INCOMPLETE_BYTE_01 = 41, /*!< Incomplete byte rcvd - 1 bit */ + ERR_INCOMPLETE_BYTE_02 = 42, /*!< Incomplete byte rcvd - 2 bit */ + ERR_INCOMPLETE_BYTE_03 = 43, /*!< Incomplete byte rcvd - 3 bit */ + ERR_INCOMPLETE_BYTE_04 = 44, /*!< Incomplete byte rcvd - 4 bit */ + ERR_INCOMPLETE_BYTE_05 = 45, /*!< Incomplete byte rcvd - 5 bit */ + ERR_INCOMPLETE_BYTE_06 = 46, /*!< Incomplete byte rcvd - 6 bit */ + ERR_INCOMPLETE_BYTE_07 = 47, /*!< Incomplete byte rcvd - 7 bit */ +}; + +/* General Sub-category number */ +#define ERR_GENERIC_GRP (0x0000) /*!< Reserved value for generic error no */ +#define ERR_WARN_GRP (0x0100) /*!< Errors which are not expected in normal operation */ +#define ERR_PROCESS_GRP (0x0200) /*!< Processes management errors */ +#define ERR_SIO_GRP (0x0800) /*!< SIO errors due to logging */ +#define ERR_RINGBUF_GRP (0x0900) /*!< Ring Buffer errors */ +#define ERR_MQ_GRP (0x0A00) /*!< MQ errors */ +#define ERR_TIMER_GRP (0x0B00) /*!< Timer errors */ +#define ERR_RFAL_GRP (0x0C00) /*!< RFAL errors */ +#define ERR_UART_GRP (0x0D00) /*!< UART errors */ +#define ERR_SPI_GRP (0x0E00) /*!< SPI errors */ +#define ERR_I2C_GRP (0x0F00) /*!< I2c errors */ + +#define ERR_INSERT_SIO_GRP(x) (ERR_SIO_GRP | x) /*!< Insert the SIO grp */ +#define ERR_INSERT_RINGBUF_GRP(x) (ERR_RINGBUF_GRP | x) /*!< Insert the Ring Buffer grp */ +#define ERR_INSERT_RFAL_GRP(x) (ERR_RFAL_GRP | x) /*!< Insert the RFAL grp */ +#define ERR_INSERT_SPI_GRP(x) (ERR_SPI_GRP | x) /*!< Insert the spi grp */ +#define ERR_INSERT_I2C_GRP(x) (ERR_I2C_GRP | x) /*!< Insert the i2c grp */ +#define ERR_INSERT_UART_GRP(x) (ERR_UART_GRP | x) /*!< Insert the uart grp */ +#define ERR_INSERT_TIMER_GRP(x) (ERR_TIMER_GRP | x) /*!< Insert the timer grp */ +#define ERR_INSERT_MQ_GRP(x) (ERR_MQ_GRP | x) /*!< Insert the mq grp */ +#define ERR_INSERT_PROCESS_GRP(x) (ERR_PROCESS_GRP | x) /*!< Insert the process grp */ +#define ERR_INSERT_WARN_GRP(x) (ERR_WARN_GRP | x) /*!< Insert the i2c grp */ +#define ERR_INSERT_GENERIC_GRP(x) (ERR_GENERIC_GRP | x) /*!< Insert the generic grp */ + +/* +****************************************************************************** +* GLOBAL MACROS +****************************************************************************** +*/ + +#define ERR_NO_MASK(x) (x & 0x00FF) /*!< Mask the error number */ + +/*! Common code to exit a function with the error if function f return error */ +#define EXIT_ON_ERR(r, f) \ + if(ERR_NONE != (r = f)) { \ + return r; \ + } + +#endif /* ST_ERRNO_H */ diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/timer.c b/esubghz_chat/lib/nfclegacy/ST25RFAL002/timer.c new file mode 100644 index 00000000000..ea0678a600d --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/timer.c @@ -0,0 +1,105 @@ +/****************************************************************************** + * @attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ +/* + * PROJECT: ST25R391x firmware + * $Revision: $ + * LANGUAGE: ANSI C + */ + +/*! \file timer.c + * + * \brief SW Timer implementation + * + * \author Gustavo Patricio + * + * This module makes use of a System Tick in millisconds and provides + * an abstraction for SW timers + * + */ + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ +#include "timer.h" +#include + +/* +****************************************************************************** +* LOCAL DEFINES +****************************************************************************** +*/ + +/* +****************************************************************************** +* LOCAL VARIABLES +****************************************************************************** +*/ + +static uint32_t timerStopwatchTick; + +/* +****************************************************************************** +* GLOBAL FUNCTIONS +****************************************************************************** +*/ + +/*******************************************************************************/ +uint32_t timerCalculateTimer(uint16_t time) { + return (furi_get_tick() + time); +} + +/*******************************************************************************/ +bool timerIsExpired(uint32_t timer) { + uint32_t uDiff; + int32_t sDiff; + + uDiff = (timer - furi_get_tick()); /* Calculate the diff between the timers */ + sDiff = uDiff; /* Convert the diff to a signed var */ + + /* Check if the given timer has expired already */ + if(sDiff < 0) { + return true; + } + + return false; +} + +/*******************************************************************************/ +void timerDelay(uint16_t tOut) { + uint32_t t; + + /* Calculate the timer and wait blocking until is running */ + t = timerCalculateTimer(tOut); + while(timerIsRunning(t)) + ; +} + +/*******************************************************************************/ +void timerStopwatchStart(void) { + timerStopwatchTick = furi_get_tick(); +} + +/*******************************************************************************/ +uint32_t timerStopwatchMeasure(void) { + return (uint32_t)(furi_get_tick() - timerStopwatchTick); +} diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/timer.h b/esubghz_chat/lib/nfclegacy/ST25RFAL002/timer.h new file mode 100644 index 00000000000..b5f5eb329d5 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/timer.h @@ -0,0 +1,125 @@ +#pragma once +/****************************************************************************** + * @attention + * + *

© COPYRIGHT 2016 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ +/* + * PROJECT: ST25R391x firmware + * $Revision: $ + * LANGUAGE: ANSI C + */ + +/*! \file timer.h + * + * \brief SW Timer implementation header file + * + * This module makes use of a System Tick in millisconds and provides + * an abstraction for SW timers + * + */ + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ +#include +#include + +/* +****************************************************************************** +* GLOBAL MACROS +****************************************************************************** +*/ +#define timerIsRunning(t) (!timerIsExpired(t)) + +/* +****************************************************************************** +* GLOBAL DEFINES +****************************************************************************** +*/ + +/*! + ***************************************************************************** + * \brief Calculate Timer + * + * This method calculates when the timer will be expired given the amount + * time in milliseconds /a tOut. + * Once the timer has been calculated it will then be used to check when + * it expires. + * + * \see timersIsExpired + * + * \param[in] time : time/duration in Milliseconds for the timer + * + * \return u32 : The new timer calculated based on the given time + ***************************************************************************** + */ +uint32_t timerCalculateTimer(uint16_t time); + +/*! + ***************************************************************************** + * \brief Checks if a Timer is Expired + * + * This method checks if a timer has already expired. + * Based on the given timer previously calculated it checks if this timer + * has already elapsed + * + * \see timersCalculateTimer + * + * \param[in] timer : the timer to check + * + * \return true : timer has already expired + * \return false : timer is still running + ***************************************************************************** + */ +bool timerIsExpired(uint32_t timer); + +/*! + ***************************************************************************** + * \brief Performs a Delay + * + * This method performs a delay for the given amount of time in Milliseconds + * + * \param[in] time : time/duration in Milliseconds of the delay + * + ***************************************************************************** + */ +void timerDelay(uint16_t time); + +/*! + ***************************************************************************** + * \brief Stopwatch start + * + * This method initiates the stopwatch to later measure the time in ms + * + ***************************************************************************** + */ +void timerStopwatchStart(void); + +/*! + ***************************************************************************** + * \brief Stopwatch Measure + * + * This method returns the elapsed time in ms since the stopwatch was initiated + * + * \return The time in ms since the stopwatch was started + ***************************************************************************** + */ +uint32_t timerStopwatchMeasure(void); diff --git a/esubghz_chat/lib/nfclegacy/ST25RFAL002/utils.h b/esubghz_chat/lib/nfclegacy/ST25RFAL002/utils.h new file mode 100644 index 00000000000..44a141986c5 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/ST25RFAL002/utils.h @@ -0,0 +1,100 @@ + +/****************************************************************************** + * @attention + * + *

© COPYRIGHT 2018 STMicroelectronics

+ * + * Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/myliberty + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * See the License for the specific language governing permissions and + * limitations under the License. + * +******************************************************************************/ + +/* + * PROJECT: NFCC firmware + * $Revision: $ + * LANGUAGE: ISO C99 + */ + +/*! \file + * + * \author Ulrich Herrmann + * + * \brief Common and helpful macros + * + */ + +#ifndef UTILS_H +#define UTILS_H + +/* +****************************************************************************** +* INCLUDES +****************************************************************************** +*/ +#include +#include + +/* +****************************************************************************** +* GLOBAL MACROS +****************************************************************************** +*/ +/*! + * this macro evaluates an error variable \a ERR against an error code \a EC. + * in case it is not equal it jumps to the given label \a LABEL. + */ +#define EVAL_ERR_NE_GOTO(EC, ERR, LABEL) \ + if(EC != ERR) goto LABEL; + +/*! + * this macro evaluates an error variable \a ERR against an error code \a EC. + * in case it is equal it jumps to the given label \a LABEL. + */ +#define EVAL_ERR_EQ_GOTO(EC, ERR, LABEL) \ + if(EC == ERR) goto LABEL; +#define BITMASK_1 (0x01) /*!< Bit mask for lsb bit */ +#define BITMASK_2 (0x03) /*!< Bit mask for two lsb bits */ +#define BITMASK_3 (0x07) /*!< Bit mask for three lsb bits */ +#define BITMASK_4 (0x0F) /*!< Bit mask for four lsb bits */ +#define U16TOU8(a) ((a)&0x00FF) /*!< Cast 16-bit unsigned to 8-bit unsigned */ +#define GETU16(a) \ + (uint16_t)( \ + (a[0] << 8) | a[1]) /*!< Cast two Big Endian 8-bits byte array to 16-bits unsigned */ + +#define REVERSE_BYTES(pData, nDataSize) \ + unsigned char swap, *lo = pData, *hi = pData + nDataSize - 1; \ + while(lo < hi) { \ + swap = *lo; \ + *lo++ = *hi; \ + *hi-- = swap; \ + } + +#define ST_MEMMOVE memmove /*!< map memmove to string library code */ +#define ST_MEMCPY memcpy /*!< map memcpy to string library code */ +#define ST_MEMSET memset /*!< map memset to string library code */ +#define ST_BYTECMP memcmp /*!< map bytecmp to string library code */ + +#define NO_WARNING(v) ((void)(v)) /*!< Macro to suppress compiler warning */ + +#ifndef NULL +#define NULL (void*)0 /*!< represents a NULL pointer */ +#endif /* !NULL */ + +/* +****************************************************************************** +* GLOBAL FUNCTION PROTOTYPES +****************************************************************************** +*/ + +#endif /* UTILS_H */ diff --git a/esubghz_chat/lib/nfclegacy/digital_signal/digital_signal.c b/esubghz_chat/lib/nfclegacy/digital_signal/digital_signal.c new file mode 100644 index 00000000000..25adb878b78 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/digital_signal/digital_signal.c @@ -0,0 +1,666 @@ +#include "digital_signal.h" + +#include +#include +#include +#include + +#include +#include + +/* must be on bank B */ +// For debugging purposes use `--extra-define=DIGITAL_SIGNAL_DEBUG_OUTPUT_PIN=gpio_ext_pb3` fbt option + +struct ReloadBuffer { + uint32_t* buffer; /* DMA ringbuffer */ + uint32_t size; /* maximum entry count of the ring buffer */ + uint32_t write_pos; /* current buffer write index */ + uint32_t read_pos; /* current buffer read index */ + bool dma_active; +}; + +struct DigitalSequence { + uint8_t signals_size; + bool bake; + uint32_t sequence_used; + uint32_t sequence_size; + DigitalSignal** signals; + uint8_t* sequence; + const GpioPin* gpio; + uint32_t send_time; + bool send_time_active; + LL_DMA_InitTypeDef dma_config_gpio; + LL_DMA_InitTypeDef dma_config_timer; + uint32_t* gpio_buff; + struct ReloadBuffer* dma_buffer; +}; + +struct DigitalSignalInternals { + uint64_t factor; + uint32_t reload_reg_entries; + uint32_t reload_reg_remainder; + uint32_t gpio_buff[2]; + const GpioPin* gpio; + LL_DMA_InitTypeDef dma_config_gpio; + LL_DMA_InitTypeDef dma_config_timer; +}; + +#define TAG "DigitalSignal" + +#define F_TIM (64000000.0) +#define T_TIM 1562 /* 15.625 ns *100 */ +#define T_TIM_DIV2 781 /* 15.625 ns / 2 *100 */ + +/* end marker in DMA ringbuffer, will get written into timer register at the end */ +#define SEQ_TIMER_MAX 0xFFFFFFFF + +/* time to wait in loops before returning */ +#define SEQ_LOCK_WAIT_MS 10UL +#define SEQ_LOCK_WAIT_TICKS (SEQ_LOCK_WAIT_MS * 1000 * 64) + +/* maximum entry count of the sequence dma ring buffer */ +#define RINGBUFFER_SIZE 128 + +/* maximum number of DigitalSignals in a sequence */ +#define SEQUENCE_SIGNALS_SIZE 32 +/* + * if sequence size runs out from the initial value passed to digital_sequence_alloc + * the size will be increased by this amount and reallocated + */ +#define SEQUENCE_SIZE_REALLOCATE_INCREMENT 256 + +DigitalSignal* digital_signal_alloc(uint32_t max_edges_cnt) { + DigitalSignal* signal = malloc(sizeof(DigitalSignal)); + signal->start_level = true; + signal->edges_max_cnt = max_edges_cnt; + signal->edge_timings = malloc(signal->edges_max_cnt * sizeof(uint32_t)); + signal->edge_cnt = 0; + signal->reload_reg_buff = malloc(signal->edges_max_cnt * sizeof(uint32_t)); + + signal->internals = malloc(sizeof(DigitalSignalInternals)); + DigitalSignalInternals* internals = signal->internals; + + internals->factor = 1024 * 1024; + + internals->dma_config_gpio.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH; + internals->dma_config_gpio.Mode = LL_DMA_MODE_CIRCULAR; + internals->dma_config_gpio.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; + internals->dma_config_gpio.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; + internals->dma_config_gpio.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD; + internals->dma_config_gpio.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD; + internals->dma_config_gpio.NbData = 2; + internals->dma_config_gpio.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP; + internals->dma_config_gpio.Priority = LL_DMA_PRIORITY_VERYHIGH; + + internals->dma_config_timer.PeriphOrM2MSrcAddress = (uint32_t) & (TIM2->ARR); + internals->dma_config_timer.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH; + internals->dma_config_timer.Mode = LL_DMA_MODE_NORMAL; + internals->dma_config_timer.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; + internals->dma_config_timer.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; + internals->dma_config_timer.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD; + internals->dma_config_timer.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD; + internals->dma_config_timer.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP; + internals->dma_config_timer.Priority = LL_DMA_PRIORITY_HIGH; + + return signal; +} + +void digital_signal_free(DigitalSignal* signal) { + furi_assert(signal); + + free(signal->edge_timings); + free(signal->reload_reg_buff); + free(signal->internals); + free(signal); +} + +bool digital_signal_append(DigitalSignal* signal_a, DigitalSignal* signal_b) { + furi_assert(signal_a); + furi_assert(signal_b); + + if(signal_a->edges_max_cnt < signal_a->edge_cnt + signal_b->edge_cnt) { + return false; + } + /* in case there are no edges in our target signal, the signal to append makes the rules */ + if(!signal_a->edge_cnt) { + signal_a->start_level = signal_b->start_level; + } + bool end_level = signal_a->start_level; + if(signal_a->edge_cnt) { + end_level = signal_a->start_level ^ !(signal_a->edge_cnt % 2); + } + uint8_t start_copy = 0; + if(end_level == signal_b->start_level) { + if(signal_a->edge_cnt) { + signal_a->edge_timings[signal_a->edge_cnt - 1] += signal_b->edge_timings[0]; + start_copy += 1; + } else { + signal_a->edge_timings[signal_a->edge_cnt] += signal_b->edge_timings[0]; + } + } + + for(size_t i = 0; i < signal_b->edge_cnt - start_copy; i++) { + signal_a->edge_timings[signal_a->edge_cnt + i] = signal_b->edge_timings[start_copy + i]; + } + signal_a->edge_cnt += signal_b->edge_cnt - start_copy; + + return true; +} + +bool digital_signal_get_start_level(DigitalSignal* signal) { + furi_assert(signal); + + return signal->start_level; +} + +uint32_t digital_signal_get_edges_cnt(DigitalSignal* signal) { + furi_assert(signal); + + return signal->edge_cnt; +} + +void digital_signal_add(DigitalSignal* signal, uint32_t ticks) { + furi_assert(signal); + furi_assert(signal->edge_cnt < signal->edges_max_cnt); + + signal->edge_timings[signal->edge_cnt++] = ticks; +} + +void digital_signal_add_pulse(DigitalSignal* signal, uint32_t ticks, bool level) { + furi_assert(signal); + furi_assert(signal->edge_cnt < signal->edges_max_cnt); + + /* virgin signal? add it as the only level */ + if(signal->edge_cnt == 0) { + signal->start_level = level; + signal->edge_timings[signal->edge_cnt++] = ticks; + } else { + bool end_level = signal->start_level ^ !(signal->edge_cnt % 2); + + if(level != end_level) { + signal->edge_timings[signal->edge_cnt++] = ticks; + } else { + signal->edge_timings[signal->edge_cnt - 1] += ticks; + } + } +} + +uint32_t digital_signal_get_edge(DigitalSignal* signal, uint32_t edge_num) { + furi_assert(signal); + furi_assert(edge_num < signal->edge_cnt); + + return signal->edge_timings[edge_num]; +} + +void digital_signal_prepare_arr(DigitalSignal* signal) { + furi_assert(signal); + + DigitalSignalInternals* internals = signal->internals; + + /* set up signal polarities */ + if(internals->gpio) { + uint32_t bit_set = internals->gpio->pin; + uint32_t bit_reset = internals->gpio->pin << 16; + +#ifdef DIGITAL_SIGNAL_DEBUG_OUTPUT_PIN + bit_set |= DIGITAL_SIGNAL_DEBUG_OUTPUT_PIN.pin; + bit_reset |= DIGITAL_SIGNAL_DEBUG_OUTPUT_PIN.pin << 16; +#endif + + if(signal->start_level) { + internals->gpio_buff[0] = bit_set; + internals->gpio_buff[1] = bit_reset; + } else { + internals->gpio_buff[0] = bit_reset; + internals->gpio_buff[1] = bit_set; + } + } + + /* set up edge timings */ + internals->reload_reg_entries = 0; + + for(size_t pos = 0; pos < signal->edge_cnt; pos++) { + uint32_t pulse_duration = signal->edge_timings[pos] + internals->reload_reg_remainder; + if(pulse_duration < 10 || pulse_duration > 10000000) { + FURI_LOG_D( + TAG, + "[prepare] pulse_duration out of range: %lu = %lu * %llu", + pulse_duration, + signal->edge_timings[pos], + internals->factor); + pulse_duration = 100; + } + uint32_t pulse_ticks = (pulse_duration + T_TIM_DIV2) / T_TIM; + internals->reload_reg_remainder = pulse_duration - (pulse_ticks * T_TIM); + + if(pulse_ticks > 1) { + signal->reload_reg_buff[internals->reload_reg_entries++] = pulse_ticks - 1; + } + } +} + +static void digital_signal_stop_dma() { + LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_1); + LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_2); + LL_DMA_ClearFlag_TC1(DMA1); + LL_DMA_ClearFlag_TC2(DMA1); +} + +static void digital_signal_stop_timer() { + LL_TIM_DisableCounter(TIM2); + LL_TIM_DisableUpdateEvent(TIM2); + LL_TIM_DisableDMAReq_UPDATE(TIM2); + + furi_hal_bus_disable(FuriHalBusTIM2); +} + +static void digital_signal_setup_timer() { + furi_hal_bus_enable(FuriHalBusTIM2); + + LL_TIM_SetCounterMode(TIM2, LL_TIM_COUNTERMODE_UP); + LL_TIM_SetClockDivision(TIM2, LL_TIM_CLOCKDIVISION_DIV1); + LL_TIM_SetPrescaler(TIM2, 0); + LL_TIM_SetAutoReload(TIM2, SEQ_TIMER_MAX); + LL_TIM_SetCounter(TIM2, 0); +} + +static void digital_signal_start_timer() { + LL_TIM_EnableCounter(TIM2); + LL_TIM_EnableUpdateEvent(TIM2); + LL_TIM_EnableDMAReq_UPDATE(TIM2); + LL_TIM_GenerateEvent_UPDATE(TIM2); +} + +static bool digital_signal_setup_dma(DigitalSignal* signal) { + furi_assert(signal); + DigitalSignalInternals* internals = signal->internals; + + if(!signal->internals->reload_reg_entries) { + return false; + } + digital_signal_stop_dma(); + + internals->dma_config_gpio.MemoryOrM2MDstAddress = (uint32_t)internals->gpio_buff; + internals->dma_config_gpio.PeriphOrM2MSrcAddress = (uint32_t) & (internals->gpio->port->BSRR); + internals->dma_config_timer.MemoryOrM2MDstAddress = (uint32_t)signal->reload_reg_buff; + internals->dma_config_timer.NbData = signal->internals->reload_reg_entries; + + /* set up DMA channel 1 and 2 for GPIO and timer copy operations */ + LL_DMA_Init(DMA1, LL_DMA_CHANNEL_1, &internals->dma_config_gpio); + LL_DMA_Init(DMA1, LL_DMA_CHANNEL_2, &internals->dma_config_timer); + + /* enable both DMA channels */ + LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1); + LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2); + + return true; +} + +void digital_signal_send(DigitalSignal* signal, const GpioPin* gpio) { + furi_assert(signal); + + if(!signal->edge_cnt) { + return; + } + + /* Configure gpio as output */ + signal->internals->gpio = gpio; + furi_hal_gpio_init( + signal->internals->gpio, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); + + digital_signal_prepare_arr(signal); + + digital_signal_setup_dma(signal); + digital_signal_setup_timer(); + digital_signal_start_timer(); + + while(!LL_DMA_IsActiveFlag_TC2(DMA1)) { + } + + digital_signal_stop_timer(); + digital_signal_stop_dma(); +} + +static void digital_sequence_alloc_signals(DigitalSequence* sequence, uint32_t size) { + sequence->signals_size = size; + sequence->signals = malloc(sequence->signals_size * sizeof(DigitalSignal*)); +} + +static void digital_sequence_alloc_sequence(DigitalSequence* sequence, uint32_t size) { + sequence->sequence_used = 0; + sequence->sequence_size = size; + sequence->sequence = malloc(sequence->sequence_size); + sequence->send_time = 0; + sequence->send_time_active = false; +} + +DigitalSequence* digital_sequence_alloc(uint32_t size, const GpioPin* gpio) { + furi_assert(gpio); + + DigitalSequence* sequence = malloc(sizeof(DigitalSequence)); + + sequence->gpio = gpio; + sequence->bake = false; + + sequence->dma_buffer = malloc(sizeof(struct ReloadBuffer)); + sequence->dma_buffer->size = RINGBUFFER_SIZE; + sequence->dma_buffer->buffer = malloc(sequence->dma_buffer->size * sizeof(uint32_t)); + + sequence->dma_config_gpio.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH; + sequence->dma_config_gpio.Mode = LL_DMA_MODE_CIRCULAR; + sequence->dma_config_gpio.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; + sequence->dma_config_gpio.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; + sequence->dma_config_gpio.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD; + sequence->dma_config_gpio.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD; + sequence->dma_config_gpio.NbData = 2; + sequence->dma_config_gpio.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP; + sequence->dma_config_gpio.Priority = LL_DMA_PRIORITY_VERYHIGH; + + sequence->dma_config_timer.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH; + sequence->dma_config_timer.Mode = LL_DMA_MODE_CIRCULAR; + sequence->dma_config_timer.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; + sequence->dma_config_timer.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; + sequence->dma_config_timer.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD; + sequence->dma_config_timer.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD; + sequence->dma_config_timer.PeriphOrM2MSrcAddress = (uint32_t) & (TIM2->ARR); + sequence->dma_config_timer.MemoryOrM2MDstAddress = (uint32_t)sequence->dma_buffer->buffer; + sequence->dma_config_timer.NbData = sequence->dma_buffer->size; + sequence->dma_config_timer.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP; + sequence->dma_config_timer.Priority = LL_DMA_PRIORITY_HIGH; + + digital_sequence_alloc_signals(sequence, SEQUENCE_SIGNALS_SIZE); + digital_sequence_alloc_sequence(sequence, size); + + return sequence; +} + +void digital_sequence_free(DigitalSequence* sequence) { + furi_assert(sequence); + + free(sequence->signals); + free(sequence->sequence); + free(sequence->dma_buffer->buffer); + free(sequence->dma_buffer); + free(sequence); +} + +void digital_sequence_set_signal( + DigitalSequence* sequence, + uint8_t signal_index, + DigitalSignal* signal) { + furi_assert(sequence); + furi_assert(signal); + furi_assert(signal_index < sequence->signals_size); + + sequence->signals[signal_index] = signal; + signal->internals->gpio = sequence->gpio; + signal->internals->reload_reg_remainder = 0; + + digital_signal_prepare_arr(signal); +} + +void digital_sequence_set_sendtime(DigitalSequence* sequence, uint32_t send_time) { + furi_assert(sequence); + + sequence->send_time = send_time; + sequence->send_time_active = true; +} + +void digital_sequence_add(DigitalSequence* sequence, uint8_t signal_index) { + furi_assert(sequence); + furi_assert(signal_index < sequence->signals_size); + + if(sequence->sequence_used >= sequence->sequence_size) { + sequence->sequence_size += SEQUENCE_SIZE_REALLOCATE_INCREMENT; + sequence->sequence = realloc(sequence->sequence, sequence->sequence_size); //-V701 + furi_assert(sequence->sequence); + } + + sequence->sequence[sequence->sequence_used++] = signal_index; +} + +static bool digital_sequence_setup_dma(DigitalSequence* sequence) { + furi_assert(sequence); + + digital_signal_stop_dma(); + + sequence->dma_config_gpio.MemoryOrM2MDstAddress = (uint32_t)sequence->gpio_buff; + sequence->dma_config_gpio.PeriphOrM2MSrcAddress = (uint32_t) & (sequence->gpio->port->BSRR); + + /* set up DMA channel 1 and 2 for GPIO and timer copy operations */ + LL_DMA_Init(DMA1, LL_DMA_CHANNEL_1, &sequence->dma_config_gpio); + LL_DMA_Init(DMA1, LL_DMA_CHANNEL_2, &sequence->dma_config_timer); + + /* enable both DMA channels */ + LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1); + LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2); + + return true; +} + +static DigitalSignal* digital_sequence_bake(DigitalSequence* sequence) { + furi_assert(sequence); + + uint32_t edges = 0; + + for(uint32_t pos = 0; pos < sequence->sequence_used; pos++) { + uint8_t signal_index = sequence->sequence[pos]; + DigitalSignal* sig = sequence->signals[signal_index]; + + edges += sig->edge_cnt; + } + + DigitalSignal* ret = digital_signal_alloc(edges); + + for(uint32_t pos = 0; pos < sequence->sequence_used; pos++) { + uint8_t signal_index = sequence->sequence[pos]; + DigitalSignal* sig = sequence->signals[signal_index]; + + digital_signal_append(ret, sig); + } + + return ret; +} + +static void digital_sequence_finish(DigitalSequence* sequence) { + struct ReloadBuffer* dma_buffer = sequence->dma_buffer; + + if(dma_buffer->dma_active) { + uint32_t prev_timer = DWT->CYCCNT; + do { + /* we are finished, when the DMA transferred the SEQ_TIMER_MAX marker */ + if(TIM2->ARR == SEQ_TIMER_MAX) { + break; + } + if(DWT->CYCCNT - prev_timer > SEQ_LOCK_WAIT_TICKS) { + dma_buffer->read_pos = + RINGBUFFER_SIZE - LL_DMA_GetDataLength(DMA1, LL_DMA_CHANNEL_2); + FURI_LOG_D( + TAG, + "[SEQ] hung %lu ms in finish (ARR 0x%08lx, read %lu, write %lu)", + SEQ_LOCK_WAIT_MS, + TIM2->ARR, + dma_buffer->read_pos, + dma_buffer->write_pos); + break; + } + } while(1); + } + + digital_signal_stop_timer(); + digital_signal_stop_dma(); +} + +static void digital_sequence_queue_pulse(DigitalSequence* sequence, uint32_t length) { + struct ReloadBuffer* dma_buffer = sequence->dma_buffer; + + if(dma_buffer->dma_active) { + uint32_t prev_timer = DWT->CYCCNT; + do { + dma_buffer->read_pos = RINGBUFFER_SIZE - LL_DMA_GetDataLength(DMA1, LL_DMA_CHANNEL_2); + + uint32_t free = + (RINGBUFFER_SIZE + dma_buffer->read_pos - dma_buffer->write_pos) % RINGBUFFER_SIZE; + + if(free > 2) { + break; + } + + if(DWT->CYCCNT - prev_timer > SEQ_LOCK_WAIT_TICKS) { + FURI_LOG_D( + TAG, + "[SEQ] hung %lu ms in queue (ARR 0x%08lx, read %lu, write %lu)", + SEQ_LOCK_WAIT_MS, + TIM2->ARR, + dma_buffer->read_pos, + dma_buffer->write_pos); + break; + } + if(TIM2->ARR == SEQ_TIMER_MAX) { + FURI_LOG_D( + TAG, + "[SEQ] buffer underrun in queue (ARR 0x%08lx, read %lu, write %lu)", + TIM2->ARR, + dma_buffer->read_pos, + dma_buffer->write_pos); + break; + } + } while(1); + } + + dma_buffer->buffer[dma_buffer->write_pos] = length; + dma_buffer->write_pos++; + dma_buffer->write_pos %= RINGBUFFER_SIZE; + dma_buffer->buffer[dma_buffer->write_pos] = SEQ_TIMER_MAX; +} + +bool digital_sequence_send(DigitalSequence* sequence) { + furi_assert(sequence); + + struct ReloadBuffer* dma_buffer = sequence->dma_buffer; + + furi_hal_gpio_init(sequence->gpio, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); +#ifdef DIGITAL_SIGNAL_DEBUG_OUTPUT_PIN + furi_hal_gpio_init( + &DIGITAL_SIGNAL_DEBUG_OUTPUT_PIN, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); +#endif + + if(sequence->bake) { + DigitalSignal* sig = digital_sequence_bake(sequence); + + digital_signal_send(sig, sequence->gpio); + digital_signal_free(sig); + return true; + } + + if(!sequence->sequence_used) { + return false; + } + + int32_t remainder = 0; + uint32_t trade_for_next = 0; + uint32_t seq_pos_next = 1; + + dma_buffer->dma_active = false; + dma_buffer->buffer[0] = SEQ_TIMER_MAX; + dma_buffer->read_pos = 0; + dma_buffer->write_pos = 0; + + /* already prepare the current signal pointer */ + DigitalSignal* sig = sequence->signals[sequence->sequence[0]]; + DigitalSignal* sig_next = NULL; + /* re-use the GPIO buffer from the first signal */ + sequence->gpio_buff = sig->internals->gpio_buff; + + FURI_CRITICAL_ENTER(); + + while(sig) { + bool last_signal = (seq_pos_next >= sequence->sequence_used); + + if(!last_signal) { + sig_next = sequence->signals[sequence->sequence[seq_pos_next++]]; + } + + for(uint32_t pulse_pos = 0; pulse_pos < sig->internals->reload_reg_entries; pulse_pos++) { + bool last_pulse = ((pulse_pos + 1) >= sig->internals->reload_reg_entries); + uint32_t pulse_length = sig->reload_reg_buff[pulse_pos] + trade_for_next; + + trade_for_next = 0; + + /* when we are too late more than half a tick, make the first edge temporarily longer */ + if(remainder >= T_TIM_DIV2) { + remainder -= T_TIM; + pulse_length += 1; + } + + /* last pulse in current signal and have a next signal? */ + if(last_pulse && sig_next) { + /* when a signal ends with the same level as the next signal begins, let the next signal generate the whole pulse. + beware, we do not want the level after the last edge, but the last level before that edge */ + bool end_level = sig->start_level ^ ((sig->edge_cnt % 2) == 0); + + /* if they have the same level, pass the duration to the next pulse(s) */ + if(end_level == sig_next->start_level) { + trade_for_next = pulse_length; + } + } + + /* if it was decided, that the next signal's first pulse shall also handle our "length", then do not queue here */ + if(!trade_for_next) { + digital_sequence_queue_pulse(sequence, pulse_length); + + if(!dma_buffer->dma_active) { + /* start transmission when buffer was filled enough */ + bool start_send = sequence->dma_buffer->write_pos >= (RINGBUFFER_SIZE - 2); + + /* or it was the last pulse */ + if(last_pulse && last_signal) { + start_send = true; + } + + /* start transmission */ + if(start_send) { + digital_sequence_setup_dma(sequence); + digital_signal_setup_timer(); + + /* if the send time is specified, wait till the core timer passed beyond that time */ + if(sequence->send_time_active) { + sequence->send_time_active = false; + while(sequence->send_time - DWT->CYCCNT < 0x80000000) { + } + } + digital_signal_start_timer(); + dma_buffer->dma_active = true; + } + } + } + } + + remainder += sig->internals->reload_reg_remainder; + sig = sig_next; + sig_next = NULL; + } + + /* wait until last dma transaction was finished */ + FURI_CRITICAL_EXIT(); + digital_sequence_finish(sequence); + + return true; +} + +void digital_sequence_clear(DigitalSequence* sequence) { + furi_assert(sequence); + + sequence->sequence_used = 0; +} + +void digital_sequence_timebase_correction(DigitalSequence* sequence, float factor) { + for(uint32_t sig_pos = 0; sig_pos < sequence->signals_size; sig_pos++) { + DigitalSignal* signal = sequence->signals[sig_pos]; + + if(signal) { + signal->internals->factor = (uint32_t)(1024 * 1024 * factor); + digital_signal_prepare_arr(signal); + } + } +} diff --git a/esubghz_chat/lib/nfclegacy/digital_signal/digital_signal.h b/esubghz_chat/lib/nfclegacy/digital_signal/digital_signal.h new file mode 100644 index 00000000000..404d02605e7 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/digital_signal/digital_signal.h @@ -0,0 +1,75 @@ +#pragma once + +#include +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* helper for easier signal generation */ +#define DIGITAL_SIGNAL_MS(x) ((x)*100000000UL) +#define DIGITAL_SIGNAL_US(x) ((x)*100000UL) +#define DIGITAL_SIGNAL_NS(x) ((x)*100UL) +#define DIGITAL_SIGNAL_PS(x) ((x) / 10UL) + +/* using an anonymous type for the internals */ +typedef struct DigitalSignalInternals DigitalSignalInternals; + +/* and a public one for accessing user-side fields */ +typedef struct DigitalSignal { + bool start_level; + uint32_t edge_cnt; + uint32_t edges_max_cnt; + uint32_t* edge_timings; + uint32_t* reload_reg_buff; /* internal, but used by unit tests */ + DigitalSignalInternals* internals; +} DigitalSignal; + +typedef struct DigitalSequence DigitalSequence; + +DigitalSignal* digital_signal_alloc(uint32_t max_edges_cnt); + +void digital_signal_free(DigitalSignal* signal); + +void digital_signal_add(DigitalSignal* signal, uint32_t ticks); + +void digital_signal_add_pulse(DigitalSignal* signal, uint32_t ticks, bool level); + +bool digital_signal_append(DigitalSignal* signal_a, DigitalSignal* signal_b); + +void digital_signal_prepare_arr(DigitalSignal* signal); + +bool digital_signal_get_start_level(DigitalSignal* signal); + +uint32_t digital_signal_get_edges_cnt(DigitalSignal* signal); + +uint32_t digital_signal_get_edge(DigitalSignal* signal, uint32_t edge_num); + +void digital_signal_send(DigitalSignal* signal, const GpioPin* gpio); + +DigitalSequence* digital_sequence_alloc(uint32_t size, const GpioPin* gpio); + +void digital_sequence_free(DigitalSequence* sequence); + +void digital_sequence_set_signal( + DigitalSequence* sequence, + uint8_t signal_index, + DigitalSignal* signal); + +void digital_sequence_set_sendtime(DigitalSequence* sequence, uint32_t send_time); + +void digital_sequence_add(DigitalSequence* sequence, uint8_t signal_index); + +bool digital_sequence_send(DigitalSequence* sequence); + +void digital_sequence_clear(DigitalSequence* sequence); + +void digital_sequence_timebase_correction(DigitalSequence* sequence, float factor); + +#ifdef __cplusplus +} +#endif diff --git a/esubghz_chat/lib/nfclegacy/furi_hal_nfc.c b/esubghz_chat/lib/nfclegacy/furi_hal_nfc.c new file mode 100644 index 00000000000..2f3a7af3e13 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/furi_hal_nfc.c @@ -0,0 +1,839 @@ +#include +#include "./furi_hal_nfc.h" +#include "ST25RFAL002/source/st25r3916/st25r3916.h" +#include "ST25RFAL002/source/st25r3916/st25r3916_irq.h" +#include "ST25RFAL002/include/rfal_rf.h" +#include + +#include "digital_signal/digital_signal.h" +#include +#include +#include +#include + +#define TAG "FurryHalNfc" + +static const uint32_t clocks_in_ms = 64 * 1000; + +FuriEventFlag* event = NULL; +#define EVENT_FLAG_INTERRUPT (1UL << 0) +#define EVENT_FLAG_STATE_CHANGED (1UL << 1) +#define EVENT_FLAG_STOP (1UL << 2) +#define EVENT_FLAG_ALL (EVENT_FLAG_INTERRUPT | EVENT_FLAG_STATE_CHANGED | EVENT_FLAG_STOP) + +#define FURRY_HAL_NFC_UID_INCOMPLETE (0x04) + +void furry_hal_nfc_init() { + furi_assert(!event); + event = furi_event_flag_alloc(); + + ReturnCode ret = rfalNfcInitialize(); + if(ret == ERR_NONE) { + furry_hal_nfc_start_sleep(); + FURI_LOG_I(TAG, "Init OK"); + } else { + FURI_LOG_W(TAG, "Init Failed, RFAL returned: %d", ret); + } +} + +void furry_hal_nfc_deinit() { + ReturnCode ret = rfalDeinitialize(); + if(ret == ERR_NONE) { + FURI_LOG_I(TAG, "Deinit OK"); + } else { + FURI_LOG_W(TAG, "Deinit Failed, RFAL returned: %d", ret); + } + + if(event) { + furi_event_flag_free(event); + event = NULL; + } +} + +bool furry_hal_nfc_is_busy() { + return rfalNfcGetState() != RFAL_NFC_STATE_IDLE; +} + +bool furry_hal_nfc_is_init() { + return rfalNfcGetState() != RFAL_NFC_STATE_NOTINIT; +} + +void furry_hal_nfc_field_on() { + furry_hal_nfc_exit_sleep(); + st25r3916TxRxOn(); +} + +void furry_hal_nfc_field_off() { + st25r3916TxRxOff(); + furry_hal_nfc_start_sleep(); +} + +void furry_hal_nfc_start_sleep() { + rfalLowPowerModeStart(); +} + +void furry_hal_nfc_exit_sleep() { + rfalLowPowerModeStop(); +} + +bool furry_hal_nfc_detect(FurryHalNfcDevData* nfc_data, uint32_t timeout) { + furi_assert(nfc_data); + + rfalNfcDevice* dev_list = NULL; + uint8_t dev_cnt = 0; + bool detected = false; + + rfalLowPowerModeStop(); + rfalNfcState state = rfalNfcGetState(); + rfalNfcState state_old = 0; + if(state == RFAL_NFC_STATE_NOTINIT) { + rfalNfcInitialize(); + } + rfalNfcDiscoverParam params; + params.compMode = RFAL_COMPLIANCE_MODE_EMV; + params.techs2Find = RFAL_NFC_POLL_TECH_A | RFAL_NFC_POLL_TECH_B | RFAL_NFC_POLL_TECH_F | + RFAL_NFC_POLL_TECH_V | RFAL_NFC_POLL_TECH_AP2P | RFAL_NFC_POLL_TECH_ST25TB; + params.totalDuration = 1000; + params.devLimit = 3; + params.wakeupEnabled = false; + params.wakeupConfigDefault = true; + params.nfcfBR = RFAL_BR_212; + params.ap2pBR = RFAL_BR_424; + params.maxBR = RFAL_BR_KEEP; + params.GBLen = RFAL_NFCDEP_GB_MAX_LEN; + params.notifyCb = NULL; + + uint32_t start = DWT->CYCCNT; + rfalNfcDiscover(¶ms); + while(true) { + rfalNfcWorker(); + state = rfalNfcGetState(); + if(state != state_old) { + FURI_LOG_T(TAG, "State change %d -> %d", state_old, state); + } + state_old = state; + if(state == RFAL_NFC_STATE_ACTIVATED) { + detected = true; + break; + } + if(state == RFAL_NFC_STATE_POLL_ACTIVATION) { + start = DWT->CYCCNT; + continue; + } + if(state == RFAL_NFC_STATE_POLL_SELECT) { + rfalNfcSelect(0); + } + if(DWT->CYCCNT - start > timeout * clocks_in_ms) { + rfalNfcDeactivate(true); + FURI_LOG_T(TAG, "Timeout"); + break; + } + furi_delay_tick(1); + } + rfalNfcGetDevicesFound(&dev_list, &dev_cnt); + if(detected) { + if(dev_list[0].type == RFAL_NFC_LISTEN_TYPE_NFCA) { + nfc_data->type = FurryHalNfcTypeA; + nfc_data->atqa[0] = dev_list[0].dev.nfca.sensRes.anticollisionInfo; + nfc_data->atqa[1] = dev_list[0].dev.nfca.sensRes.platformInfo; + nfc_data->sak = dev_list[0].dev.nfca.selRes.sak; + uint8_t* cuid_start = dev_list[0].nfcid; + if(dev_list[0].nfcidLen == 7) { + cuid_start = &dev_list[0].nfcid[3]; + } + nfc_data->cuid = (cuid_start[0] << 24) | (cuid_start[1] << 16) | (cuid_start[2] << 8) | + (cuid_start[3]); + } else if( + dev_list[0].type == RFAL_NFC_LISTEN_TYPE_NFCB || + dev_list[0].type == RFAL_NFC_LISTEN_TYPE_ST25TB) { + nfc_data->type = FurryHalNfcTypeB; + } else if(dev_list[0].type == RFAL_NFC_LISTEN_TYPE_NFCF) { + nfc_data->type = FurryHalNfcTypeF; + } else if(dev_list[0].type == RFAL_NFC_LISTEN_TYPE_NFCV) { + nfc_data->type = FurryHalNfcTypeV; + } + if(dev_list[0].rfInterface == RFAL_NFC_INTERFACE_RF) { + nfc_data->interface = FurryHalNfcInterfaceRf; + } else if(dev_list[0].rfInterface == RFAL_NFC_INTERFACE_ISODEP) { + nfc_data->interface = FurryHalNfcInterfaceIsoDep; + } else if(dev_list[0].rfInterface == RFAL_NFC_INTERFACE_NFCDEP) { + nfc_data->interface = FurryHalNfcInterfaceNfcDep; + } + nfc_data->uid_len = dev_list[0].nfcidLen; + memcpy(nfc_data->uid, dev_list[0].nfcid, nfc_data->uid_len); + } + + return detected; +} + +bool furry_hal_nfc_activate_nfca(uint32_t timeout, uint32_t* cuid) { + rfalNfcDevice* dev_list; + uint8_t dev_cnt = 0; + rfalLowPowerModeStop(); + rfalNfcState state = rfalNfcGetState(); + if(state == RFAL_NFC_STATE_NOTINIT) { + rfalNfcInitialize(); + } + rfalNfcDiscoverParam params = { + .compMode = RFAL_COMPLIANCE_MODE_NFC, + .techs2Find = RFAL_NFC_POLL_TECH_A, + .totalDuration = 1000, + .devLimit = 3, + .wakeupEnabled = false, + .wakeupConfigDefault = true, + .nfcfBR = RFAL_BR_212, + .ap2pBR = RFAL_BR_424, + .maxBR = RFAL_BR_KEEP, + .GBLen = RFAL_NFCDEP_GB_MAX_LEN, + .notifyCb = NULL, + }; + uint32_t start = DWT->CYCCNT; + rfalNfcDiscover(¶ms); + while(state != RFAL_NFC_STATE_ACTIVATED) { + rfalNfcWorker(); + state = rfalNfcGetState(); + FURI_LOG_T(TAG, "Current state %d", state); + if(state == RFAL_NFC_STATE_POLL_ACTIVATION) { + start = DWT->CYCCNT; + continue; + } + if(state == RFAL_NFC_STATE_POLL_SELECT) { + rfalNfcSelect(0); + } + if(DWT->CYCCNT - start > timeout * clocks_in_ms) { + rfalNfcDeactivate(true); + FURI_LOG_T(TAG, "Timeout"); + return false; + } + furi_thread_yield(); + } + rfalNfcGetDevicesFound(&dev_list, &dev_cnt); + // Take first device and set cuid + if(cuid) { + uint8_t* cuid_start = dev_list[0].nfcid; + if(dev_list[0].nfcidLen == 7) { + cuid_start = &dev_list[0].nfcid[3]; + } + *cuid = (cuid_start[0] << 24) | (cuid_start[1] << 16) | (cuid_start[2] << 8) | + (cuid_start[3]); + FURI_LOG_T(TAG, "Activated tag with cuid: %lX", *cuid); + } + return true; +} + +bool furry_hal_nfc_listen( + uint8_t* uid, + uint8_t uid_len, + uint8_t* atqa, + uint8_t sak, + bool activate_after_sak, + uint32_t timeout) { + rfalNfcState state = rfalNfcGetState(); + if(state == RFAL_NFC_STATE_NOTINIT) { + rfalNfcInitialize(); + } else if(state >= RFAL_NFC_STATE_ACTIVATED) { + rfalNfcDeactivate(false); + } + rfalLowPowerModeStop(); + rfalNfcDiscoverParam params = { + .techs2Find = RFAL_NFC_LISTEN_TECH_A, + .totalDuration = 1000, + .devLimit = 1, + .wakeupEnabled = false, + .wakeupConfigDefault = true, + .nfcfBR = RFAL_BR_212, + .ap2pBR = RFAL_BR_424, + .maxBR = RFAL_BR_KEEP, + .GBLen = RFAL_NFCDEP_GB_MAX_LEN, + .notifyCb = NULL, + .activate_after_sak = activate_after_sak, + }; + if(FURI_BIT(sak, 5)) { + params.compMode = RFAL_COMPLIANCE_MODE_EMV; + } else { + params.compMode = RFAL_COMPLIANCE_MODE_NFC; + } + params.lmConfigPA.nfcidLen = uid_len; + memcpy(params.lmConfigPA.nfcid, uid, uid_len); + params.lmConfigPA.SENS_RES[0] = atqa[0]; + params.lmConfigPA.SENS_RES[1] = atqa[1]; + params.lmConfigPA.SEL_RES = sak; + rfalNfcDiscover(¶ms); + + // Disable EMD suppression. + st25r3916ModifyRegister(ST25R3916_REG_EMD_SUP_CONF, ST25R3916_REG_EMD_SUP_CONF_emd_emv, 0); + + uint32_t start = DWT->CYCCNT; + while(state != RFAL_NFC_STATE_ACTIVATED) { + rfalNfcWorker(); + state = rfalNfcGetState(); + if(DWT->CYCCNT - start > timeout * clocks_in_ms) { + rfalNfcDeactivate(true); + return false; + } + furi_delay_tick(1); + } + return true; +} + +static void furry_hal_nfc_read_fifo(uint8_t* data, uint16_t* bits) { + uint8_t fifo_status[2]; + uint8_t rx_buff[64]; + + st25r3916ReadMultipleRegisters( + ST25R3916_REG_FIFO_STATUS1, fifo_status, ST25R3916_FIFO_STATUS_LEN); + uint16_t rx_bytes = + ((((uint16_t)fifo_status[1] & ST25R3916_REG_FIFO_STATUS2_fifo_b_mask) >> + ST25R3916_REG_FIFO_STATUS2_fifo_b_shift) + << 8); + rx_bytes |= (((uint16_t)fifo_status[0]) & 0x00FFU); + st25r3916ReadFifo(rx_buff, rx_bytes); + + memcpy(data, rx_buff, rx_bytes); + *bits = rx_bytes * 8; +} + +void furry_hal_nfc_listen_sleep() { + st25r3916ExecuteCommand(ST25R3916_CMD_GOTO_SLEEP); +} + +void furry_hal_nfc_stop_cmd() { + st25r3916ExecuteCommand(ST25R3916_CMD_STOP); +} + +bool furry_hal_nfc_listen_rx(FurryHalNfcTxRxContext* tx_rx, uint32_t timeout_ms) { + furi_assert(tx_rx); + + // Wait for interrupts + uint32_t start = furi_get_tick(); + bool data_received = false; + while(true) { + if(furi_hal_gpio_read(&gpio_nfc_irq_rfid_pull) == true) { + st25r3916CheckForReceivedInterrupts(); + if(st25r3916GetInterrupt(ST25R3916_IRQ_MASK_RXE)) { + furry_hal_nfc_read_fifo(tx_rx->rx_data, &tx_rx->rx_bits); + data_received = true; + if(tx_rx->sniff_rx) { + tx_rx->sniff_rx(tx_rx->rx_data, tx_rx->rx_bits, false, tx_rx->sniff_context); + } + break; + } + continue; + } + if(furi_get_tick() - start > timeout_ms) { + FURI_LOG_T(TAG, "Interrupt waiting timeout"); + furi_delay_tick(1); + break; + } + } + + return data_received; +} + +void furry_hal_nfc_listen_start(FurryHalNfcDevData* nfc_data) { + furi_assert(nfc_data); + + furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeInput, GpioPullDown, GpioSpeedVeryHigh); + // Clear interrupts + st25r3916ClearInterrupts(); + // Mask all interrupts + st25r3916DisableInterrupts(ST25R3916_IRQ_MASK_ALL); + // RESET + st25r3916ExecuteCommand(ST25R3916_CMD_STOP); + // Setup registers + st25r3916WriteRegister( + ST25R3916_REG_OP_CONTROL, + ST25R3916_REG_OP_CONTROL_en | ST25R3916_REG_OP_CONTROL_rx_en | + ST25R3916_REG_OP_CONTROL_en_fd_auto_efd); + st25r3916WriteRegister( + ST25R3916_REG_MODE, + ST25R3916_REG_MODE_targ_targ | ST25R3916_REG_MODE_om3 | ST25R3916_REG_MODE_om0); + st25r3916WriteRegister( + ST25R3916_REG_PASSIVE_TARGET, + ST25R3916_REG_PASSIVE_TARGET_fdel_2 | ST25R3916_REG_PASSIVE_TARGET_fdel_0 | + ST25R3916_REG_PASSIVE_TARGET_d_ac_ap2p | ST25R3916_REG_PASSIVE_TARGET_d_212_424_1r); + st25r3916WriteRegister(ST25R3916_REG_MASK_RX_TIMER, 0x02); + + // Mask interrupts + uint32_t clear_irq_mask = + (ST25R3916_IRQ_MASK_RXE | ST25R3916_IRQ_MASK_RXE_PTA | ST25R3916_IRQ_MASK_WU_A_X | + ST25R3916_IRQ_MASK_WU_A); + st25r3916EnableInterrupts(clear_irq_mask); + + // Set 4 or 7 bytes UID + if(nfc_data->uid_len == 4) { + st25r3916ChangeRegisterBits( + ST25R3916_REG_AUX, ST25R3916_REG_AUX_nfc_id_mask, ST25R3916_REG_AUX_nfc_id_4bytes); + } else { + st25r3916ChangeRegisterBits( + ST25R3916_REG_AUX, ST25R3916_REG_AUX_nfc_id_mask, ST25R3916_REG_AUX_nfc_id_7bytes); + } + // Write PT Memory + uint8_t pt_memory[15] = {}; + memcpy(pt_memory, nfc_data->uid, nfc_data->uid_len); + pt_memory[10] = nfc_data->atqa[0]; + pt_memory[11] = nfc_data->atqa[1]; + if(nfc_data->uid_len == 4) { + pt_memory[12] = nfc_data->sak & ~FURRY_HAL_NFC_UID_INCOMPLETE; + } else { + pt_memory[12] = FURRY_HAL_NFC_UID_INCOMPLETE; + } + pt_memory[13] = nfc_data->sak & ~FURRY_HAL_NFC_UID_INCOMPLETE; + pt_memory[14] = nfc_data->sak & ~FURRY_HAL_NFC_UID_INCOMPLETE; + + st25r3916WritePTMem(pt_memory, sizeof(pt_memory)); + // Go to sense + st25r3916ExecuteCommand(ST25R3916_CMD_GOTO_SENSE); +} + +void rfal_interrupt_callback_handler() { + furi_event_flag_set(event, EVENT_FLAG_INTERRUPT); +} + +void rfal_state_changed_callback(void* context) { + UNUSED(context); + furi_event_flag_set(event, EVENT_FLAG_STATE_CHANGED); +} + +void furry_hal_nfc_stop() { + if(event) { + furi_event_flag_set(event, EVENT_FLAG_STOP); + } +} + +bool furry_hal_nfc_emulate_nfca( + uint8_t* uid, + uint8_t uid_len, + uint8_t* atqa, + uint8_t sak, + FurryHalNfcEmulateCallback callback, + void* context, + uint32_t timeout) { + rfalSetUpperLayerCallback(rfal_interrupt_callback_handler); + rfal_set_state_changed_callback(rfal_state_changed_callback); + + rfalLmConfPA config; + config.nfcidLen = uid_len; + memcpy(config.nfcid, uid, uid_len); + memcpy(config.SENS_RES, atqa, RFAL_LM_SENS_RES_LEN); + config.SEL_RES = sak; + uint8_t buff_rx[256]; + uint16_t buff_rx_size = 256; + uint16_t buff_rx_len = 0; + uint8_t buff_tx[1040]; + uint16_t buff_tx_len = 0; + uint32_t data_type = FURRY_HAL_NFC_TXRX_DEFAULT; + + rfalLowPowerModeStop(); + if(rfalListenStart( + RFAL_LM_MASK_NFCA, + &config, + NULL, + NULL, + buff_rx, + rfalConvBytesToBits(buff_rx_size), + &buff_rx_len)) { + rfalListenStop(); + FURI_LOG_E(TAG, "Failed to start listen mode"); + return false; + } + while(true) { + buff_rx_len = 0; + buff_tx_len = 0; + uint32_t flag = furi_event_flag_wait(event, EVENT_FLAG_ALL, FuriFlagWaitAny, timeout); + if(flag == (unsigned)FuriFlagErrorTimeout || flag == EVENT_FLAG_STOP) { + break; + } + bool data_received = false; + buff_rx_len = 0; + rfalWorker(); + rfalLmState state = rfalListenGetState(&data_received, NULL); + if(data_received) { + rfalTransceiveBlockingRx(); + if(nfca_emulation_handler(buff_rx, buff_rx_len, buff_tx, &buff_tx_len)) { + if(rfalListenSleepStart( + RFAL_LM_STATE_SLEEP_A, + buff_rx, + rfalConvBytesToBits(buff_rx_size), + &buff_rx_len)) { + FURI_LOG_E(TAG, "Failed to enter sleep mode"); + break; + } else { + continue; + } + } + if(buff_tx_len) { + ReturnCode ret = rfalTransceiveBitsBlockingTx( + buff_tx, + buff_tx_len, + buff_rx, + rfalConvBytesToBits(buff_rx_size), + &buff_rx_len, + data_type, + RFAL_FWT_NONE); + if(ret) { + FURI_LOG_E(TAG, "Tranceive failed with status %d", ret); + break; + } + continue; + } + if((state == RFAL_LM_STATE_ACTIVE_A || state == RFAL_LM_STATE_ACTIVE_Ax)) { + if(callback) { + callback(buff_rx, buff_rx_len, buff_tx, &buff_tx_len, &data_type, context); + } + if(!rfalIsExtFieldOn()) { + break; + } + if(buff_tx_len) { + if(buff_tx_len == UINT16_MAX) buff_tx_len = 0; + + ReturnCode ret = rfalTransceiveBitsBlockingTx( + buff_tx, + buff_tx_len, + buff_rx, + rfalConvBytesToBits(buff_rx_size), + &buff_rx_len, + data_type, + RFAL_FWT_NONE); + if(ret) { + FURI_LOG_E(TAG, "Tranceive failed with status %d", ret); + continue; + } + } else { + break; + } + } + } + } + rfalListenStop(); + return true; +} + +static bool furry_hal_nfc_transparent_tx_rx(FurryHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) { + furi_assert(tx_rx->nfca_signal); + + bool ret = false; + + // Start transparent mode + st25r3916ExecuteCommand(ST25R3916_CMD_TRANSPARENT_MODE); + // Reconfigure gpio for Transparent mode + furi_hal_spi_bus_handle_deinit(&furi_hal_spi_bus_handle_nfc); + + // Send signal + FURI_CRITICAL_ENTER(); + nfca_signal_encode(tx_rx->nfca_signal, tx_rx->tx_data, tx_rx->tx_bits, tx_rx->tx_parity); + digital_signal_send(tx_rx->nfca_signal->tx_signal, &gpio_spi_r_mosi); + FURI_CRITICAL_EXIT(); + furi_hal_gpio_write(&gpio_spi_r_mosi, false); + + // Configure gpio back to SPI and exit transparent + furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc); + st25r3916ExecuteCommand(ST25R3916_CMD_UNMASK_RECEIVE_DATA); + + // Manually wait for interrupt + furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeInput, GpioPullDown, GpioSpeedVeryHigh); + st25r3916ClearAndEnableInterrupts(ST25R3916_IRQ_MASK_RXE); + + if(tx_rx->sniff_tx) { + tx_rx->sniff_tx(tx_rx->tx_data, tx_rx->tx_bits, false, tx_rx->sniff_context); + } + + uint32_t irq = 0; + uint8_t rxe = 0; + uint32_t start = DWT->CYCCNT; + while(true) { + if(!rfalIsExtFieldOn()) { + return false; + } + if(furi_hal_gpio_read(&gpio_nfc_irq_rfid_pull) == true) { + st25r3916ReadRegister(ST25R3916_REG_IRQ_MAIN, &rxe); + if(rxe & (1 << 4)) { + irq = 1; + break; + } + } + uint32_t timeout = DWT->CYCCNT - start; + if(timeout / furi_hal_cortex_instructions_per_microsecond() > timeout_ms * 1000) { + FURI_LOG_D(TAG, "Interrupt waiting timeout"); + break; + } + } + if(irq) { + uint8_t fifo_stat[2]; + st25r3916ReadMultipleRegisters( + ST25R3916_REG_FIFO_STATUS1, fifo_stat, ST25R3916_FIFO_STATUS_LEN); + uint16_t len = + ((((uint16_t)fifo_stat[1] & ST25R3916_REG_FIFO_STATUS2_fifo_b_mask) >> + ST25R3916_REG_FIFO_STATUS2_fifo_b_shift) + << RFAL_BITS_IN_BYTE); + len |= (((uint16_t)fifo_stat[0]) & 0x00FFU); + uint8_t rx[100]; + st25r3916ReadFifo(rx, len); + + tx_rx->rx_bits = len * 8; + memcpy(tx_rx->rx_data, rx, len); + + if(tx_rx->sniff_rx) { + tx_rx->sniff_rx(tx_rx->rx_data, tx_rx->rx_bits, false, tx_rx->sniff_context); + } + + ret = true; + } else { + FURI_LOG_E(TAG, "Timeout error"); + ret = false; + } + + st25r3916ClearInterrupts(); + + return ret; +} + +static uint32_t furry_hal_nfc_tx_rx_get_flag(FurryHalNfcTxRxType type) { + uint32_t flags = 0; + + if(type == FurryHalNfcTxRxTypeRxNoCrc) { + flags = RFAL_TXRX_FLAGS_CRC_RX_KEEP; + } else if(type == FurryHalNfcTxRxTypeRxKeepPar) { + flags = RFAL_TXRX_FLAGS_CRC_TX_MANUAL | RFAL_TXRX_FLAGS_CRC_RX_KEEP | + RFAL_TXRX_FLAGS_PAR_RX_KEEP; + } else if(type == FurryHalNfcTxRxTypeRaw) { + flags = RFAL_TXRX_FLAGS_CRC_TX_MANUAL | RFAL_TXRX_FLAGS_CRC_RX_KEEP | + RFAL_TXRX_FLAGS_PAR_RX_KEEP | RFAL_TXRX_FLAGS_PAR_TX_NONE; + } else if(type == FurryHalNfcTxRxTypeRxRaw) { + flags = RFAL_TXRX_FLAGS_CRC_TX_MANUAL | RFAL_TXRX_FLAGS_CRC_RX_KEEP | + RFAL_TXRX_FLAGS_PAR_RX_KEEP | RFAL_TXRX_FLAGS_PAR_TX_NONE; + } + + return flags; +} + +static uint16_t furry_hal_nfc_data_and_parity_to_bitstream( + uint8_t* data, + uint16_t len, + uint8_t* parity, + uint8_t* out) { + furi_assert(data); + furi_assert(out); + + uint8_t next_par_bit = 0; + uint16_t curr_bit_pos = 0; + for(uint16_t i = 0; i < len; i++) { + next_par_bit = FURI_BIT(parity[i / 8], 7 - (i % 8)); + if(curr_bit_pos % 8 == 0) { + out[curr_bit_pos / 8] = data[i]; + curr_bit_pos += 8; + out[curr_bit_pos / 8] = next_par_bit; + curr_bit_pos++; + } else { + out[curr_bit_pos / 8] |= data[i] << (curr_bit_pos % 8); + out[curr_bit_pos / 8 + 1] = data[i] >> (8 - curr_bit_pos % 8); + out[curr_bit_pos / 8 + 1] |= next_par_bit << (curr_bit_pos % 8); + curr_bit_pos += 9; + } + } + return curr_bit_pos; +} + +uint16_t furry_hal_nfc_bitstream_to_data_and_parity( + uint8_t* in_buff, + uint16_t in_buff_bits, + uint8_t* out_data, + uint8_t* out_parity) { + if(in_buff_bits < 8) { + out_data[0] = in_buff[0]; + return in_buff_bits; + } + if(in_buff_bits % 9 != 0) { + return 0; + } + + uint8_t curr_byte = 0; + uint16_t bit_processed = 0; + memset(out_parity, 0, in_buff_bits / 9); + while(bit_processed < in_buff_bits) { + out_data[curr_byte] = in_buff[bit_processed / 8] >> (bit_processed % 8); + out_data[curr_byte] |= in_buff[bit_processed / 8 + 1] << (8 - bit_processed % 8); + out_parity[curr_byte / 8] |= FURI_BIT(in_buff[bit_processed / 8 + 1], bit_processed % 8) + << (7 - curr_byte % 8); + bit_processed += 9; + curr_byte++; + } + return curr_byte * 8; +} + +bool furry_hal_nfc_tx_rx(FurryHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) { + furi_assert(tx_rx); + + ReturnCode ret; + rfalNfcState state = RFAL_NFC_STATE_ACTIVATED; + uint8_t temp_tx_buff[FURRY_HAL_NFC_DATA_BUFF_SIZE] = {}; + uint16_t temp_tx_bits = 0; + uint8_t* temp_rx_buff = NULL; + uint16_t* temp_rx_bits = NULL; + + if(tx_rx->tx_rx_type == FurryHalNfcTxRxTransparent) { + return furry_hal_nfc_transparent_tx_rx(tx_rx, timeout_ms); + } + + // Prepare data for FIFO if necessary + uint32_t flags = furry_hal_nfc_tx_rx_get_flag(tx_rx->tx_rx_type); + if(tx_rx->tx_rx_type == FurryHalNfcTxRxTypeRaw) { + temp_tx_bits = furry_hal_nfc_data_and_parity_to_bitstream( + tx_rx->tx_data, tx_rx->tx_bits / 8, tx_rx->tx_parity, temp_tx_buff); + ret = rfalNfcDataExchangeCustomStart( + temp_tx_buff, temp_tx_bits, &temp_rx_buff, &temp_rx_bits, RFAL_FWT_NONE, flags); + } else { + ret = rfalNfcDataExchangeCustomStart( + tx_rx->tx_data, tx_rx->tx_bits, &temp_rx_buff, &temp_rx_bits, RFAL_FWT_NONE, flags); + } + if(ret != ERR_NONE) { + FURI_LOG_E(TAG, "Failed to start data exchange"); + return false; + } + + if(tx_rx->sniff_tx) { + bool crc_dropped = !(flags & RFAL_TXRX_FLAGS_CRC_TX_MANUAL); + tx_rx->sniff_tx(tx_rx->tx_data, tx_rx->tx_bits, crc_dropped, tx_rx->sniff_context); + } + + uint32_t start = DWT->CYCCNT; + while(state != RFAL_NFC_STATE_DATAEXCHANGE_DONE) { + rfalNfcWorker(); + state = rfalNfcGetState(); + ret = rfalNfcDataExchangeGetStatus(); + if(ret == ERR_WRONG_STATE) { + return false; + } else if(ret == ERR_BUSY) { + if(DWT->CYCCNT - start > timeout_ms * clocks_in_ms) { + FURI_LOG_D(TAG, "Timeout during data exchange"); + return false; + } + continue; + } else { + start = DWT->CYCCNT; + } + furi_delay_tick(1); + } + + if(tx_rx->tx_rx_type == FurryHalNfcTxRxTypeRaw || + tx_rx->tx_rx_type == FurryHalNfcTxRxTypeRxRaw) { + tx_rx->rx_bits = furry_hal_nfc_bitstream_to_data_and_parity( + temp_rx_buff, *temp_rx_bits, tx_rx->rx_data, tx_rx->rx_parity); + } else { + memcpy(tx_rx->rx_data, temp_rx_buff, MIN(*temp_rx_bits / 8, FURRY_HAL_NFC_DATA_BUFF_SIZE)); + tx_rx->rx_bits = *temp_rx_bits; + } + + if(tx_rx->sniff_rx) { + bool crc_dropped = !(flags & RFAL_TXRX_FLAGS_CRC_RX_KEEP); + tx_rx->sniff_rx(tx_rx->rx_data, tx_rx->rx_bits, crc_dropped, tx_rx->sniff_context); + } + + return true; +} + +bool furry_hal_nfc_tx_rx_full(FurryHalNfcTxRxContext* tx_rx) { + uint16_t part_len_bytes; + + if(!furry_hal_nfc_tx_rx(tx_rx, 1000)) { + return false; + } + while(tx_rx->rx_bits && tx_rx->rx_data[0] == 0xAF) { + FurryHalNfcTxRxContext tmp = *tx_rx; + tmp.tx_data[0] = 0xAF; + tmp.tx_bits = 8; + if(!furry_hal_nfc_tx_rx(&tmp, 1000)) { + return false; + } + part_len_bytes = tmp.rx_bits / 8; + if(part_len_bytes > FURRY_HAL_NFC_DATA_BUFF_SIZE - tx_rx->rx_bits / 8) { + FURI_LOG_W(TAG, "Overrun rx buf"); + return false; + } + if(part_len_bytes == 0) { + FURI_LOG_W(TAG, "Empty 0xAF response"); + return false; + } + memcpy(tx_rx->rx_data + tx_rx->rx_bits / 8, tmp.rx_data + 1, part_len_bytes - 1); + tx_rx->rx_data[0] = tmp.rx_data[0]; + tx_rx->rx_bits += 8 * (part_len_bytes - 1); + } + + return true; +} + +void furry_hal_nfc_sleep() { + rfalNfcDeactivate(false); + rfalLowPowerModeStart(); +} + +FurryHalNfcReturn furry_hal_nfc_ll_set_mode( + FurryHalNfcMode mode, + FurryHalNfcBitrate txBR, + FurryHalNfcBitrate rxBR) { + return rfalSetMode((rfalMode)mode, (rfalBitRate)txBR, (rfalBitRate)rxBR); +} + +void furry_hal_nfc_ll_set_error_handling(FurryHalNfcErrorHandling eHandling) { + rfalSetErrorHandling((rfalEHandling)eHandling); +} + +void furry_hal_nfc_ll_set_guard_time(uint32_t cycles) { + rfalSetGT(cycles); +} + +void furry_hal_nfc_ll_set_fdt_listen(uint32_t cycles) { + rfalSetFDTListen(cycles); +} + +void furry_hal_nfc_ll_set_fdt_poll(uint32_t FDTPoll) { + rfalSetFDTPoll(FDTPoll); +} + +void furry_hal_nfc_ll_txrx_on() { + st25r3916TxRxOn(); +} + +void furry_hal_nfc_ll_txrx_off() { + st25r3916TxRxOff(); +} + +FurryHalNfcReturn furry_hal_nfc_ll_txrx( + uint8_t* txBuf, + uint16_t txBufLen, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* actLen, + uint32_t flags, + uint32_t fwt) { + return rfalTransceiveBlockingTxRx(txBuf, txBufLen, rxBuf, rxBufLen, actLen, flags, fwt); +} + +FurryHalNfcReturn furry_hal_nfc_ll_txrx_bits( + uint8_t* txBuf, + uint16_t txBufLen, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* actLen, + uint32_t flags, + uint32_t fwt) { + return rfalTransceiveBitsBlockingTxRx(txBuf, txBufLen, rxBuf, rxBufLen, actLen, flags, fwt); +} + +void furry_hal_nfc_ll_poll() { + rfalWorker(); +} + +void furry_hal_nfc_field_detect_start() { + st25r3916WriteRegister( + ST25R3916_REG_OP_CONTROL, + ST25R3916_REG_OP_CONTROL_en | ST25R3916_REG_OP_CONTROL_en_fd_mask); + st25r3916WriteRegister(ST25R3916_REG_MODE, ST25R3916_REG_MODE_targ | ST25R3916_REG_MODE_om0); +} + +bool furry_hal_nfc_field_is_present() { + return st25r3916CheckReg( + ST25R3916_REG_AUX_DISPLAY, + ST25R3916_REG_AUX_DISPLAY_efd_o, + ST25R3916_REG_AUX_DISPLAY_efd_o); +} \ No newline at end of file diff --git a/esubghz_chat/lib/nfclegacy/furi_hal_nfc.h b/esubghz_chat/lib/nfclegacy/furi_hal_nfc.h new file mode 100644 index 00000000000..f75f131411b --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/furi_hal_nfc.h @@ -0,0 +1,438 @@ +/** + * @file furry_hal_nfc.h + * NFC HAL API + */ + +#pragma once + +#include "ST25RFAL002/st_errno.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +#include "ST25RFAL002/include/rfal_nfc.h" +#include "protocols/nfca.h" + +#define FURRY_HAL_NFC_UID_MAX_LEN 10 +#define FURRY_HAL_NFC_DATA_BUFF_SIZE (512) +#define FURRY_HAL_NFC_PARITY_BUFF_SIZE (FURRY_HAL_NFC_DATA_BUFF_SIZE / 8) + +#define FURRY_HAL_NFC_TXRX_DEFAULT \ + ((uint32_t)RFAL_TXRX_FLAGS_CRC_TX_AUTO | (uint32_t)RFAL_TXRX_FLAGS_CRC_RX_REMV | \ + (uint32_t)RFAL_TXRX_FLAGS_PAR_RX_REMV | (uint32_t)RFAL_TXRX_FLAGS_PAR_TX_AUTO) + +#define FURRY_HAL_NFC_TX_DEFAULT_RX_NO_CRC \ + ((uint32_t)RFAL_TXRX_FLAGS_CRC_TX_AUTO | (uint32_t)RFAL_TXRX_FLAGS_CRC_RX_KEEP | \ + (uint32_t)RFAL_TXRX_FLAGS_PAR_RX_REMV | (uint32_t)RFAL_TXRX_FLAGS_PAR_TX_AUTO) + +#define FURRY_HAL_NFC_TXRX_WITH_PAR \ + ((uint32_t)RFAL_TXRX_FLAGS_CRC_TX_MANUAL | (uint32_t)RFAL_TXRX_FLAGS_CRC_RX_KEEP | \ + (uint32_t)RFAL_TXRX_FLAGS_PAR_RX_KEEP | (uint32_t)RFAL_TXRX_FLAGS_PAR_TX_AUTO) + +#define FURRY_HAL_NFC_TXRX_RAW \ + ((uint32_t)RFAL_TXRX_FLAGS_CRC_TX_MANUAL | (uint32_t)RFAL_TXRX_FLAGS_CRC_RX_KEEP | \ + (uint32_t)RFAL_TXRX_FLAGS_PAR_RX_KEEP | (uint32_t)RFAL_TXRX_FLAGS_PAR_TX_NONE) + +#define FURRY_HAL_NFC_TX_RAW_RX_DEFAULT \ + ((uint32_t)RFAL_TXRX_FLAGS_CRC_TX_MANUAL | (uint32_t)RFAL_TXRX_FLAGS_CRC_RX_REMV | \ + (uint32_t)RFAL_TXRX_FLAGS_PAR_RX_REMV | (uint32_t)RFAL_TXRX_FLAGS_PAR_TX_NONE) + +typedef enum { + FurryHalNfcTxRxTypeDefault, + FurryHalNfcTxRxTypeRxNoCrc, + FurryHalNfcTxRxTypeRxKeepPar, + FurryHalNfcTxRxTypeRaw, + FurryHalNfcTxRxTypeRxRaw, + FurryHalNfcTxRxTransparent, +} FurryHalNfcTxRxType; + +typedef bool (*FurryHalNfcEmulateCallback)( + uint8_t* buff_rx, + uint16_t buff_rx_len, + uint8_t* buff_tx, + uint16_t* buff_tx_len, + uint32_t* flags, + void* context); + +typedef enum { + FurryHalNfcTypeA, + FurryHalNfcTypeB, + FurryHalNfcTypeF, + FurryHalNfcTypeV, +} FurryHalNfcType; + +typedef enum { + FurryHalNfcInterfaceRf, + FurryHalNfcInterfaceIsoDep, + FurryHalNfcInterfaceNfcDep, +} FurryHalNfcInterface; + +typedef struct { + FurryHalNfcType type; + FurryHalNfcInterface interface; + uint8_t uid_len; + uint8_t uid[10]; + uint32_t cuid; + uint8_t atqa[2]; + uint8_t sak; +} FurryHalNfcDevData; + +typedef void ( + *FurryHalNfcTxRxSniffCallback)(uint8_t* data, uint16_t bits, bool crc_dropped, void* context); + +typedef struct { + uint8_t tx_data[FURRY_HAL_NFC_DATA_BUFF_SIZE]; + uint8_t tx_parity[FURRY_HAL_NFC_PARITY_BUFF_SIZE]; + uint16_t tx_bits; + uint8_t rx_data[FURRY_HAL_NFC_DATA_BUFF_SIZE]; + uint8_t rx_parity[FURRY_HAL_NFC_PARITY_BUFF_SIZE]; + uint16_t rx_bits; + FurryHalNfcTxRxType tx_rx_type; + NfcaSignal* nfca_signal; + + FurryHalNfcTxRxSniffCallback sniff_tx; + FurryHalNfcTxRxSniffCallback sniff_rx; + void* sniff_context; +} FurryHalNfcTxRxContext; + +/** Init nfc + */ +void furry_hal_nfc_init(); + +/** Deinit nfc + */ +void furry_hal_nfc_deinit(); + +/** Check if nfc worker is busy + * + * @return true if busy + */ +bool furry_hal_nfc_is_busy(); + +/** Check if nfc is initialized + * + * @return true if initialized + */ +bool furry_hal_nfc_is_init(); + +/** NFC field on + */ +void furry_hal_nfc_field_on(); + +/** NFC field off + */ +void furry_hal_nfc_field_off(); + +/** NFC start sleep + */ +void furry_hal_nfc_start_sleep(); + +void furry_hal_nfc_stop_cmd(); + +/** NFC stop sleep + */ +void furry_hal_nfc_exit_sleep(); + +/** NFC poll + * + * @param dev_list pointer to rfalNfcDevice buffer + * @param dev_cnt pointer device count + * @param timeout timeout in ms + * @param deactivate deactivate flag + * + * @return true on success + */ +bool furry_hal_nfc_detect(FurryHalNfcDevData* nfc_data, uint32_t timeout); + +/** Activate NFC-A tag + * + * @param timeout timeout in ms + * @param cuid pointer to 32bit uid + * + * @return true on succeess + */ +bool furry_hal_nfc_activate_nfca(uint32_t timeout, uint32_t* cuid); + +/** NFC listen + * + * @param uid pointer to uid buffer + * @param uid_len uid length + * @param atqa pointer to atqa + * @param sak sak + * @param activate_after_sak activate after sak flag + * @param timeout timeout in ms + * + * @return true on success + */ +bool furry_hal_nfc_listen( + uint8_t* uid, + uint8_t uid_len, + uint8_t* atqa, + uint8_t sak, + bool activate_after_sak, + uint32_t timeout); + +/** Start Target Listen mode + * @note RFAL free implementation + * + * @param nfc_data FurryHalNfcDevData instance + */ +void furry_hal_nfc_listen_start(FurryHalNfcDevData* nfc_data); + +/** Read data in Target Listen mode + * @note Must be called only after furry_hal_nfc_listen_start() + * + * @param tx_rx FurryHalNfcTxRxContext instance + * @param timeout_ms timeout im ms + * + * @return true on not empty receive + */ +bool furry_hal_nfc_listen_rx(FurryHalNfcTxRxContext* tx_rx, uint32_t timeout_ms); + +/** Set Target in Sleep state */ +void furry_hal_nfc_listen_sleep(); + +/** Emulate NFC-A Target + * @note RFAL based implementation + * + * @param uid NFC-A UID + * @param uid_len NFC-A UID length + * @param atqa NFC-A ATQA + * @param sak NFC-A SAK + * @param callback FurryHalNfcEmulateCallback instance + * @param context pointer to context for callback + * @param timeout timeout in ms + * + * @return true on success + */ +bool furry_hal_nfc_emulate_nfca( + uint8_t* uid, + uint8_t uid_len, + uint8_t* atqa, + uint8_t sak, + FurryHalNfcEmulateCallback callback, + void* context, + uint32_t timeout); + +/** NFC data exchange + * + * @param tx_rx_ctx FurryHalNfcTxRxContext instance + * + * @return true on success + */ +bool furry_hal_nfc_tx_rx(FurryHalNfcTxRxContext* tx_rx, uint16_t timeout_ms); + +/** NFC data full exhange + * + * @param tx_rx_ctx FurryHalNfcTxRxContext instance + * + * @return true on success + */ +bool furry_hal_nfc_tx_rx_full(FurryHalNfcTxRxContext* tx_rx); + +/** NFC deactivate and start sleep + */ +void furry_hal_nfc_sleep(); + +void furry_hal_nfc_stop(); + +/* Low level transport API, use it to implement your own transport layers */ + +#define furry_hal_nfc_ll_ms2fc rfalConvMsTo1fc + +#define FURRY_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL RFAL_TXRX_FLAGS_CRC_TX_MANUAL +#define FURRY_HAL_NFC_LL_TXRX_FLAGS_AGC_ON RFAL_TXRX_FLAGS_AGC_ON +#define FURRY_HAL_NFC_LL_TXRX_FLAGS_PAR_RX_REMV RFAL_TXRX_FLAGS_PAR_RX_REMV +#define FURRY_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP RFAL_TXRX_FLAGS_CRC_RX_KEEP + +typedef enum { + FurryHalNfcReturnOk = 0, /*!< no error occurred */ + FurryHalNfcReturnNomem = 1, /*!< not enough memory to perform the requested operation */ + FurryHalNfcReturnBusy = 2, /*!< device or resource busy */ + FurryHalNfcReturnIo = 3, /*!< generic IO error */ + FurryHalNfcReturnTimeout = 4, /*!< error due to timeout */ + FurryHalNfcReturnRequest = + 5, /*!< invalid request or requested function can't be executed at the moment */ + FurryHalNfcReturnNomsg = 6, /*!< No message of desired type */ + FurryHalNfcReturnParam = 7, /*!< Parameter error */ + FurryHalNfcReturnSystem = 8, /*!< System error */ + FurryHalNfcReturnFraming = 9, /*!< Framing error */ + FurryHalNfcReturnOverrun = 10, /*!< lost one or more received bytes */ + FurryHalNfcReturnProto = 11, /*!< protocol error */ + FurryHalNfcReturnInternal = 12, /*!< Internal Error */ + FurryHalNfcReturnAgain = 13, /*!< Call again */ + FurryHalNfcReturnMemCorrupt = 14, /*!< memory corruption */ + FurryHalNfcReturnNotImplemented = 15, /*!< not implemented */ + FurryHalNfcReturnPcCorrupt = + 16, /*!< Program Counter has been manipulated or spike/noise trigger illegal operation */ + FurryHalNfcReturnSend = 17, /*!< error sending*/ + FurryHalNfcReturnIgnore = 18, /*!< indicates error detected but to be ignored */ + FurryHalNfcReturnSemantic = 19, /*!< indicates error in state machine (unexpected cmd) */ + FurryHalNfcReturnSyntax = 20, /*!< indicates error in state machine (unknown cmd) */ + FurryHalNfcReturnCrc = 21, /*!< crc error */ + FurryHalNfcReturnNotfound = 22, /*!< transponder not found */ + FurryHalNfcReturnNotunique = + 23, /*!< transponder not unique - more than one transponder in field */ + FurryHalNfcReturnNotsupp = 24, /*!< requested operation not supported */ + FurryHalNfcReturnWrite = 25, /*!< write error */ + FurryHalNfcReturnFifo = 26, /*!< fifo over or underflow error */ + FurryHalNfcReturnPar = 27, /*!< parity error */ + FurryHalNfcReturnDone = 28, /*!< transfer has already finished */ + FurryHalNfcReturnRfCollision = + 29, /*!< collision error (Bit Collision or during RF Collision avoidance ) */ + FurryHalNfcReturnHwOverrun = 30, /*!< lost one or more received bytes */ + FurryHalNfcReturnReleaseReq = 31, /*!< device requested release */ + FurryHalNfcReturnSleepReq = 32, /*!< device requested sleep */ + FurryHalNfcReturnWrongState = 33, /*!< incorrent state for requested operation */ + FurryHalNfcReturnMaxReruns = 34, /*!< blocking procedure reached maximum runs */ + FurryHalNfcReturnDisabled = 35, /*!< operation aborted due to disabled configuration */ + FurryHalNfcReturnHwMismatch = 36, /*!< expected hw do not match */ + FurryHalNfcReturnLinkLoss = + 37, /*!< Other device's field didn't behave as expected: turned off by Initiator in Passive mode, or AP2P did not turn on field */ + FurryHalNfcReturnInvalidHandle = 38, /*!< invalid or not initalized device handle */ + FurryHalNfcReturnIncompleteByte = 40, /*!< Incomplete byte rcvd */ + FurryHalNfcReturnIncompleteByte01 = 41, /*!< Incomplete byte rcvd - 1 bit */ + FurryHalNfcReturnIncompleteByte02 = 42, /*!< Incomplete byte rcvd - 2 bit */ + FurryHalNfcReturnIncompleteByte03 = 43, /*!< Incomplete byte rcvd - 3 bit */ + FurryHalNfcReturnIncompleteByte04 = 44, /*!< Incomplete byte rcvd - 4 bit */ + FurryHalNfcReturnIncompleteByte05 = 45, /*!< Incomplete byte rcvd - 5 bit */ + FurryHalNfcReturnIncompleteByte06 = 46, /*!< Incomplete byte rcvd - 6 bit */ + FurryHalNfcReturnIncompleteByte07 = 47, /*!< Incomplete byte rcvd - 7 bit */ +} FurryHalNfcReturn; + +typedef enum { + FurryHalNfcModeNone = 0, /*!< No mode selected/defined */ + FurryHalNfcModePollNfca = 1, /*!< Mode to perform as NFCA (ISO14443A) Poller (PCD) */ + FurryHalNfcModePollNfcaT1t = 2, /*!< Mode to perform as NFCA T1T (Topaz) Poller (PCD) */ + FurryHalNfcModePollNfcb = 3, /*!< Mode to perform as NFCB (ISO14443B) Poller (PCD) */ + FurryHalNfcModePollBPrime = 4, /*!< Mode to perform as B' Calypso (Innovatron) (PCD) */ + FurryHalNfcModePollBCts = 5, /*!< Mode to perform as CTS Poller (PCD) */ + FurryHalNfcModePollNfcf = 6, /*!< Mode to perform as NFCF (FeliCa) Poller (PCD) */ + FurryHalNfcModePollNfcv = 7, /*!< Mode to perform as NFCV (ISO15963) Poller (PCD) */ + FurryHalNfcModePollPicopass = 8, /*!< Mode to perform as PicoPass / iClass Poller (PCD) */ + FurryHalNfcModePollActiveP2p = 9, /*!< Mode to perform as Active P2P (ISO18092) Initiator */ + FurryHalNfcModeListenNfca = 10, /*!< Mode to perform as NFCA (ISO14443A) Listener (PICC) */ + FurryHalNfcModeListenNfcb = 11, /*!< Mode to perform as NFCA (ISO14443B) Listener (PICC) */ + FurryHalNfcModeListenNfcf = 12, /*!< Mode to perform as NFCA (ISO15963) Listener (PICC) */ + FurryHalNfcModeListenActiveP2p = 13 /*!< Mode to perform as Active P2P (ISO18092) Target */ +} FurryHalNfcMode; + +typedef enum { + FurryHalNfcBitrate106 = 0, /*!< Bit Rate 106 kbit/s (fc/128) */ + FurryHalNfcBitrate212 = 1, /*!< Bit Rate 212 kbit/s (fc/64) */ + FurryHalNfcBitrate424 = 2, /*!< Bit Rate 424 kbit/s (fc/32) */ + FurryHalNfcBitrate848 = 3, /*!< Bit Rate 848 kbit/s (fc/16) */ + FurryHalNfcBitrate1695 = 4, /*!< Bit Rate 1695 kbit/s (fc/8) */ + FurryHalNfcBitrate3390 = 5, /*!< Bit Rate 3390 kbit/s (fc/4) */ + FurryHalNfcBitrate6780 = 6, /*!< Bit Rate 6780 kbit/s (fc/2) */ + FurryHalNfcBitrate13560 = 7, /*!< Bit Rate 13560 kbit/s (fc) */ + FurryHalNfcBitrate52p97 = 0xEB, /*!< Bit Rate 52.97 kbit/s (fc/256) Fast Mode VICC->VCD */ + FurryHalNfcBitrate26p48 = + 0xEC, /*!< Bit Rate 26,48 kbit/s (fc/512) NFCV VICC->VCD & VCD->VICC 1of4 */ + FurryHalNfcBitrate1p66 = 0xED, /*!< Bit Rate 1,66 kbit/s (fc/8192) NFCV VCD->VICC 1of256 */ + FurryHalNfcBitrateKeep = 0xFF /*!< Value indicating to keep the same previous bit rate */ +} FurryHalNfcBitrate; + +FurryHalNfcReturn furry_hal_nfc_ll_set_mode( + FurryHalNfcMode mode, + FurryHalNfcBitrate txBR, + FurryHalNfcBitrate rxBR); + +#define FURRY_HAL_NFC_LL_GT_NFCA \ + furry_hal_nfc_ll_ms2fc(5U) /*!< GTA Digital 2.0 6.10.4.1 & B.2 */ +#define FURRY_HAL_NFC_LL_GT_NFCB \ + furry_hal_nfc_ll_ms2fc(5U) /*!< GTB Digital 2.0 7.9.4.1 & B.3 */ +#define FURRY_HAL_NFC_LL_GT_NFCF \ + furry_hal_nfc_ll_ms2fc(20U) /*!< GTF Digital 2.0 8.7.4.1 & B.4 */ +#define FURRY_HAL_NFC_LL_GT_NFCV \ + furry_hal_nfc_ll_ms2fc(5U) /*!< GTV Digital 2.0 9.7.5.1 & B.5 */ +#define FURRY_HAL_NFC_LL_GT_PICOPASS furry_hal_nfc_ll_ms2fc(1U) /*!< GT Picopass */ +#define FURRY_HAL_NFC_LL_GT_AP2P furry_hal_nfc_ll_ms2fc(5U) /*!< TIRFG Ecma 340 11.1.1 */ +#define FURRY_HAL_NFC_LL_GT_AP2P_ADJUSTED \ + furry_hal_nfc_ll_ms2fc( \ + 5U + \ + 25U) /*!< Adjusted GT for greater interoperability (Sony XPERIA P, Nokia N9, Huawei P2) */ + +void furry_hal_nfc_ll_set_guard_time(uint32_t cycles); + +typedef enum { + FurryHalNfcErrorHandlingNone = 0, /*!< No special error handling will be performed */ + FurryHalNfcErrorHandlingNfc = 1, /*!< Error handling set to perform as NFC compliant device */ + FurryHalNfcErrorHandlingEmvco = + 2 /*!< Error handling set to perform as EMVCo compliant device */ +} FurryHalNfcErrorHandling; + +void furry_hal_nfc_ll_set_error_handling(FurryHalNfcErrorHandling eHandling); + +/* RFAL Frame Delay Time (FDT) Listen default values */ +#define FURRY_HAL_NFC_LL_FDT_LISTEN_NFCA_POLLER \ + 1172U /*!< FDTA,LISTEN,MIN (n=9) Last bit: Logic "1" - tnn,min/2 Digital 1.1 6.10 ; EMV CCP Spec Book D v2.01 4.8.1.3 */ +#define FURRY_HAL_NFC_LL_FDT_LISTEN_NFCB_POLLER \ + 1008U /*!< TR0B,MIN Digital 1.1 7.1.3 & A.3 ; EMV CCP Spec Book D v2.01 4.8.1.3 & Table A.5 */ +#define FURRY_HAL_NFC_LL_FDT_LISTEN_NFCF_POLLER \ + 2672U /*!< TR0F,LISTEN,MIN Digital 1.1 8.7.1.1 & A.4 */ +#define FURRY_HAL_NFC_LL_FDT_LISTEN_NFCV_POLLER \ + 4310U /*!< FDTV,LISTEN,MIN t1 min Digital 2.1 B.5 ; ISO15693-3 2009 9.1 */ +#define FURRY_HAL_NFC_LL_FDT_LISTEN_PICOPASS_POLLER \ + 3400U /*!< ISO15693 t1 min - observed adjustment */ +#define FURRY_HAL_NFC_LL_FDT_LISTEN_AP2P_POLLER \ + 64U /*!< FDT AP2P No actual FDTListen is required as fields switch and collision avoidance */ +#define FURRY_HAL_NFC_LL_FDT_LISTEN_NFCA_LISTENER 1172U /*!< FDTA,LISTEN,MIN Digital 1.1 6.10 */ +#define FURRY_HAL_NFC_LL_FDT_LISTEN_NFCB_LISTENER \ + 1024U /*!< TR0B,MIN Digital 1.1 7.1.3 & A.3 ; EMV CCP Spec Book D v2.01 4.8.1.3 & Table A.5 */ +#define FURRY_HAL_NFC_LL_FDT_LISTEN_NFCF_LISTENER \ + 2688U /*!< TR0F,LISTEN,MIN Digital 2.1 8.7.1.1 & B.4 */ +#define FURRY_HAL_NFC_LL_FDT_LISTEN_AP2P_LISTENER \ + 64U /*!< FDT AP2P No actual FDTListen exists as fields switch and collision avoidance */ + +void furry_hal_nfc_ll_set_fdt_listen(uint32_t cycles); + +/* RFAL Frame Delay Time (FDT) Poll default values */ +#define FURRY_HAL_NFC_LL_FDT_POLL_NFCA_POLLER \ + 6780U /*!< FDTA,POLL,MIN Digital 1.1 6.10.3.1 & A.2 */ +#define FURRY_HAL_NFC_LL_FDT_POLL_NFCA_T1T_POLLER \ + 384U /*!< RRDDT1T,MIN,B1 Digital 1.1 10.7.1 & A.5 */ +#define FURRY_HAL_NFC_LL_FDT_POLL_NFCB_POLLER \ + 6780U /*!< FDTB,POLL,MIN = TR2B,MIN,DEFAULT Digital 1.1 7.9.3 & A.3 ; EMVCo 3.0 FDTB,PCD,MIN Table A.5 */ +#define FURRY_HAL_NFC_LL_FDT_POLL_NFCF_POLLER \ + 6800U /*!< FDTF,POLL,MIN Digital 2.1 8.7.3 & B.4 */ +#define FURRY_HAL_NFC_LL_FDT_POLL_NFCV_POLLER 4192U /*!< FDTV,POLL Digital 2.1 9.7.3.1 & B.5 */ +#define FURRY_HAL_NFC_LL_FDT_POLL_PICOPASS_POLLER 1790U /*!< FDT Max */ +#define FURRY_HAL_NFC_LL_FDT_POLL_AP2P_POLLER \ + 0U /*!< FDT AP2P No actual FDTPoll exists as fields switch and collision avoidance */ + +void furry_hal_nfc_ll_set_fdt_poll(uint32_t FDTPoll); + +void furry_hal_nfc_ll_txrx_on(); + +void furry_hal_nfc_ll_txrx_off(); + +FurryHalNfcReturn furry_hal_nfc_ll_txrx( + uint8_t* txBuf, + uint16_t txBufLen, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* actLen, + uint32_t flags, + uint32_t fwt); + +FurryHalNfcReturn furry_hal_nfc_ll_txrx_bits( + uint8_t* txBuf, + uint16_t txBufLen, + uint8_t* rxBuf, + uint16_t rxBufLen, + uint16_t* actLen, + uint32_t flags, + uint32_t fwt); + +void furry_hal_nfc_ll_poll(); + +void furry_hal_nfc_field_detect_start(); + +bool furry_hal_nfc_field_is_present(); + +#ifdef __cplusplus +} +#endif diff --git a/esubghz_chat/lib/nfclegacy/nfc_device.c b/esubghz_chat/lib/nfclegacy/nfc_device.c new file mode 100644 index 00000000000..7467dd9355d --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/nfc_device.c @@ -0,0 +1,558 @@ +#include "nfc_device.h" +#include "nfc_types.h" + +#include +#include +#include "protocols/nfc_util.h" +#include + +#define TAG "NfcDevice" +#define NFC_DEVICE_KEYS_FOLDER EXT_PATH("nfc/.cache") +#define NFC_DEVICE_KEYS_EXTENSION ".keys" + +static const char* nfc_file_header = "Flipper NFC device"; +static const uint32_t nfc_file_version = 3; + +// Protocols format versions +static const uint32_t nfc_mifare_ultralight_data_format_version = 1; + +NfcDevice* nfc_device_alloc() { + NfcDevice* nfc_dev = malloc(sizeof(NfcDevice)); + nfc_dev->storage = furi_record_open(RECORD_STORAGE); + nfc_dev->dialogs = furi_record_open(RECORD_DIALOGS); + nfc_dev->load_path = furi_string_alloc(); + nfc_dev->dev_data.parsed_data = furi_string_alloc(); + nfc_dev->folder = furi_string_alloc(); + + return nfc_dev; +} + +void nfc_device_free(NfcDevice* nfc_dev) { + furi_assert(nfc_dev); + nfc_device_clear(nfc_dev); + furi_record_close(RECORD_STORAGE); + furi_record_close(RECORD_DIALOGS); + furi_string_free(nfc_dev->load_path); + if(nfc_dev->dev_data.parsed_data != NULL) { + furi_string_free(nfc_dev->dev_data.parsed_data); + } + furi_string_free(nfc_dev->folder); + free(nfc_dev); +} + +static void nfc_device_prepare_format_string(NfcDevice* dev, FuriString* format_string) { + if(dev->format == NfcDeviceSaveFormatUid) { + furi_string_set(format_string, "UID"); + } else if(dev->format == NfcDeviceSaveFormatBankCard) { + furi_string_set(format_string, "Bank card"); + } else if(dev->format == NfcDeviceSaveFormatMifareUl) { + furi_string_set(format_string, nfc_mf_ul_type(dev->dev_data.mf_ul_data.type, true)); + } else if(dev->format == NfcDeviceSaveFormatMifareClassic) { + furi_string_set(format_string, "Mifare Classic"); + } else if(dev->format == NfcDeviceSaveFormatMifareDesfire) { + furi_string_set(format_string, "Mifare DESFire"); + } else if(dev->format == NfcDeviceSaveFormatNfcV) { + furi_string_set(format_string, "ISO15693"); + } else { + furi_string_set(format_string, "Unknown"); + } +} + +static bool nfc_device_parse_format_string(NfcDevice* dev, FuriString* format_string) { + if(furi_string_start_with_str(format_string, "UID")) { + dev->format = NfcDeviceSaveFormatUid; + dev->dev_data.protocol = NfcDeviceProtocolUnknown; + return true; + } + if(furi_string_start_with_str(format_string, "Bank card")) { + dev->format = NfcDeviceSaveFormatBankCard; + dev->dev_data.protocol = NfcDeviceProtocolEMV; + return true; + } + // Check Mifare Ultralight types + for(MfUltralightType type = MfUltralightTypeUnknown; type < MfUltralightTypeNum; type++) { + if(furi_string_equal(format_string, nfc_mf_ul_type(type, true))) { + dev->format = NfcDeviceSaveFormatMifareUl; + dev->dev_data.protocol = NfcDeviceProtocolMifareUl; + dev->dev_data.mf_ul_data.type = type; + return true; + } + } + if(furi_string_start_with_str(format_string, "Mifare Classic")) { + dev->format = NfcDeviceSaveFormatMifareClassic; + dev->dev_data.protocol = NfcDeviceProtocolMifareClassic; + return true; + } + if(furi_string_start_with_str(format_string, "Mifare DESFire")) { + dev->format = NfcDeviceSaveFormatMifareDesfire; + dev->dev_data.protocol = NfcDeviceProtocolMifareDesfire; + return true; + } + if(furi_string_start_with_str(format_string, "ISO15693")) { + dev->format = NfcDeviceSaveFormatNfcV; + dev->dev_data.protocol = NfcDeviceProtocolNfcV; + return true; + } + return false; +} + +static bool nfc_device_save_mifare_ul_data(FlipperFormat* file, NfcDevice* dev) { + bool saved = false; + MfUltralightData* data = &dev->dev_data.mf_ul_data; + FuriString* temp_str; + temp_str = furi_string_alloc(); + + // Save Mifare Ultralight specific data + do { + if(!flipper_format_write_comment_cstr(file, "Mifare Ultralight specific data")) break; + if(!flipper_format_write_uint32( + file, "Data format version", &nfc_mifare_ultralight_data_format_version, 1)) + break; + if(!flipper_format_write_hex(file, "Signature", data->signature, sizeof(data->signature))) + break; + if(!flipper_format_write_hex( + file, "Mifare version", (uint8_t*)&data->version, sizeof(data->version))) + break; + // Write conters and tearing flags data + bool counters_saved = true; + for(uint8_t i = 0; i < 3; i++) { + furi_string_printf(temp_str, "Counter %d", i); + if(!flipper_format_write_uint32( + file, furi_string_get_cstr(temp_str), &data->counter[i], 1)) { + counters_saved = false; + break; + } + furi_string_printf(temp_str, "Tearing %d", i); + if(!flipper_format_write_hex( + file, furi_string_get_cstr(temp_str), &data->tearing[i], 1)) { + counters_saved = false; + break; + } + } + if(!counters_saved) break; + // Write pages data + uint32_t pages_total = data->data_size / 4; + if(!flipper_format_write_uint32(file, "Pages total", &pages_total, 1)) break; + uint32_t pages_read = data->data_read / 4; + if(!flipper_format_write_uint32(file, "Pages read", &pages_read, 1)) break; + bool pages_saved = true; + for(uint16_t i = 0; i < data->data_size; i += 4) { + furi_string_printf(temp_str, "Page %d", i / 4); + if(!flipper_format_write_hex(file, furi_string_get_cstr(temp_str), &data->data[i], 4)) { + pages_saved = false; + break; + } + } + if(!pages_saved) break; + + // Write authentication counter + uint32_t auth_counter = data->curr_authlim; + if(!flipper_format_write_uint32(file, "Failed authentication attempts", &auth_counter, 1)) + break; + + saved = true; + } while(false); + + furi_string_free(temp_str); + return saved; +} + +bool nfc_device_load_mifare_ul_data(FlipperFormat* file, NfcDevice* dev) { + bool parsed = false; + MfUltralightData* data = &dev->dev_data.mf_ul_data; + FuriString* temp_str; + temp_str = furi_string_alloc(); + uint32_t data_format_version = 0; + + do { + // Read Mifare Ultralight format version + if(!flipper_format_read_uint32(file, "Data format version", &data_format_version, 1)) { + if(!flipper_format_rewind(file)) break; + } + + // Read signature + if(!flipper_format_read_hex(file, "Signature", data->signature, sizeof(data->signature))) + break; + // Read Mifare version + if(!flipper_format_read_hex( + file, "Mifare version", (uint8_t*)&data->version, sizeof(data->version))) + break; + // Read counters and tearing flags + bool counters_parsed = true; + for(uint8_t i = 0; i < 3; i++) { + furi_string_printf(temp_str, "Counter %d", i); + if(!flipper_format_read_uint32( + file, furi_string_get_cstr(temp_str), &data->counter[i], 1)) { + counters_parsed = false; + break; + } + furi_string_printf(temp_str, "Tearing %d", i); + if(!flipper_format_read_hex( + file, furi_string_get_cstr(temp_str), &data->tearing[i], 1)) { + counters_parsed = false; + break; + } + } + if(!counters_parsed) break; + // Read pages + uint32_t pages_total = 0; + if(!flipper_format_read_uint32(file, "Pages total", &pages_total, 1)) break; + uint32_t pages_read = 0; + if(data_format_version < nfc_mifare_ultralight_data_format_version) { + pages_read = pages_total; + } else { + if(!flipper_format_read_uint32(file, "Pages read", &pages_read, 1)) break; + } + data->data_size = pages_total * 4; + data->data_read = pages_read * 4; + if(data->data_size > MF_UL_MAX_DUMP_SIZE || data->data_read > MF_UL_MAX_DUMP_SIZE) break; + bool pages_parsed = true; + for(uint16_t i = 0; i < pages_total; i++) { + furi_string_printf(temp_str, "Page %d", i); + if(!flipper_format_read_hex( + file, furi_string_get_cstr(temp_str), &data->data[i * 4], 4)) { + pages_parsed = false; + break; + } + } + if(!pages_parsed) break; + + // Read authentication counter + uint32_t auth_counter; + if(!flipper_format_read_uint32(file, "Failed authentication attempts", &auth_counter, 1)) + auth_counter = 0; + data->curr_authlim = auth_counter; + + data->auth_success = mf_ul_is_full_capture(data); + + parsed = true; + } while(false); + + furi_string_free(temp_str); + return parsed; +} + +void nfc_device_set_name(NfcDevice* dev, const char* name) { + furi_assert(dev); + + strlcpy(dev->dev_name, name, NFC_DEV_NAME_MAX_LEN); +} + +static void nfc_device_get_path_without_ext(FuriString* orig_path, FuriString* shadow_path) { + // TODO: this won't work if there is ".nfc" anywhere in the path other than + // at the end + size_t ext_start = furi_string_search(orig_path, NFC_APP_FILENAME_EXTENSION); + furi_string_set_n(shadow_path, orig_path, 0, ext_start); +} + +static void nfc_device_get_shadow_path(FuriString* orig_path, FuriString* shadow_path) { + nfc_device_get_path_without_ext(orig_path, shadow_path); + furi_string_cat_printf(shadow_path, "%s", NFC_APP_SHADOW_EXTENSION); +} + +static void nfc_device_get_folder_from_path(FuriString* path, FuriString* folder) { + size_t last_slash = furi_string_search_rchar(path, '/'); + if(last_slash == FURI_STRING_FAILURE) { + // No slashes in the path, treat the whole path as a folder + furi_string_set(folder, path); + } else { + furi_string_set_n(folder, path, 0, last_slash); + } +} + +bool nfc_device_save(NfcDevice* dev, const char* dev_name) { + return false; + furi_assert(dev); + + bool saved = false; + FlipperFormat* file = flipper_format_file_alloc(dev->storage); + FurryHalNfcDevData* data = &dev->dev_data.nfc_data; + FuriString* temp_str; + temp_str = furi_string_alloc(); + + do { + // Create directory if necessary + FuriString* folder = furi_string_alloc(); + // Get folder from filename (filename is in the form of "folder/filename.nfc", so the folder is "folder/") + furi_string_set(temp_str, dev_name); + // Get folder from filename + nfc_device_get_folder_from_path(temp_str, folder); + FURI_LOG_I("Nfc", "Saving to folder %s", furi_string_get_cstr(folder)); + if(!storage_simply_mkdir(dev->storage, furi_string_get_cstr(folder))) { + FURI_LOG_E("Nfc", "Failed to create folder %s", furi_string_get_cstr(folder)); + break; + } + furi_string_free(folder); + // First remove nfc device file if it was saved + // Open file + if(!flipper_format_file_open_always(file, furi_string_get_cstr(temp_str))) break; + // Write header + if(!flipper_format_write_header_cstr(file, nfc_file_header, nfc_file_version)) break; + // Write nfc device type + if(!flipper_format_write_comment_cstr( + file, "Nfc device type can be UID, Mifare Ultralight, Mifare Classic or ISO15693")) + break; + nfc_device_prepare_format_string(dev, temp_str); + if(!flipper_format_write_string(file, "Device type", temp_str)) break; + // Write UID + if(!flipper_format_write_comment_cstr(file, "UID is common for all formats")) break; + if(!flipper_format_write_hex(file, "UID", data->uid, data->uid_len)) break; + + if(dev->format != NfcDeviceSaveFormatNfcV) { + // Write ATQA, SAK + if(!flipper_format_write_comment_cstr(file, "ISO14443 specific fields")) break; + // Save ATQA in MSB order for correct companion apps display + uint8_t atqa[2] = {data->atqa[1], data->atqa[0]}; + if(!flipper_format_write_hex(file, "ATQA", atqa, 2)) break; + if(!flipper_format_write_hex(file, "SAK", &data->sak, 1)) break; + } + + // Save more data if necessary + if(dev->format == NfcDeviceSaveFormatMifareUl) { + if(!nfc_device_save_mifare_ul_data(file, dev)) break; + } + saved = true; + } while(0); + + if(!saved) { //-V547 + dialog_message_show_storage_error(dev->dialogs, "Can not save\nkey file"); + } + furi_string_free(temp_str); + flipper_format_free(file); + return saved; +} + +bool nfc_device_save_shadow(NfcDevice* dev, const char* path) { + return false; + dev->shadow_file_exist = true; + // Replace extension from .nfc to .shd if necessary + FuriString* orig_path = furi_string_alloc(); + furi_string_set_str(orig_path, path); + FuriString* shadow_path = furi_string_alloc(); + nfc_device_get_shadow_path(orig_path, shadow_path); + + bool file_saved = nfc_device_save(dev, furi_string_get_cstr(shadow_path)); + furi_string_free(orig_path); + furi_string_free(shadow_path); + + return file_saved; +} + +static bool nfc_device_load_data(NfcDevice* dev, FuriString* path, bool show_dialog) { + bool parsed = false; + FlipperFormat* file = flipper_format_file_alloc(dev->storage); + FurryHalNfcDevData* data = &dev->dev_data.nfc_data; + uint32_t data_cnt = 0; + FuriString* temp_str; + temp_str = furi_string_alloc(); + bool deprecated_version = false; + + // Version 2 of file format had ATQA bytes swapped + uint32_t version_with_lsb_atqa = 2; + + if(dev->loading_cb) { + dev->loading_cb(dev->loading_cb_ctx, true); + } + + do { + // Check existence of shadow file + nfc_device_get_shadow_path(path, temp_str); + dev->shadow_file_exist = + storage_common_stat(dev->storage, furi_string_get_cstr(temp_str), NULL) == FSE_OK; + // Open shadow file if it exists. If not - open original + if(dev->shadow_file_exist) { + if(!flipper_format_file_open_existing(file, furi_string_get_cstr(temp_str))) break; + } else { + if(!flipper_format_file_open_existing(file, furi_string_get_cstr(path))) break; + } + // Read and verify file header + uint32_t version = 0; + if(!flipper_format_read_header(file, temp_str, &version)) break; + if(furi_string_cmp_str(temp_str, nfc_file_header)) break; + if(version != nfc_file_version) { + if(version < version_with_lsb_atqa) { + deprecated_version = true; + break; + } + } + // Read Nfc device type + if(!flipper_format_read_string(file, "Device type", temp_str)) break; + if(!nfc_device_parse_format_string(dev, temp_str)) break; + // Read and parse UID, ATQA and SAK + if(!flipper_format_get_value_count(file, "UID", &data_cnt)) break; + if(!(data_cnt == 4 || data_cnt == 7 || data_cnt == 8)) break; + data->uid_len = data_cnt; + if(!flipper_format_read_hex(file, "UID", data->uid, data->uid_len)) break; + if(dev->format != NfcDeviceSaveFormatNfcV) { + if(version == version_with_lsb_atqa) { + if(!flipper_format_read_hex(file, "ATQA", data->atqa, 2)) break; + } else { + uint8_t atqa[2] = {}; + if(!flipper_format_read_hex(file, "ATQA", atqa, 2)) break; + data->atqa[0] = atqa[1]; + data->atqa[1] = atqa[0]; + } + if(!flipper_format_read_hex(file, "SAK", &data->sak, 1)) break; + } + // Load CUID + uint8_t* cuid_start = data->uid; + if(data->uid_len == 7) { + cuid_start = &data->uid[3]; + } + data->cuid = (cuid_start[0] << 24) | (cuid_start[1] << 16) | (cuid_start[2] << 8) | + (cuid_start[3]); + // Parse other data + if(dev->format == NfcDeviceSaveFormatMifareUl) { + if(!nfc_device_load_mifare_ul_data(file, dev)) break; + } + parsed = true; + } while(false); + + if(dev->loading_cb) { + dev->loading_cb(dev->loading_cb_ctx, false); + } + + if((!parsed) && (show_dialog)) { + if(deprecated_version) { + dialog_message_show_storage_error(dev->dialogs, "File format deprecated"); + } else { + dialog_message_show_storage_error(dev->dialogs, "Can not parse\nfile"); + } + } + + furi_string_free(temp_str); + flipper_format_free(file); + return parsed; +} + +bool nfc_device_load(NfcDevice* dev, const char* file_path, bool show_dialog) { + furi_assert(dev); + furi_assert(file_path); + + // Load device data + furi_string_set(dev->load_path, file_path); + bool dev_load = nfc_device_load_data(dev, dev->load_path, show_dialog); + if(dev_load) { + // Set device name + FuriString* filename; + filename = furi_string_alloc(); + path_extract_filename_no_ext(file_path, filename); + nfc_device_set_name(dev, furi_string_get_cstr(filename)); + furi_string_free(filename); + } + + return dev_load; +} + +void nfc_device_data_clear(NfcDeviceData* dev_data) { + if(dev_data->protocol == NfcDeviceProtocolMifareUl) { + mf_ul_reset(&dev_data->mf_ul_data); + } + + memset(&dev_data->nfc_data, 0, sizeof(FurryHalNfcDevData)); + dev_data->protocol = NfcDeviceProtocolUnknown; + if(dev_data->parsed_data != NULL) { + furi_string_reset(dev_data->parsed_data); + } +} + +void nfc_device_clear(NfcDevice* dev) { + furi_assert(dev); + + nfc_device_set_name(dev, ""); + nfc_device_data_clear(&dev->dev_data); + dev->format = NfcDeviceSaveFormatUid; + furi_string_reset(dev->load_path); +} + +bool nfc_device_delete(NfcDevice* dev, bool use_load_path) { + furi_assert(dev); + + bool deleted = false; + FuriString* file_path; + file_path = furi_string_alloc(); + + do { + // Delete original file + if(use_load_path && !furi_string_empty(dev->load_path)) { + furi_string_set(file_path, dev->load_path); + } else { + furi_string_printf( + file_path, + "%s/%s%s", + furi_string_get_cstr(dev->folder), + dev->dev_name, + NFC_APP_FILENAME_EXTENSION); + } + if(!storage_simply_remove(dev->storage, furi_string_get_cstr(file_path))) break; + // Delete shadow file if it exists + if(dev->shadow_file_exist) { + if(use_load_path && !furi_string_empty(dev->load_path)) { + nfc_device_get_shadow_path(dev->load_path, file_path); + } else { + furi_string_printf( + file_path, + "%s/%s%s", + furi_string_get_cstr(dev->folder), + dev->dev_name, + NFC_APP_SHADOW_EXTENSION); + } + if(!storage_simply_remove(dev->storage, furi_string_get_cstr(file_path))) break; + } + deleted = true; + } while(0); + + if(!deleted) { + dialog_message_show_storage_error(dev->dialogs, "Can not remove file"); + } + + furi_string_free(file_path); + return deleted; +} + +bool nfc_device_restore(NfcDevice* dev, bool use_load_path) { + furi_assert(dev); + furi_assert(dev->shadow_file_exist); + + bool restored = false; + FuriString* path; + + path = furi_string_alloc(); + + do { + if(use_load_path && !furi_string_empty(dev->load_path)) { + nfc_device_get_shadow_path(dev->load_path, path); + } else { + furi_string_printf( + path, + "%s/%s%s", + furi_string_get_cstr(dev->folder), + dev->dev_name, + NFC_APP_SHADOW_EXTENSION); + } + if(!storage_simply_remove(dev->storage, furi_string_get_cstr(path))) break; + dev->shadow_file_exist = false; + if(use_load_path && !furi_string_empty(dev->load_path)) { + furi_string_set(path, dev->load_path); + } else { + furi_string_printf( + path, + "%s/%s%s", + furi_string_get_cstr(dev->folder), + dev->dev_name, + NFC_APP_FILENAME_EXTENSION); + } + if(!nfc_device_load_data(dev, path, true)) break; + restored = true; + } while(0); + + furi_string_free(path); + return restored; +} + +void nfc_device_set_loading_callback(NfcDevice* dev, NfcLoadingCallback callback, void* context) { + furi_assert(dev); + + dev->loading_cb = callback; + dev->loading_cb_ctx = context; +} diff --git a/esubghz_chat/lib/nfclegacy/nfc_device.h b/esubghz_chat/lib/nfclegacy/nfc_device.h new file mode 100644 index 00000000000..af045bba694 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/nfc_device.h @@ -0,0 +1,111 @@ +#pragma once + +#include +#include +#include +#include + +#include "./furi_hal_nfc.h" +#include "protocols/mifare_ultralight.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define NFC_DEV_NAME_MAX_LEN 22 +#define NFC_READER_DATA_MAX_SIZE 64 +#define NFC_DICT_KEY_BATCH_SIZE 10 + +#define NFC_APP_FILENAME_PREFIX "NFC" +#define NFC_APP_FILENAME_EXTENSION ".nfc" +#define NFC_APP_SHADOW_EXTENSION ".shd" + +typedef void (*NfcLoadingCallback)(void* context, bool state); + +typedef enum { + NfcDeviceProtocolUnknown, + NfcDeviceProtocolEMV, + NfcDeviceProtocolMifareUl, + NfcDeviceProtocolMifareClassic, + NfcDeviceProtocolMifareDesfire, + NfcDeviceProtocolNfcV +} NfcProtocol; + +typedef enum { + NfcDeviceSaveFormatUid, + NfcDeviceSaveFormatBankCard, + NfcDeviceSaveFormatMifareUl, + NfcDeviceSaveFormatMifareClassic, + NfcDeviceSaveFormatMifareDesfire, + NfcDeviceSaveFormatNfcV, +} NfcDeviceSaveFormat; + +typedef struct { + uint8_t data[NFC_READER_DATA_MAX_SIZE]; + uint16_t size; +} NfcReaderRequestData; + +typedef enum { + NfcReadModeAuto, + NfcReadModeMfClassic, + NfcReadModeMfUltralight, + NfcReadModeMfDesfire, + NfcReadModeEMV, + NfcReadModeNFCA, +} NfcReadMode; + +typedef struct { + FurryHalNfcDevData nfc_data; + NfcProtocol protocol; + NfcReadMode read_mode; + union { + NfcReaderRequestData reader_data; + MfUltralightAuth mf_ul_auth; + }; + union { + MfUltralightData mf_ul_data; + }; + FuriString* parsed_data; +} NfcDeviceData; + +typedef struct { + Storage* storage; + DialogsApp* dialogs; + NfcDeviceData dev_data; + char dev_name[NFC_DEV_NAME_MAX_LEN + 1]; + FuriString* load_path; + FuriString* folder; + NfcDeviceSaveFormat format; + bool shadow_file_exist; + + NfcLoadingCallback loading_cb; + void* loading_cb_ctx; +} NfcDevice; + +NfcDevice* nfc_device_alloc(); + +void nfc_device_free(NfcDevice* nfc_dev); + +void nfc_device_set_name(NfcDevice* dev, const char* name); + +bool nfc_device_save(NfcDevice* dev, const char* dev_name); + +bool nfc_device_save_shadow(NfcDevice* dev, const char* dev_name); + +bool nfc_device_load(NfcDevice* dev, const char* file_path, bool show_dialog); + +bool nfc_device_load_key_cache(NfcDevice* dev); + +void nfc_device_data_clear(NfcDeviceData* dev); + +void nfc_device_clear(NfcDevice* dev); + +bool nfc_device_delete(NfcDevice* dev, bool use_load_path); + +bool nfc_device_restore(NfcDevice* dev, bool use_load_path); + +void nfc_device_set_loading_callback(NfcDevice* dev, NfcLoadingCallback callback, void* context); + +#ifdef __cplusplus +} +#endif diff --git a/esubghz_chat/lib/nfclegacy/nfc_types.c b/esubghz_chat/lib/nfclegacy/nfc_types.c new file mode 100644 index 00000000000..40079dc8131 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/nfc_types.c @@ -0,0 +1,57 @@ +#include "nfc_types.h" + +const char* nfc_get_dev_type(FurryHalNfcType type) { + if(type == FurryHalNfcTypeA) { + return "NFC-A"; + } else if(type == FurryHalNfcTypeB) { + return "NFC-B"; + } else if(type == FurryHalNfcTypeF) { + return "NFC-F"; + } else if(type == FurryHalNfcTypeV) { + return "NFC-V"; + } else { + return "Unknown"; + } +} + +const char* nfc_guess_protocol(NfcProtocol protocol) { + if(protocol == NfcDeviceProtocolEMV) { + return "EMV bank card"; + } else if(protocol == NfcDeviceProtocolMifareUl) { + return "Mifare Ultral/NTAG"; + } else if(protocol == NfcDeviceProtocolMifareClassic) { + return "Mifare Classic"; + } else if(protocol == NfcDeviceProtocolMifareDesfire) { + return "Mifare DESFire"; + } else { + return "Unrecognized"; + } +} + +const char* nfc_mf_ul_type(MfUltralightType type, bool full_name) { + if(type == MfUltralightTypeNTAG213) { + return "NTAG213"; + } else if(type == MfUltralightTypeNTAG215) { + return "NTAG215"; + } else if(type == MfUltralightTypeNTAG216) { + return "NTAG216"; + } else if(type == MfUltralightTypeNTAGI2C1K) { + return "NTAG I2C 1K"; + } else if(type == MfUltralightTypeNTAGI2C2K) { + return "NTAG I2C 2K"; + } else if(type == MfUltralightTypeNTAGI2CPlus1K) { + return "NTAG I2C Plus 1K"; + } else if(type == MfUltralightTypeNTAGI2CPlus2K) { + return "NTAG I2C Plus 2K"; + } else if(type == MfUltralightTypeNTAG203) { + return "NTAG203"; + } else if(type == MfUltralightTypeULC) { + return "Mifare Ultralight C"; + } else if(type == MfUltralightTypeUL11 && full_name) { + return "Mifare Ultralight 11"; + } else if(type == MfUltralightTypeUL21 && full_name) { + return "Mifare Ultralight 21"; + } else { + return "Mifare Ultralight"; + } +} diff --git a/esubghz_chat/lib/nfclegacy/nfc_types.h b/esubghz_chat/lib/nfclegacy/nfc_types.h new file mode 100644 index 00000000000..5ccd8aefc13 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/nfc_types.h @@ -0,0 +1,17 @@ +#pragma once + +#include "nfc_device.h" + +#ifdef __cplusplus +extern "C" { +#endif + +const char* nfc_get_dev_type(FurryHalNfcType type); + +const char* nfc_guess_protocol(NfcProtocol protocol); + +const char* nfc_mf_ul_type(MfUltralightType type, bool full_name); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/esubghz_chat/lib/nfclegacy/nfc_worker.c b/esubghz_chat/lib/nfclegacy/nfc_worker.c new file mode 100644 index 00000000000..b80f9aa8645 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/nfc_worker.c @@ -0,0 +1,390 @@ +#include "nfc_worker_i.h" +#include + +#include "ST25RFAL002/platform.h" + +#define TAG "NfcWorker" + +/***************************** NFC Worker API *******************************/ + +NfcWorker* nfc_worker_alloc() { + NfcWorker* nfc_worker = malloc(sizeof(NfcWorker)); + + // Worker thread attributes + nfc_worker->thread = furi_thread_alloc_ex("NfcWorker", 8192, nfc_worker_task, nfc_worker); + + nfc_worker->callback = NULL; + nfc_worker->context = NULL; + nfc_worker->storage = furi_record_open(RECORD_STORAGE); + + // Initialize rfal + while(furry_hal_nfc_is_busy()) { + furi_delay_ms(10); + } + nfc_worker_change_state(nfc_worker, NfcWorkerStateReady); + + return nfc_worker; +} + +void nfc_worker_free(NfcWorker* nfc_worker) { + furi_assert(nfc_worker); + + furi_thread_free(nfc_worker->thread); + + furi_record_close(RECORD_STORAGE); + + free(nfc_worker); +} + +NfcWorkerState nfc_worker_get_state(NfcWorker* nfc_worker) { + return nfc_worker->state; +} + +void nfc_worker_start( + NfcWorker* nfc_worker, + NfcWorkerState state, + NfcDeviceData* dev_data, + NfcWorkerCallback callback, + void* context) { + furi_check(nfc_worker); + //furi_check(dev_data); + while(furry_hal_nfc_is_busy()) { + furi_delay_ms(10); + } + furry_hal_nfc_deinit(); + furry_hal_nfc_init(); + + nfc_worker->callback = callback; + nfc_worker->context = context; + nfc_worker->dev_data = dev_data; + nfc_worker_change_state(nfc_worker, state); + furi_thread_start(nfc_worker->thread); +} + +void nfc_worker_stop(NfcWorker* nfc_worker) { + furi_assert(nfc_worker); + furi_assert(nfc_worker->thread); + if(furi_thread_get_state(nfc_worker->thread) != FuriThreadStateStopped) { + furry_hal_nfc_stop(); + nfc_worker_change_state(nfc_worker, NfcWorkerStateStop); + furi_thread_join(nfc_worker->thread); + } +} + +void nfc_worker_change_state(NfcWorker* nfc_worker, NfcWorkerState state) { + nfc_worker->state = state; +} + +/***************************** NFC Worker Thread *******************************/ + +int32_t nfc_worker_task(void* context) { + NfcWorker* nfc_worker = context; + + furry_hal_nfc_exit_sleep(); + + if(nfc_worker->state == NfcWorkerStateRead) { + if(nfc_worker->dev_data->read_mode == NfcReadModeAuto) { + nfc_worker_read(nfc_worker); + } else { + nfc_worker_read_type(nfc_worker); + } + } else if(nfc_worker->state == NfcWorkerStateUidEmulate) { + nfc_worker_emulate_uid(nfc_worker); + } else if(nfc_worker->state == NfcWorkerStateMfUltralightEmulate) { + nfc_worker_emulate_mf_ultralight(nfc_worker); + } else if(nfc_worker->state == NfcWorkerStateReadMfUltralightReadAuth) { + nfc_worker_mf_ultralight_read_auth(nfc_worker); + } + furry_hal_nfc_sleep(); + nfc_worker_change_state(nfc_worker, NfcWorkerStateReady); + + return 0; +} + +static bool nfc_worker_read_mf_ultralight(NfcWorker* nfc_worker, FurryHalNfcTxRxContext* tx_rx) { + bool read_success = false; + MfUltralightReader reader = {}; + MfUltralightData data = {}; + + do { + furry_hal_nfc_sleep(); + + // Otherwise, try to read as usual + if(!furry_hal_nfc_detect(&nfc_worker->dev_data->nfc_data, 200)) break; + if(!mf_ul_read_card(tx_rx, &reader, &data)) break; + // Copy data + nfc_worker->dev_data->mf_ul_data = data; + read_success = true; + } while(false); + + return read_success; +} + +static bool nfc_worker_read_nfca(NfcWorker* nfc_worker, FurryHalNfcTxRxContext* tx_rx) { + FurryHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; + + bool card_read = false; + furry_hal_nfc_sleep(); + if(mf_ul_check_card_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak)) { + FURI_LOG_I(TAG, "Mifare Ultralight / NTAG detected"); + nfc_worker->dev_data->protocol = NfcDeviceProtocolMifareUl; + card_read = nfc_worker_read_mf_ultralight(nfc_worker, tx_rx); + } else if(nfc_data->interface == FurryHalNfcInterfaceIsoDep) { + FURI_LOG_I(TAG, "ISO14443-4 card detected"); + + nfc_worker->dev_data->protocol = NfcDeviceProtocolUnknown; + + card_read = true; + } else { + nfc_worker->dev_data->protocol = NfcDeviceProtocolUnknown; + card_read = true; + } + + return card_read; +} + +void nfc_worker_read(NfcWorker* nfc_worker) { + furi_assert(nfc_worker); + furi_assert(nfc_worker->callback); + + nfc_device_data_clear(nfc_worker->dev_data); + NfcDeviceData* dev_data = nfc_worker->dev_data; + FurryHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; + FurryHalNfcTxRxContext tx_rx = {}; + NfcWorkerEvent event = 0; + bool card_not_detected_notified = false; + + while(nfc_worker->state == NfcWorkerStateRead) { + if(furry_hal_nfc_detect(nfc_data, 300)) { + // Process first found device + nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context); + card_not_detected_notified = false; + if(nfc_data->type == FurryHalNfcTypeA) { + if(nfc_worker_read_nfca(nfc_worker, &tx_rx)) { + if(dev_data->protocol == NfcDeviceProtocolMifareUl) { + event = NfcWorkerEventReadMfUltralight; + break; + } else if(dev_data->protocol == NfcDeviceProtocolMifareClassic) { + event = NfcWorkerEventReadMfClassicDone; + break; + } else if(dev_data->protocol == NfcDeviceProtocolMifareDesfire) { + event = NfcWorkerEventReadMfDesfire; + break; + } else if(dev_data->protocol == NfcDeviceProtocolEMV) { + event = NfcWorkerEventReadBankCard; + break; + } else if(dev_data->protocol == NfcDeviceProtocolUnknown) { + event = NfcWorkerEventReadUidNfcA; + break; + } + } else { + if(dev_data->protocol == NfcDeviceProtocolMifareClassic) { + event = NfcWorkerEventReadMfClassicDictAttackRequired; + break; + } + } + } else if(nfc_data->type == FurryHalNfcTypeB) { + event = NfcWorkerEventReadUidNfcB; + break; + } else if(nfc_data->type == FurryHalNfcTypeF) { + event = NfcWorkerEventReadUidNfcF; + break; + } + } else { + if(!card_not_detected_notified) { + nfc_worker->callback(NfcWorkerEventNoCardDetected, nfc_worker->context); + card_not_detected_notified = true; + } + } + furry_hal_nfc_sleep(); + furi_delay_ms(100); + } + // Notify caller and exit + if(event > NfcWorkerEventReserved) { + nfc_worker->callback(event, nfc_worker->context); + } +} + +void nfc_worker_read_type(NfcWorker* nfc_worker) { + furi_assert(nfc_worker); + furi_assert(nfc_worker->callback); + + NfcReadMode read_mode = nfc_worker->dev_data->read_mode; + nfc_device_data_clear(nfc_worker->dev_data); + //NfcDeviceData* dev_data = nfc_worker->dev_data; + FurryHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; + FurryHalNfcTxRxContext tx_rx = {}; + NfcWorkerEvent event = 0; + bool card_not_detected_notified = false; + + while(nfc_worker->state == NfcWorkerStateRead) { + if(furry_hal_nfc_detect(nfc_data, 300)) { + FURI_LOG_D(TAG, "Card detected"); + furry_hal_nfc_sleep(); + // Process first found device + nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context); + card_not_detected_notified = false; + if(nfc_data->type == FurryHalNfcTypeA) { + if(read_mode == NfcReadModeMfClassic) { + // none + } else if(read_mode == NfcReadModeMfUltralight) { + FURI_LOG_I(TAG, "Mifare Ultralight / NTAG"); + nfc_worker->dev_data->protocol = NfcDeviceProtocolMifareUl; + if(nfc_worker_read_mf_ultralight(nfc_worker, &tx_rx)) { + event = NfcWorkerEventReadMfUltralight; + break; + } + } else if(read_mode == NfcReadModeNFCA) { + nfc_worker->dev_data->protocol = NfcDeviceProtocolUnknown; + event = NfcWorkerEventReadUidNfcA; + break; + } + } + } else { + if(!card_not_detected_notified) { + nfc_worker->callback(NfcWorkerEventNoCardDetected, nfc_worker->context); + card_not_detected_notified = true; + } + } + furry_hal_nfc_sleep(); + furi_delay_ms(100); + } + // Notify caller and exit + if(event > NfcWorkerEventReserved) { + nfc_worker->callback(event, nfc_worker->context); + } +} + +void nfc_worker_emulate_uid(NfcWorker* nfc_worker) { + FurryHalNfcTxRxContext tx_rx = {}; + FurryHalNfcDevData* data = &nfc_worker->dev_data->nfc_data; + NfcReaderRequestData* reader_data = &nfc_worker->dev_data->reader_data; + + // TODO add support for RATS + // Need to save ATS to support ISO-14443A-4 emulation + + while(nfc_worker->state == NfcWorkerStateUidEmulate) { + if(furry_hal_nfc_listen(data->uid, data->uid_len, data->atqa, data->sak, false, 100)) { + if(furry_hal_nfc_tx_rx(&tx_rx, 100)) { + reader_data->size = tx_rx.rx_bits / 8; + if(reader_data->size > 0) { + memcpy(reader_data->data, tx_rx.rx_data, reader_data->size); + if(nfc_worker->callback) { + nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); + } + } + } else { + FURI_LOG_E(TAG, "Failed to get reader commands"); + } + } + } +} + +void nfc_worker_mf_ultralight_auth_received_callback(MfUltralightAuth auth, void* context) { + furi_assert(context); + + NfcWorker* nfc_worker = context; + nfc_worker->dev_data->mf_ul_auth = auth; + if(nfc_worker->callback) { + nfc_worker->callback(NfcWorkerEventMfUltralightPwdAuth, nfc_worker->context); + } +} + +void nfc_worker_emulate_mf_ultralight(NfcWorker* nfc_worker) { + FurryHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; + MfUltralightEmulator emulator = {}; + mf_ul_prepare_emulation(&emulator, &nfc_worker->dev_data->mf_ul_data); + + // TODO rework with reader analyzer + emulator.auth_received_callback = nfc_worker_mf_ultralight_auth_received_callback; + emulator.context = nfc_worker; + + rfal_platform_spi_acquire(); + + while(nfc_worker->state == NfcWorkerStateMfUltralightEmulate) { + mf_ul_reset_emulation(&emulator, true); + furry_hal_nfc_emulate_nfca( + nfc_data->uid, + nfc_data->uid_len, + nfc_data->atqa, + nfc_data->sak, + mf_ul_prepare_emulation_response, + &emulator, + 5000); + // Check if data was modified + if(emulator.data_changed) { + nfc_worker->dev_data->mf_ul_data = emulator.data; + if(nfc_worker->callback) { + nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); + } + emulator.data_changed = false; + } + } + + rfal_platform_spi_release(); +} + +void nfc_worker_mf_ultralight_read_auth(NfcWorker* nfc_worker) { + furi_assert(nfc_worker); + furi_assert(nfc_worker->callback); + + MfUltralightData* data = &nfc_worker->dev_data->mf_ul_data; + FurryHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; + FurryHalNfcTxRxContext tx_rx = {}; + MfUltralightReader reader = {}; + mf_ul_reset(data); + + uint32_t key = 0; + uint16_t pack = 0; + while(nfc_worker->state == NfcWorkerStateReadMfUltralightReadAuth) { + furry_hal_nfc_sleep(); + if(furry_hal_nfc_detect(nfc_data, 300) && nfc_data->type == FurryHalNfcTypeA) { + if(mf_ul_check_card_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak)) { + nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context); + if(data->auth_method == MfUltralightAuthMethodManual || + data->auth_method == MfUltralightAuthMethodAuto) { + nfc_worker->callback(NfcWorkerEventMfUltralightPassKey, nfc_worker->context); + key = nfc_util_bytes2num(data->auth_key, 4); + } else if(data->auth_method == MfUltralightAuthMethodAmeebo) { + key = mf_ul_pwdgen_amiibo(nfc_data); + } else if(data->auth_method == MfUltralightAuthMethodXiaomi) { + key = mf_ul_pwdgen_xiaomi(nfc_data); + } else { + FURI_LOG_E(TAG, "Incorrect auth method"); + break; + } + + data->auth_success = mf_ultralight_authenticate(&tx_rx, key, &pack); + + if(!data->auth_success) { + // Reset card + furry_hal_nfc_sleep(); + if(!furry_hal_nfc_activate_nfca(300, NULL)) { + nfc_worker->callback(NfcWorkerEventFail, nfc_worker->context); + break; + } + } + + mf_ul_read_card(&tx_rx, &reader, data); + if(data->auth_success) { + MfUltralightConfigPages* config_pages = mf_ultralight_get_config_pages(data); + if(config_pages != NULL) { + config_pages->auth_data.pwd.value = REVERSE_BYTES_U32(key); + config_pages->auth_data.pack.value = pack; + } + nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); + break; + } else { + nfc_worker->callback(NfcWorkerEventFail, nfc_worker->context); + break; + } + } else { + nfc_worker->callback(NfcWorkerEventWrongCardDetected, nfc_worker->context); + furi_delay_ms(10); + } + } else { + nfc_worker->callback(NfcWorkerEventNoCardDetected, nfc_worker->context); + furi_delay_ms(10); + } + } +} diff --git a/esubghz_chat/lib/nfclegacy/nfc_worker.h b/esubghz_chat/lib/nfclegacy/nfc_worker.h new file mode 100644 index 00000000000..7733b791914 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/nfc_worker.h @@ -0,0 +1,109 @@ +#pragma once + +#include "nfc_device.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct NfcWorker NfcWorker; + +typedef enum { + // Init states + NfcWorkerStateNone, + NfcWorkerStateReady, + // Main worker states + NfcWorkerStateRead, + NfcWorkerStateUidEmulate, + NfcWorkerStateMfUltralightEmulate, + NfcWorkerStateMfClassicEmulate, + NfcWorkerStateMfClassicWrite, + NfcWorkerStateMfClassicUpdate, + NfcWorkerStateReadMfUltralightReadAuth, + NfcWorkerStateMfClassicDictAttack, + NfcWorkerStateAnalyzeReader, + NfcWorkerStateNfcVEmulate, + NfcWorkerStateNfcVUnlock, + NfcWorkerStateNfcVUnlockAndSave, + NfcWorkerStateNfcVSniff, + // Debug + NfcWorkerStateEmulateApdu, + NfcWorkerStateField, + // Transition + NfcWorkerStateStop, +} NfcWorkerState; + +typedef enum { + // Reserve first 50 events for application events + NfcWorkerEventReserved = 50, + + // Nfc read events + NfcWorkerEventReadUidNfcB, + NfcWorkerEventReadUidNfcV, + NfcWorkerEventReadUidNfcF, + NfcWorkerEventReadUidNfcA, + NfcWorkerEventReadMfUltralight, + NfcWorkerEventReadMfDesfire, + NfcWorkerEventReadMfClassicDone, + NfcWorkerEventReadMfClassicLoadKeyCache, + NfcWorkerEventReadMfClassicDictAttackRequired, + NfcWorkerEventReadBankCard, + NfcWorkerEventReadNfcV, + + // Nfc worker common events + NfcWorkerEventSuccess, + NfcWorkerEventFail, + NfcWorkerEventAborted, + NfcWorkerEventCardDetected, + NfcWorkerEventNoCardDetected, + NfcWorkerEventWrongCardDetected, + + // Read Mifare Classic events + NfcWorkerEventNoDictFound, + NfcWorkerEventNewSector, + NfcWorkerEventNewDictKeyBatch, + NfcWorkerEventFoundKeyA, + NfcWorkerEventFoundKeyB, + NfcWorkerEventKeyAttackStart, + NfcWorkerEventKeyAttackStop, + NfcWorkerEventKeyAttackNextSector, + + // Write Mifare Classic events + NfcWorkerEventWrongCard, + + // Detect Reader events + NfcWorkerEventDetectReaderDetected, + NfcWorkerEventDetectReaderLost, + NfcWorkerEventDetectReaderMfkeyCollected, + + // Mifare Ultralight events + NfcWorkerEventMfUltralightPassKey, // NFC worker requesting manual key + NfcWorkerEventMfUltralightPwdAuth, // Reader sent auth command + NfcWorkerEventNfcVPassKey, // NFC worker requesting manual key + NfcWorkerEventNfcVCommandExecuted, + NfcWorkerEventNfcVContentChanged, +} NfcWorkerEvent; + +typedef bool (*NfcWorkerCallback)(NfcWorkerEvent event, void* context); + +NfcWorker* nfc_worker_alloc(); + +NfcWorkerState nfc_worker_get_state(NfcWorker* nfc_worker); + +void nfc_worker_free(NfcWorker* nfc_worker); + +void nfc_worker_start( + NfcWorker* nfc_worker, + NfcWorkerState state, + NfcDeviceData* dev_data, + NfcWorkerCallback callback, + void* context); + +void nfc_worker_stop(NfcWorker* nfc_worker); +void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker); +void nfc_worker_nfcv_emulate(NfcWorker* nfc_worker); +void nfc_worker_nfcv_sniff(NfcWorker* nfc_worker); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/esubghz_chat/lib/nfclegacy/nfc_worker_i.h b/esubghz_chat/lib/nfclegacy/nfc_worker_i.h new file mode 100644 index 00000000000..0b74c10703b --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/nfc_worker_i.h @@ -0,0 +1,52 @@ +#pragma once + +#include "nfc_worker.h" + +#include +#include + +#include "protocols/nfc_util.h" +#include "protocols/mifare_common.h" +#include "protocols/mifare_ultralight.h" +#include "protocols/nfca.h" + +struct NfcWorker { + FuriThread* thread; + Storage* storage; + Stream* dict_stream; + + NfcDeviceData* dev_data; + + NfcWorkerCallback callback; + void* context; + + NfcWorkerState state; +}; + +void nfc_worker_change_state(NfcWorker* nfc_worker, NfcWorkerState state); + +int32_t nfc_worker_task(void* context); + +void nfc_worker_read(NfcWorker* nfc_worker); + +void nfc_worker_read_type(NfcWorker* nfc_worker); + +void nfc_worker_emulate_uid(NfcWorker* nfc_worker); + +void nfc_worker_emulate_mf_ultralight(NfcWorker* nfc_worker); + +void nfc_worker_emulate_mf_classic(NfcWorker* nfc_worker); + +void nfc_worker_write_mf_classic(NfcWorker* nfc_worker); + +void nfc_worker_update_mf_classic(NfcWorker* nfc_worker); + +void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker); + +void nfc_worker_mf_ultralight_read_auth(NfcWorker* nfc_worker); + +void nfc_worker_mf_ul_auth_attack(NfcWorker* nfc_worker); + +void nfc_worker_emulate_apdu(NfcWorker* nfc_worker); + +void nfc_worker_analyze_reader(NfcWorker* nfc_worker); diff --git a/esubghz_chat/lib/nfclegacy/protocols/crypto1.c b/esubghz_chat/lib/nfclegacy/protocols/crypto1.c new file mode 100644 index 00000000000..f59651cf45f --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/protocols/crypto1.c @@ -0,0 +1,128 @@ +#include "crypto1.h" +#include "nfc_util.h" +#include + +// Algorithm from https://github.com/RfidResearchGroup/proxmark3.git + +#define SWAPENDIAN(x) \ + ((x) = ((x) >> 8 & 0xff00ff) | ((x)&0xff00ff) << 8, (x) = (x) >> 16 | (x) << 16) +#define LF_POLY_ODD (0x29CE5C) +#define LF_POLY_EVEN (0x870804) + +#define BEBIT(x, n) FURI_BIT(x, (n) ^ 24) + +void crypto1_reset(Crypto1* crypto1) { + furi_assert(crypto1); + crypto1->even = 0; + crypto1->odd = 0; +} + +void crypto1_init(Crypto1* crypto1, uint64_t key) { + furi_assert(crypto1); + crypto1->even = 0; + crypto1->odd = 0; + for(int8_t i = 47; i > 0; i -= 2) { + crypto1->odd = crypto1->odd << 1 | FURI_BIT(key, (i - 1) ^ 7); + crypto1->even = crypto1->even << 1 | FURI_BIT(key, i ^ 7); + } +} + +uint32_t crypto1_filter(uint32_t in) { + uint32_t out = 0; + out = 0xf22c0 >> (in & 0xf) & 16; + out |= 0x6c9c0 >> (in >> 4 & 0xf) & 8; + out |= 0x3c8b0 >> (in >> 8 & 0xf) & 4; + out |= 0x1e458 >> (in >> 12 & 0xf) & 2; + out |= 0x0d938 >> (in >> 16 & 0xf) & 1; + return FURI_BIT(0xEC57E80A, out); +} + +uint8_t crypto1_bit(Crypto1* crypto1, uint8_t in, int is_encrypted) { + furi_assert(crypto1); + uint8_t out = crypto1_filter(crypto1->odd); + uint32_t feed = out & (!!is_encrypted); + feed ^= !!in; + feed ^= LF_POLY_ODD & crypto1->odd; + feed ^= LF_POLY_EVEN & crypto1->even; + crypto1->even = crypto1->even << 1 | (nfc_util_even_parity32(feed)); + + FURI_SWAP(crypto1->odd, crypto1->even); + return out; +} + +uint8_t crypto1_byte(Crypto1* crypto1, uint8_t in, int is_encrypted) { + furi_assert(crypto1); + uint8_t out = 0; + for(uint8_t i = 0; i < 8; i++) { + out |= crypto1_bit(crypto1, FURI_BIT(in, i), is_encrypted) << i; + } + return out; +} + +uint32_t crypto1_word(Crypto1* crypto1, uint32_t in, int is_encrypted) { + furi_assert(crypto1); + uint32_t out = 0; + for(uint8_t i = 0; i < 32; i++) { + out |= crypto1_bit(crypto1, BEBIT(in, i), is_encrypted) << (24 ^ i); + } + return out; +} + +uint32_t prng_successor(uint32_t x, uint32_t n) { + SWAPENDIAN(x); + while(n--) x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31; + + return SWAPENDIAN(x); +} + +void crypto1_decrypt( + Crypto1* crypto, + uint8_t* encrypted_data, + uint16_t encrypted_data_bits, + uint8_t* decrypted_data) { + furi_assert(crypto); + furi_assert(encrypted_data); + furi_assert(decrypted_data); + + if(encrypted_data_bits < 8) { + uint8_t decrypted_byte = 0; + decrypted_byte |= (crypto1_bit(crypto, 0, 0) ^ FURI_BIT(encrypted_data[0], 0)) << 0; + decrypted_byte |= (crypto1_bit(crypto, 0, 0) ^ FURI_BIT(encrypted_data[0], 1)) << 1; + decrypted_byte |= (crypto1_bit(crypto, 0, 0) ^ FURI_BIT(encrypted_data[0], 2)) << 2; + decrypted_byte |= (crypto1_bit(crypto, 0, 0) ^ FURI_BIT(encrypted_data[0], 3)) << 3; + decrypted_data[0] = decrypted_byte; + } else { + for(size_t i = 0; i < encrypted_data_bits / 8; i++) { + decrypted_data[i] = crypto1_byte(crypto, 0, 0) ^ encrypted_data[i]; + } + } +} + +void crypto1_encrypt( + Crypto1* crypto, + uint8_t* keystream, + uint8_t* plain_data, + uint16_t plain_data_bits, + uint8_t* encrypted_data, + uint8_t* encrypted_parity) { + furi_assert(crypto); + furi_assert(plain_data); + furi_assert(encrypted_data); + furi_assert(encrypted_parity); + + if(plain_data_bits < 8) { + encrypted_data[0] = 0; + for(size_t i = 0; i < plain_data_bits; i++) { + encrypted_data[0] |= (crypto1_bit(crypto, 0, 0) ^ FURI_BIT(plain_data[0], i)) << i; + } + } else { + memset(encrypted_parity, 0, plain_data_bits / 8 + 1); + for(uint8_t i = 0; i < plain_data_bits / 8; i++) { + encrypted_data[i] = crypto1_byte(crypto, keystream ? keystream[i] : 0, 0) ^ + plain_data[i]; + encrypted_parity[i / 8] |= + (((crypto1_filter(crypto->odd) ^ nfc_util_odd_parity8(plain_data[i])) & 0x01) + << (7 - (i & 0x0007))); + } + } +} diff --git a/esubghz_chat/lib/nfclegacy/protocols/crypto1.h b/esubghz_chat/lib/nfclegacy/protocols/crypto1.h new file mode 100644 index 00000000000..bbf6dc239ce --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/protocols/crypto1.h @@ -0,0 +1,45 @@ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + uint32_t odd; + uint32_t even; +} Crypto1; + +void crypto1_reset(Crypto1* crypto1); + +void crypto1_init(Crypto1* crypto1, uint64_t key); + +uint8_t crypto1_bit(Crypto1* crypto1, uint8_t in, int is_encrypted); + +uint8_t crypto1_byte(Crypto1* crypto1, uint8_t in, int is_encrypted); + +uint32_t crypto1_word(Crypto1* crypto1, uint32_t in, int is_encrypted); + +uint32_t crypto1_filter(uint32_t in); + +uint32_t prng_successor(uint32_t x, uint32_t n); + +void crypto1_decrypt( + Crypto1* crypto, + uint8_t* encrypted_data, + uint16_t encrypted_data_bits, + uint8_t* decrypted_data); + +void crypto1_encrypt( + Crypto1* crypto, + uint8_t* keystream, + uint8_t* plain_data, + uint16_t plain_data_bits, + uint8_t* encrypted_data, + uint8_t* encrypted_parity); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/esubghz_chat/lib/nfclegacy/protocols/mifare_common.c b/esubghz_chat/lib/nfclegacy/protocols/mifare_common.c new file mode 100644 index 00000000000..5277cc8cd16 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/protocols/mifare_common.c @@ -0,0 +1,19 @@ +#include "mifare_common.h" + +MifareType mifare_common_get_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) { + MifareType type = MifareTypeUnknown; + + if((ATQA0 == 0x44) && (ATQA1 == 0x00) && (SAK == 0x00)) { + type = MifareTypeUltralight; + } else if( + ((ATQA0 == 0x44 || ATQA0 == 0x04) && + (SAK == 0x08 || SAK == 0x88 || SAK == 0x09 || SAK == 0x89)) || + ((ATQA0 == 0x42 || ATQA0 == 0x02) && (SAK == 0x18)) || + ((ATQA0 == 0x01) && (ATQA1 == 0x0F) && (SAK == 0x01))) { + type = MifareTypeClassic; + } else if(ATQA0 == 0x44 && ATQA1 == 0x03 && SAK == 0x20) { + type = MifareTypeDesfire; + } + + return type; +} diff --git a/esubghz_chat/lib/nfclegacy/protocols/mifare_common.h b/esubghz_chat/lib/nfclegacy/protocols/mifare_common.h new file mode 100644 index 00000000000..2b694d9068a --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/protocols/mifare_common.h @@ -0,0 +1,12 @@ +#pragma once + +#include + +typedef enum { + MifareTypeUnknown, + MifareTypeUltralight, + MifareTypeClassic, + MifareTypeDesfire, +} MifareType; + +MifareType mifare_common_get_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK); diff --git a/mifare_nested/lib/nfclegacy/protocols/mifare_ultralight.c b/esubghz_chat/lib/nfclegacy/protocols/mifare_ultralight.c similarity index 100% rename from mifare_nested/lib/nfclegacy/protocols/mifare_ultralight.c rename to esubghz_chat/lib/nfclegacy/protocols/mifare_ultralight.c diff --git a/mifare_nested/lib/nfclegacy/protocols/mifare_ultralight.h b/esubghz_chat/lib/nfclegacy/protocols/mifare_ultralight.h similarity index 100% rename from mifare_nested/lib/nfclegacy/protocols/mifare_ultralight.h rename to esubghz_chat/lib/nfclegacy/protocols/mifare_ultralight.h diff --git a/esubghz_chat/lib/nfclegacy/protocols/nfc_util.c b/esubghz_chat/lib/nfclegacy/protocols/nfc_util.c new file mode 100644 index 00000000000..8cb6d57f218 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/protocols/nfc_util.c @@ -0,0 +1,70 @@ +#include "nfc_util.h" + +#include + +static const uint8_t nfc_util_odd_byte_parity[256] = { + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, + 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, + 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, + 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, + 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, + 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, + 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1}; + +void nfc_util_num2bytes(uint64_t src, uint8_t len, uint8_t* dest) { + furi_assert(dest); + furi_assert(len <= 8); + + while(len--) { + dest[len] = (uint8_t)src; + src >>= 8; + } +} + +uint64_t nfc_util_bytes2num(const uint8_t* src, uint8_t len) { + furi_assert(src); + furi_assert(len <= 8); + + uint64_t res = 0; + while(len--) { + res = (res << 8) | (*src); + src++; + } + return res; +} + +uint8_t nfc_util_even_parity32(uint32_t data) { + // data ^= data >> 16; + // data ^= data >> 8; + // return !nfc_util_odd_byte_parity[data]; + return (__builtin_parity(data) & 0xFF); +} + +uint8_t nfc_util_odd_parity8(uint8_t data) { + return nfc_util_odd_byte_parity[data]; +} + +void nfc_util_odd_parity(const uint8_t* src, uint8_t* dst, uint8_t len) { + furi_assert(src); + furi_assert(dst); + + uint8_t parity = 0; + uint8_t bit = 0; + while(len--) { + parity |= nfc_util_odd_parity8(*src) << (7 - bit); // parity is MSB first + bit++; + if(bit == 8) { + *dst = parity; + dst++; + parity = 0; + bit = 0; + } + src++; + } + + if(bit) { + *dst = parity; + } +} \ No newline at end of file diff --git a/esubghz_chat/lib/nfclegacy/protocols/nfc_util.h b/esubghz_chat/lib/nfclegacy/protocols/nfc_util.h new file mode 100644 index 00000000000..a9d5a3f8ab0 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/protocols/nfc_util.h @@ -0,0 +1,21 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void nfc_util_num2bytes(uint64_t src, uint8_t len, uint8_t* dest); + +uint64_t nfc_util_bytes2num(const uint8_t* src, uint8_t len); + +uint8_t nfc_util_even_parity32(uint32_t data); + +uint8_t nfc_util_odd_parity8(uint8_t data); + +void nfc_util_odd_parity(const uint8_t* src, uint8_t* dst, uint8_t len); + +#ifdef __cplusplus +} +#endif diff --git a/esubghz_chat/lib/nfclegacy/protocols/nfca.c b/esubghz_chat/lib/nfclegacy/protocols/nfca.c new file mode 100644 index 00000000000..ab4f3f23c60 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/protocols/nfca.c @@ -0,0 +1,140 @@ +#include "nfca.h" +#include +#include +#include + +#define NFCA_CRC_INIT (0x6363) + +#define NFCA_F_SIG (13560000.0) +#define T_SIG 7374 //73.746ns*100 +#define T_SIG_x8 58992 //T_SIG*8 +#define T_SIG_x8_x8 471936 //T_SIG*8*8 +#define T_SIG_x8_x9 530928 //T_SIG*8*9 + +#define NFCA_SIGNAL_MAX_EDGES (1350) + +typedef struct { + uint8_t cmd; + uint8_t param; +} nfca_cmd_rats; + +static uint8_t nfca_default_ats[] = {0x05, 0x78, 0x80, 0x80, 0x00}; + +static uint8_t nfca_halt_req[] = {NFCA_CMD_HALT, 0x00}; + +uint16_t nfca_get_crc16(uint8_t* buff, uint16_t len) { + uint16_t crc = NFCA_CRC_INIT; + uint8_t byte = 0; + + for(uint8_t i = 0; i < len; i++) { + byte = buff[i]; + byte ^= (uint8_t)(crc & 0xff); + byte ^= byte << 4; + crc = (crc >> 8) ^ (((uint16_t)byte) << 8) ^ (((uint16_t)byte) << 3) ^ + (((uint16_t)byte) >> 4); + } + + return crc; +} + +void nfca_append_crc16(uint8_t* buff, uint16_t len) { + uint16_t crc = nfca_get_crc16(buff, len); + buff[len] = (uint8_t)crc; + buff[len + 1] = (uint8_t)(crc >> 8); +} + +bool nfca_emulation_handler( + uint8_t* buff_rx, + uint16_t buff_rx_len, + uint8_t* buff_tx, + uint16_t* buff_tx_len) { + bool halt = false; + uint8_t rx_bytes = buff_rx_len / 8; + + if(rx_bytes == sizeof(nfca_halt_req) && !memcmp(buff_rx, nfca_halt_req, rx_bytes)) { + halt = true; + } else if(rx_bytes == sizeof(nfca_cmd_rats) && buff_rx[0] == NFCA_CMD_RATS) { + memcpy(buff_tx, nfca_default_ats, sizeof(nfca_default_ats)); + *buff_tx_len = sizeof(nfca_default_ats) * 8; + } + + return halt; +} + +static void nfca_add_bit(DigitalSignal* signal, bool bit) { + if(bit) { + signal->start_level = true; + for(size_t i = 0; i < 7; i++) { + signal->edge_timings[i] = T_SIG_x8; + } + signal->edge_timings[7] = T_SIG_x8_x9; + signal->edge_cnt = 8; + } else { + signal->start_level = false; + signal->edge_timings[0] = T_SIG_x8_x8; + for(size_t i = 1; i < 9; i++) { + signal->edge_timings[i] = T_SIG_x8; + } + signal->edge_cnt = 9; + } +} + +static void nfca_add_byte(NfcaSignal* nfca_signal, uint8_t byte, bool parity) { + for(uint8_t i = 0; i < 8; i++) { + if(byte & (1 << i)) { + digital_signal_append(nfca_signal->tx_signal, nfca_signal->one); + } else { + digital_signal_append(nfca_signal->tx_signal, nfca_signal->zero); + } + } + if(parity) { + digital_signal_append(nfca_signal->tx_signal, nfca_signal->one); + } else { + digital_signal_append(nfca_signal->tx_signal, nfca_signal->zero); + } +} + +NfcaSignal* nfca_signal_alloc() { + NfcaSignal* nfca_signal = malloc(sizeof(NfcaSignal)); + nfca_signal->one = digital_signal_alloc(10); + nfca_signal->zero = digital_signal_alloc(10); + nfca_add_bit(nfca_signal->one, true); + nfca_add_bit(nfca_signal->zero, false); + nfca_signal->tx_signal = digital_signal_alloc(NFCA_SIGNAL_MAX_EDGES); + + return nfca_signal; +} + +void nfca_signal_free(NfcaSignal* nfca_signal) { + furi_assert(nfca_signal); + + digital_signal_free(nfca_signal->one); + digital_signal_free(nfca_signal->zero); + digital_signal_free(nfca_signal->tx_signal); + free(nfca_signal); +} + +void nfca_signal_encode(NfcaSignal* nfca_signal, uint8_t* data, uint16_t bits, uint8_t* parity) { + furi_assert(nfca_signal); + furi_assert(data); + furi_assert(parity); + + nfca_signal->tx_signal->edge_cnt = 0; + nfca_signal->tx_signal->start_level = true; + // Start of frame + digital_signal_append(nfca_signal->tx_signal, nfca_signal->one); + + if(bits < 8) { + for(size_t i = 0; i < bits; i++) { + if(FURI_BIT(data[0], i)) { + digital_signal_append(nfca_signal->tx_signal, nfca_signal->one); + } else { + digital_signal_append(nfca_signal->tx_signal, nfca_signal->zero); + } + } + } else { + for(size_t i = 0; i < bits / 8; i++) { + nfca_add_byte(nfca_signal, data[i], parity[i / 8] & (1 << (7 - (i & 0x07)))); + } + } +} diff --git a/esubghz_chat/lib/nfclegacy/protocols/nfca.h b/esubghz_chat/lib/nfclegacy/protocols/nfca.h new file mode 100644 index 00000000000..f69d66ef282 --- /dev/null +++ b/esubghz_chat/lib/nfclegacy/protocols/nfca.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include + +#include "../digital_signal/digital_signal.h" + +#define NFCA_CMD_RATS (0xE0U) +#define NFCA_CMD_HALT (0x50U) + +typedef struct { + DigitalSignal* one; + DigitalSignal* zero; + DigitalSignal* tx_signal; +} NfcaSignal; + +uint16_t nfca_get_crc16(uint8_t* buff, uint16_t len); + +void nfca_append_crc16(uint8_t* buff, uint16_t len); + +bool nfca_emulation_handler( + uint8_t* buff_rx, + uint16_t buff_rx_len, + uint8_t* buff_tx, + uint16_t* buff_tx_len); + +NfcaSignal* nfca_signal_alloc(); + +void nfca_signal_free(NfcaSignal* nfca_signal); + +void nfca_signal_encode(NfcaSignal* nfca_signal, uint8_t* data, uint16_t bits, uint8_t* parity); diff --git a/esubghz_chat/lib/parity/parity.c b/esubghz_chat/lib/parity/parity.c new file mode 100644 index 00000000000..c8e2f807e4f --- /dev/null +++ b/esubghz_chat/lib/parity/parity.c @@ -0,0 +1,71 @@ +#include "parity.h" + +uint32_t __paritysi2(uint32_t a) { + uint32_t x = (uint32_t)a; + x ^= x >> 16; + x ^= x >> 8; + x ^= x >> 4; + return (0x6996 >> (x & 0xF)) & 1; +} + +static const uint8_t g_odd_byte_parity[256] = { + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, + 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, + 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, + 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, + 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, + 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, + 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1}; + +#define ODD_PARITY8(x) \ + { g_odd_byte_parity[x] } +#define EVEN_PARITY8(x) \ + { !g_odd_byte_parity[x] } + +uint8_t oddparity8(const uint8_t x) { + return g_odd_byte_parity[x]; +} + +uint8_t evenparity8(const uint8_t x) { + return !g_odd_byte_parity[x]; +} + +uint8_t evenparity16(uint16_t x) { +#if !defined __GNUC__ + x ^= x >> 8; + return EVEN_PARITY8(x); +#else + return (__builtin_parity(x) & 0xFF); +#endif +} + +uint8_t oddparity16(uint16_t x) { +#if !defined __GNUC__ + x ^= x >> 8; + return ODD_PARITY8(x); +#else + return !__builtin_parity(x); +#endif +} + +uint8_t evenparity32(uint32_t x) { +#if !defined __GNUC__ + x ^= x >> 16; + x ^= x >> 8; + return EVEN_PARITY8(x); +#else + return (__builtin_parity(x) & 0xFF); +#endif +} + +uint8_t oddparity32(uint32_t x) { +#if !defined __GNUC__ + x ^= x >> 16; + x ^= x >> 8; + return ODD_PARITY8(x); +#else + return !__builtin_parity(x); +#endif +} \ No newline at end of file diff --git a/esubghz_chat/lib/parity/parity.h b/esubghz_chat/lib/parity/parity.h new file mode 100644 index 00000000000..16648afa15d --- /dev/null +++ b/esubghz_chat/lib/parity/parity.h @@ -0,0 +1,10 @@ +#include "stdint.h" + +uint8_t oddparity8(const uint8_t x); +uint8_t evenparity8(const uint8_t x); + +uint8_t evenparity16(uint16_t x); +uint8_t oddparity16(uint16_t x); + +uint8_t evenparity32(uint32_t x); +uint8_t oddparity32(uint32_t x); \ No newline at end of file diff --git a/esubghz_chat/scenes/esubghz_chat_key_display.c b/esubghz_chat/scenes/esubghz_chat_key_display.c index fe0428ebb9d..9394d480f3c 100644 --- a/esubghz_chat/scenes/esubghz_chat_key_display.c +++ b/esubghz_chat/scenes/esubghz_chat_key_display.c @@ -88,7 +88,7 @@ void scene_on_enter_key_display(void* context) { dialog_ex_set_left_button_text(state->key_display, "Back"); if(state->encrypted) { - // dialog_ex_set_center_button_text(state->key_display, "Share"); + dialog_ex_set_center_button_text(state->key_display, "Share"); } dialog_ex_set_result_callback(state->key_display, key_display_result_cb); @@ -119,11 +119,11 @@ bool scene_on_event_key_display(void* context, SceneManagerEvent event) { consumed = true; break; - /* open key sharing popup */ - // case ESubGhzChatEvent_KeyDisplayShare: - // scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_KeySharePopup); - // consumed = true; - // break; + /* open key sharing popup */ + case ESubGhzChatEvent_KeyDisplayShare: + scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_KeySharePopup); + consumed = true; + break; } break; diff --git a/esubghz_chat/scenes/esubghz_chat_key_menu.c b/esubghz_chat/scenes/esubghz_chat_key_menu.c index 533aa3b9d34..cd1269ee13e 100644 --- a/esubghz_chat/scenes/esubghz_chat_key_menu.c +++ b/esubghz_chat/scenes/esubghz_chat_key_menu.c @@ -5,7 +5,7 @@ typedef enum { ESubGhzChatKeyMenuItems_Password, ESubGhzChatKeyMenuItems_HexKey, ESubGhzChatKeyMenuItems_GenKey, - // ESubGhzChatKeyMenuItems_ReadKeyFromNfc, + ESubGhzChatKeyMenuItems_ReadKeyFromNfc, } ESubGhzChatKeyMenuItems; static void key_menu_cb(void* context, uint32_t index) { @@ -52,10 +52,10 @@ static void key_menu_cb(void* context, uint32_t index) { view_dispatcher_send_custom_event(state->view_dispatcher, ESubGhzChatEvent_KeyMenuGenKey); break; - // case ESubGhzChatKeyMenuItems_ReadKeyFromNfc: - // view_dispatcher_send_custom_event( - // state->view_dispatcher, ESubGhzChatEvent_KeyMenuReadKeyFromNfc); - // break; + case ESubGhzChatKeyMenuItems_ReadKeyFromNfc: + view_dispatcher_send_custom_event( + state->view_dispatcher, ESubGhzChatEvent_KeyMenuReadKeyFromNfc); + break; default: break; @@ -98,13 +98,13 @@ void scene_on_enter_key_menu(void* context) { ESubGhzChatKeyMenuItems_GenKey, key_menu_cb, state); - // menu_add_item( - // state->menu, - // "Read Key from NFC", - // &I_Nfc_14px, - // ESubGhzChatKeyMenuItems_ReadKeyFromNfc, - // key_menu_cb, - // state); + menu_add_item( + state->menu, + "Read Key from NFC", + &I_Nfc_14px, + ESubGhzChatKeyMenuItems_ReadKeyFromNfc, + key_menu_cb, + state); view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_Menu); } @@ -140,11 +140,11 @@ bool scene_on_event_key_menu(void* context, SceneManagerEvent event) { consumed = true; break; - /* switch to hex key read scene */ - // case ESubGhzChatEvent_KeyMenuReadKeyFromNfc: - // scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_KeyReadPopup); - // consumed = true; - // break; + /* switch to hex key read scene */ + case ESubGhzChatEvent_KeyMenuReadKeyFromNfc: + scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_KeyReadPopup); + consumed = true; + break; } break; diff --git a/esubghz_chat/scenes/esubghz_chat_key_read_popup.c b/esubghz_chat/scenes/esubghz_chat_key_read_popup.c index d9d784a74e5..31d13a5f85c 100644 --- a/esubghz_chat/scenes/esubghz_chat_key_read_popup.c +++ b/esubghz_chat/scenes/esubghz_chat_key_read_popup.c @@ -1,273 +1,268 @@ -// #include "../esubghz_chat_i.h" -// #include "../helpers/nfc_helpers.h" - -// typedef enum { -// KeyReadPopupState_Idle, -// KeyReadPopupState_Detecting, -// KeyReadPopupState_Reading, -// KeyReadPopupState_Fail, -// KeyReadPopupState_Success, -// } KeyReadPopupState; - -// static bool read_worker_cb(NfcWorkerEvent event, void* context) { -// furi_assert(context); -// ESubGhzChatState* state = context; - -// view_dispatcher_send_custom_event(state->view_dispatcher, event); - -// return true; -// } - -// static void key_read_popup_timeout_cb(void* context) { -// furi_assert(context); -// ESubGhzChatState* state = context; - -// uint32_t cur_state = -// scene_manager_get_scene_state(state->scene_manager, ESubGhzChatScene_KeyReadPopup); - -// /* done displaying our failure */ -// if(cur_state == KeyReadPopupState_Fail) { -// view_dispatcher_send_custom_event( -// state->view_dispatcher, ESubGhzChatEvent_KeyReadPopupFailed); -// /* done displaying our success */ -// } else if(cur_state == KeyReadPopupState_Success) { -// view_dispatcher_send_custom_event( -// state->view_dispatcher, ESubGhzChatEvent_KeyReadPopupSucceeded); -// } -// } - -// struct ReplayDictNfcReaderContext { -// uint8_t* cur; -// uint8_t* max; -// }; - -// static bool replay_dict_nfc_reader(uint64_t* run_id, uint32_t* counter, void* context) { -// struct ReplayDictNfcReaderContext* ctx = (struct ReplayDictNfcReaderContext*)context; - -// if(ctx->cur + sizeof(struct ReplayDictNfcEntry) > ctx->max) { -// return false; -// } - -// struct ReplayDictNfcEntry* entry = (struct ReplayDictNfcEntry*)ctx->cur; -// *run_id = entry->run_id; -// *counter = __ntohl(entry->counter); - -// ctx->cur += sizeof(struct ReplayDictNfcEntry); - -// return true; -// } - -// static bool key_read_popup_handle_key_read(ESubGhzChatState* state) { -// NfcDeviceData* dev_data = state->nfc_dev_data; - -// /* check for config pages */ -// if(dev_data->mf_ul_data.data_read < NFC_CONFIG_PAGES * 4) { -// return false; -// } - -// size_t data_read = dev_data->mf_ul_data.data_read - (NFC_CONFIG_PAGES * 4); - -// /* check if key was transmitted */ -// if(data_read < KEY_BITS / 8) { -// return false; -// } - -// /* initiate the crypto context */ -// bool ret = crypto_ctx_set_key( -// state->crypto_ctx, dev_data->mf_ul_data.data, state->name_prefix, furi_get_tick()); - -// /* cleanup */ -// crypto_explicit_bzero(dev_data->mf_ul_data.data, KEY_BITS / 8); - -// if(!ret) { -// crypto_ctx_clear(state->crypto_ctx); -// return false; -// } - -// /* read the frequency */ -// if(data_read >= (KEY_BITS / 8) + sizeof(struct FreqNfcEntry)) { -// struct FreqNfcEntry* freq_entry = -// (struct FreqNfcEntry*)(dev_data->mf_ul_data.data + (KEY_BITS / 8)); -// state->frequency = __ntohl(freq_entry->frequency); -// } - -// /* read the replay dict */ -// struct ReplayDictNfcReaderContext rd_ctx = { -// .cur = dev_data->mf_ul_data.data + (KEY_BITS / 8) + sizeof(struct FreqNfcEntry), -// .max = -// dev_data->mf_ul_data.data + (data_read < NFC_MAX_BYTES ? data_read : NFC_MAX_BYTES)}; - -// crypto_ctx_read_replay_dict(state->crypto_ctx, replay_dict_nfc_reader, &rd_ctx); - -// /* set encrypted flag */ -// state->encrypted = true; - -// return true; -// } - -// static void key_read_popup_set_state(ESubGhzChatState* state, KeyReadPopupState new_state) { -// uint32_t cur_state = -// scene_manager_get_scene_state(state->scene_manager, ESubGhzChatScene_KeyReadPopup); -// if(cur_state == new_state) { -// return; -// } - -// if(new_state == KeyReadPopupState_Detecting) { -// popup_reset(state->nfc_popup); -// popup_disable_timeout(state->nfc_popup); -// popup_set_text(state->nfc_popup, "Tap Flipper\n to sender", 97, 24, AlignCenter, AlignTop); -// popup_set_icon(state->nfc_popup, 0, 8, &I_NFC_manual_60x50); -// notification_message(state->notification, &sequence_blink_start_cyan); -// } else if(new_state == KeyReadPopupState_Reading) { -// popup_reset(state->nfc_popup); -// popup_disable_timeout(state->nfc_popup); -// popup_set_header( -// state->nfc_popup, -// "Reading key\nDon't " -// "move...", -// 85, -// 24, -// AlignCenter, -// AlignTop); -// popup_set_icon(state->nfc_popup, 12, 23, &I_Loading_24); -// notification_message(state->notification, &sequence_blink_start_yellow); -// } else if(new_state == KeyReadPopupState_Fail) { -// nfc_worker_stop(state->nfc_worker); - -// popup_reset(state->nfc_popup); -// popup_set_header(state->nfc_popup, "Failure!", 64, 2, AlignCenter, AlignTop); -// popup_set_text(state->nfc_popup, "Failed\nto read\nkey.", 78, 16, AlignLeft, AlignTop); -// popup_set_icon(state->nfc_popup, 14, 10, &I_dolph_cry_49x54); - -// popup_set_timeout(state->nfc_popup, KEY_READ_POPUP_MS); -// popup_set_context(state->nfc_popup, state); -// popup_set_callback(state->nfc_popup, key_read_popup_timeout_cb); -// popup_enable_timeout(state->nfc_popup); - -// notification_message(state->notification, &sequence_blink_stop); -// } else if(new_state == KeyReadPopupState_Success) { -// nfc_worker_stop(state->nfc_worker); - -// popup_reset(state->nfc_popup); -// popup_set_header(state->nfc_popup, "Key\nread!", 13, 22, AlignLeft, AlignBottom); -// popup_set_icon(state->nfc_popup, 36, 5, &I_DolphinDone_80x58); - -// popup_set_timeout(state->nfc_popup, KEY_READ_POPUP_MS); -// popup_set_context(state->nfc_popup, state); -// popup_set_callback(state->nfc_popup, key_read_popup_timeout_cb); -// popup_enable_timeout(state->nfc_popup); - -// notification_message(state->notification, &sequence_success); -// notification_message(state->notification, &sequence_blink_stop); -// } - -// scene_manager_set_scene_state(state->scene_manager, ESubGhzChatScene_KeyReadPopup, new_state); - -// view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_NfcPopup); -// } - -// /* Prepares the key share read scene. */ -// void scene_on_enter_key_read_popup(void* context) { -// FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_key_read_popup"); - -// furi_assert(context); -// ESubGhzChatState* state = context; - -// key_read_popup_set_state(state, KeyReadPopupState_Detecting); - -// state->nfc_dev_data->parsed_data = furi_string_alloc(); -// if(state->nfc_dev_data->parsed_data == NULL) { -// /* can't do anything here, crash */ -// furi_check(0); -// } - -// nfc_worker_start( -// state->nfc_worker, NfcWorkerStateRead, state->nfc_dev_data, read_worker_cb, state); -// } - -// /* Handles scene manager events for the key read popup scene. */ -// bool scene_on_event_key_read_popup(void* context, SceneManagerEvent event) { -// FURI_LOG_T(APPLICATION_NAME, "scene_on_event_key_read_popup"); - -// furi_assert(context); -// ESubGhzChatState* state = context; - -// bool consumed = false; - -// switch(event.type) { -// case SceneManagerEventTypeCustom: -// switch(event.event) { -// /* card detected */ -// case NfcWorkerEventCardDetected: -// key_read_popup_set_state(state, KeyReadPopupState_Reading); -// consumed = true; -// break; - -// /* no card detected */ -// case NfcWorkerEventNoCardDetected: -// key_read_popup_set_state(state, KeyReadPopupState_Detecting); -// consumed = true; -// break; - -// /* key probably read */ -// case NfcWorkerEventReadMfUltralight: -// if(key_read_popup_handle_key_read(state)) { -// key_read_popup_set_state(state, KeyReadPopupState_Success); -// } else { -// key_read_popup_set_state(state, KeyReadPopupState_Fail); -// } -// consumed = true; -// break; - -// /* close the popup and go back */ -// case ESubGhzChatEvent_KeyReadPopupFailed: -// if(!scene_manager_previous_scene(state->scene_manager)) { -// view_dispatcher_stop(state->view_dispatcher); -// } -// consumed = true; -// break; - -// /* success, go to frequency input */ -// case ESubGhzChatEvent_KeyReadPopupSucceeded: -// scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_FreqInput); -// consumed = true; -// break; - -// /* something else happend, treat as failure */ -// default: -// key_read_popup_set_state(state, KeyReadPopupState_Fail); -// consumed = true; -// break; -// } - -// break; - -// default: -// consumed = false; -// break; -// } - -// return consumed; -// } - -// /* Cleans up the key read popup scene. */ -// void scene_on_exit_key_read_popup(void* context) { -// FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_key_read_popup"); - -// furi_assert(context); -// ESubGhzChatState* state = context; - -// popup_reset(state->nfc_popup); -// scene_manager_set_scene_state( -// state->scene_manager, ESubGhzChatScene_KeyReadPopup, KeyReadPopupState_Idle); - -// notification_message(state->notification, &sequence_blink_stop); - -// nfc_worker_stop(state->nfc_worker); - -// crypto_explicit_bzero(state->nfc_dev_data->mf_ul_data.data, KEY_BITS / 8); -// if(state->nfc_dev_data->parsed_data != NULL) { -// furi_string_free(state->nfc_dev_data->parsed_data); -// } -// memset(state->nfc_dev_data, 0, sizeof(NfcDeviceData)); -// } +#include "../esubghz_chat_i.h" +#include "../helpers/nfc_helpers.h" +#include + +typedef enum { + KeyReadPopupState_Idle, + KeyReadPopupState_Detecting, + KeyReadPopupState_Reading, + KeyReadPopupState_Fail, + KeyReadPopupState_Success, +} KeyReadPopupState; + +static bool read_worker_cb(NfcWorkerEvent event, void* context) { + furi_assert(context); + ESubGhzChatState* state = context; + + view_dispatcher_send_custom_event(state->view_dispatcher, event); + + return true; +} + +static void key_read_popup_timeout_cb(void* context) { + furi_assert(context); + ESubGhzChatState* state = context; + + uint32_t cur_state = + scene_manager_get_scene_state(state->scene_manager, ESubGhzChatScene_KeyReadPopup); + + /* done displaying our failure */ + if(cur_state == KeyReadPopupState_Fail) { + view_dispatcher_send_custom_event( + state->view_dispatcher, ESubGhzChatEvent_KeyReadPopupFailed); + /* done displaying our success */ + } else if(cur_state == KeyReadPopupState_Success) { + view_dispatcher_send_custom_event( + state->view_dispatcher, ESubGhzChatEvent_KeyReadPopupSucceeded); + } +} + +struct ReplayDictNfcReaderContext { + uint8_t* cur; + uint8_t* max; +}; + +static bool replay_dict_nfc_reader(uint64_t* run_id, uint32_t* counter, void* context) { + struct ReplayDictNfcReaderContext* ctx = (struct ReplayDictNfcReaderContext*)context; + + if(ctx->cur + sizeof(struct ReplayDictNfcEntry) > ctx->max) { + return false; + } + + struct ReplayDictNfcEntry* entry = (struct ReplayDictNfcEntry*)ctx->cur; + *run_id = entry->run_id; + *counter = __ntohl(entry->counter); + + ctx->cur += sizeof(struct ReplayDictNfcEntry); + + return true; +} + +static bool key_read_popup_handle_key_read(ESubGhzChatState* state) { + NfcDeviceData* dev_data = state->nfc_dev_data; + + /* check for config pages */ + if(dev_data->mf_ul_data.data_read < NFC_CONFIG_PAGES * 4) { + return false; + } + + size_t data_read = dev_data->mf_ul_data.data_read - (NFC_CONFIG_PAGES * 4); + + /* check if key was transmitted */ + if(data_read < KEY_BITS / 8) { + return false; + } + + /* initiate the crypto context */ + bool ret = crypto_ctx_set_key( + state->crypto_ctx, dev_data->mf_ul_data.data, state->name_prefix, furi_get_tick()); + + /* cleanup */ + crypto_explicit_bzero(dev_data->mf_ul_data.data, KEY_BITS / 8); + + if(!ret) { + crypto_ctx_clear(state->crypto_ctx); + return false; + } + + /* read the frequency */ + if(data_read >= (KEY_BITS / 8) + sizeof(struct FreqNfcEntry)) { + struct FreqNfcEntry* freq_entry = + (struct FreqNfcEntry*)(dev_data->mf_ul_data.data + (KEY_BITS / 8)); + state->frequency = __ntohl(freq_entry->frequency); + } + + /* read the replay dict */ + struct ReplayDictNfcReaderContext rd_ctx = { + .cur = dev_data->mf_ul_data.data + (KEY_BITS / 8) + sizeof(struct FreqNfcEntry), + .max = + dev_data->mf_ul_data.data + (data_read < NFC_MAX_BYTES ? data_read : NFC_MAX_BYTES)}; + + crypto_ctx_read_replay_dict(state->crypto_ctx, replay_dict_nfc_reader, &rd_ctx); + + /* set encrypted flag */ + state->encrypted = true; + + return true; +} + +static void key_read_popup_set_state(ESubGhzChatState* state, KeyReadPopupState new_state) { + uint32_t cur_state = + scene_manager_get_scene_state(state->scene_manager, ESubGhzChatScene_KeyReadPopup); + if(cur_state == new_state) { + return; + } + + if(new_state == KeyReadPopupState_Detecting) { + popup_reset(state->nfc_popup); + popup_disable_timeout(state->nfc_popup); + popup_set_text(state->nfc_popup, "Tap Flipper\n to sender", 97, 24, AlignCenter, AlignTop); + popup_set_icon(state->nfc_popup, 0, 8, &I_NFC_manual_60x50); + notification_message(state->notification, &sequence_blink_start_cyan); + } else if(new_state == KeyReadPopupState_Reading) { + popup_reset(state->nfc_popup); + popup_disable_timeout(state->nfc_popup); + popup_set_header( + state->nfc_popup, + "Reading key\nDon't " + "move...", + 85, + 24, + AlignCenter, + AlignTop); + popup_set_icon(state->nfc_popup, 12, 23, &I_Loading_24); + notification_message(state->notification, &sequence_blink_start_yellow); + } else if(new_state == KeyReadPopupState_Fail) { + nfc_worker_stop(state->nfc_worker); + + popup_reset(state->nfc_popup); + popup_set_header(state->nfc_popup, "Failure!", 64, 2, AlignCenter, AlignTop); + popup_set_text(state->nfc_popup, "Failed\nto read\nkey.", 78, 16, AlignLeft, AlignTop); + popup_set_icon(state->nfc_popup, 21, 13, &I_dolph_cry_49x54); + + popup_set_timeout(state->nfc_popup, KEY_READ_POPUP_MS); + popup_set_context(state->nfc_popup, state); + popup_set_callback(state->nfc_popup, key_read_popup_timeout_cb); + popup_enable_timeout(state->nfc_popup); + + notification_message(state->notification, &sequence_blink_stop); + } else if(new_state == KeyReadPopupState_Success) { + nfc_worker_stop(state->nfc_worker); + + popup_reset(state->nfc_popup); + popup_set_header(state->nfc_popup, "Key\nread!", 13, 22, AlignLeft, AlignBottom); + popup_set_icon(state->nfc_popup, 36, 5, &I_DolphinDone_80x58); + + popup_set_timeout(state->nfc_popup, KEY_READ_POPUP_MS); + popup_set_context(state->nfc_popup, state); + popup_set_callback(state->nfc_popup, key_read_popup_timeout_cb); + popup_enable_timeout(state->nfc_popup); + + notification_message(state->notification, &sequence_success); + notification_message(state->notification, &sequence_blink_stop); + } + + scene_manager_set_scene_state(state->scene_manager, ESubGhzChatScene_KeyReadPopup, new_state); + + view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_NfcPopup); +} + +/* Prepares the key share read scene. */ +void scene_on_enter_key_read_popup(void* context) { + FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_key_read_popup"); + + furi_assert(context); + ESubGhzChatState* state = context; + + key_read_popup_set_state(state, KeyReadPopupState_Detecting); + + nfc_worker_start( + state->nfc_worker, NfcWorkerStateRead, state->nfc_dev_data, read_worker_cb, state); +} + +/* Handles scene manager events for the key read popup scene. */ +bool scene_on_event_key_read_popup(void* context, SceneManagerEvent event) { + FURI_LOG_T(APPLICATION_NAME, "scene_on_event_key_read_popup"); + + furi_assert(context); + ESubGhzChatState* state = context; + + bool consumed = false; + + switch(event.type) { + case SceneManagerEventTypeCustom: + switch(event.event) { + /* card detected */ + case NfcWorkerEventCardDetected: + key_read_popup_set_state(state, KeyReadPopupState_Reading); + consumed = true; + break; + + /* no card detected */ + case NfcWorkerEventNoCardDetected: + key_read_popup_set_state(state, KeyReadPopupState_Detecting); + consumed = true; + break; + + /* key probably read */ + case NfcWorkerEventReadMfUltralight: + if(key_read_popup_handle_key_read(state)) { + key_read_popup_set_state(state, KeyReadPopupState_Success); + } else { + key_read_popup_set_state(state, KeyReadPopupState_Fail); + } + consumed = true; + break; + + /* close the popup and go back */ + case ESubGhzChatEvent_KeyReadPopupFailed: + if(!scene_manager_previous_scene(state->scene_manager)) { + view_dispatcher_stop(state->view_dispatcher); + } + consumed = true; + break; + + /* success, go to frequency input */ + case ESubGhzChatEvent_KeyReadPopupSucceeded: + scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_FreqInput); + consumed = true; + break; + + /* something else happend, treat as failure */ + default: + key_read_popup_set_state(state, KeyReadPopupState_Fail); + consumed = true; + break; + } + + break; + + default: + consumed = false; + break; + } + + return consumed; +} + +/* Cleans up the key read popup scene. */ +void scene_on_exit_key_read_popup(void* context) { + FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_key_read_popup"); + + furi_assert(context); + ESubGhzChatState* state = context; + + popup_reset(state->nfc_popup); + scene_manager_set_scene_state( + state->scene_manager, ESubGhzChatScene_KeyReadPopup, KeyReadPopupState_Idle); + + notification_message(state->notification, &sequence_blink_stop); + + nfc_worker_stop(state->nfc_worker); + + crypto_explicit_bzero(state->nfc_dev_data->mf_ul_data.data, KEY_BITS / 8); + /*if(state->nfc_dev_data->parsed_data != NULL) { + furi_string_free(state->nfc_dev_data->parsed_data); + }*/ + //memset(state->nfc_dev_data, 0, sizeof(NfcDeviceData)); +} diff --git a/esubghz_chat/scenes/esubghz_chat_key_share_popup.c b/esubghz_chat/scenes/esubghz_chat_key_share_popup.c index 53fa89f427f..7c6645cb607 100644 --- a/esubghz_chat/scenes/esubghz_chat_key_share_popup.c +++ b/esubghz_chat/scenes/esubghz_chat_key_share_popup.c @@ -1,124 +1,136 @@ -// #include "../esubghz_chat_i.h" -// #include "../helpers/nfc_helpers.h" +#include "../esubghz_chat_i.h" +#include "../helpers/nfc_helpers.h" +#include -// struct ReplayDictNfcWriterContext { -// uint8_t* cur; -// uint8_t* max; -// }; +struct ReplayDictNfcWriterContext { + uint8_t* cur; + uint8_t* max; +}; -// static bool replay_dict_nfc_writer(uint64_t run_id, uint32_t counter, void* context) { -// struct ReplayDictNfcWriterContext* ctx = (struct ReplayDictNfcWriterContext*)context; +static bool replay_dict_nfc_writer(uint64_t run_id, uint32_t counter, void* context) { + struct ReplayDictNfcWriterContext* ctx = (struct ReplayDictNfcWriterContext*)context; -// struct ReplayDictNfcEntry entry = {.run_id = run_id, .counter = __htonl(counter), .unused = 0}; + struct ReplayDictNfcEntry entry = {.run_id = run_id, .counter = __htonl(counter), .unused = 0}; -// if(ctx->cur + sizeof(entry) > ctx->max) { -// return false; -// } + if(ctx->cur + sizeof(entry) > ctx->max) { + return false; + } -// memcpy(ctx->cur, &entry, sizeof(entry)); -// ctx->cur += sizeof(entry); + memcpy(ctx->cur, &entry, sizeof(entry)); + ctx->cur += sizeof(entry); -// return true; -// } + return true; +} -// static void prepare_nfc_dev_data(ESubGhzChatState* state) { -// NfcDeviceData* dev_data = state->nfc_dev_data; +static void prepare_nfc_dev_data(ESubGhzChatState* state) { + NfcDeviceData* dev_data = state->nfc_dev_data; -// dev_data->protocol = NfcDeviceProtocolMifareUl; -// furi_hal_random_fill_buf(dev_data->nfc_data.uid, 7); -// dev_data->nfc_data.uid_len = 7; -// dev_data->nfc_data.atqa[0] = 0x44; -// dev_data->nfc_data.atqa[1] = 0x00; -// dev_data->nfc_data.sak = 0x00; + dev_data->protocol = NfcDeviceProtocolMifareUl; + furi_hal_random_fill_buf(dev_data->nfc_data.uid, 7); + dev_data->nfc_data.uid_len = 7; + dev_data->nfc_data.atqa[0] = 0x44; + dev_data->nfc_data.atqa[1] = 0x00; + dev_data->nfc_data.sak = 0x00; -// dev_data->mf_ul_data.type = MfUltralightTypeNTAG215; -// dev_data->mf_ul_data.version.header = 0x00; -// dev_data->mf_ul_data.version.vendor_id = 0x04; -// dev_data->mf_ul_data.version.prod_type = 0x04; -// dev_data->mf_ul_data.version.prod_subtype = 0x02; -// dev_data->mf_ul_data.version.prod_ver_major = 0x01; -// dev_data->mf_ul_data.version.prod_ver_minor = 0x00; -// dev_data->mf_ul_data.version.storage_size = 0x11; -// dev_data->mf_ul_data.version.protocol_type = 0x03; + dev_data->mf_ul_data.type = MfUltralightTypeNTAG215; + dev_data->mf_ul_data.version.header = 0x00; + dev_data->mf_ul_data.version.vendor_id = 0x04; + dev_data->mf_ul_data.version.prod_type = 0x04; + dev_data->mf_ul_data.version.prod_subtype = 0x02; + dev_data->mf_ul_data.version.prod_ver_major = 0x01; + dev_data->mf_ul_data.version.prod_ver_minor = 0x00; + dev_data->mf_ul_data.version.storage_size = 0x11; + dev_data->mf_ul_data.version.protocol_type = 0x03; -// size_t data_written = 0; + size_t data_written = 0; -// /* write key */ -// crypto_ctx_get_key(state->crypto_ctx, dev_data->mf_ul_data.data); -// data_written += (KEY_BITS / 8); + /* write key */ + crypto_ctx_get_key(state->crypto_ctx, dev_data->mf_ul_data.data); + data_written += (KEY_BITS / 8); -// /* write frequency */ -// struct FreqNfcEntry* freq_entry = -// (struct FreqNfcEntry*)(dev_data->mf_ul_data.data + data_written); -// freq_entry->frequency = __htonl(state->frequency); -// freq_entry->unused1 = 0; -// freq_entry->unused2 = 0; -// freq_entry->unused3 = 0; -// data_written += sizeof(struct FreqNfcEntry); + /* write frequency */ + struct FreqNfcEntry* freq_entry = + (struct FreqNfcEntry*)(dev_data->mf_ul_data.data + data_written); + freq_entry->frequency = __htonl(state->frequency); + freq_entry->unused1 = 0; + freq_entry->unused2 = 0; + freq_entry->unused3 = 0; + data_written += sizeof(struct FreqNfcEntry); -// /* write the replay dict */ -// struct ReplayDictNfcWriterContext wr_ctx = { -// .cur = dev_data->mf_ul_data.data + data_written, -// .max = dev_data->mf_ul_data.data + NFC_MAX_BYTES}; + /* write the replay dict */ + struct ReplayDictNfcWriterContext wr_ctx = { + .cur = dev_data->mf_ul_data.data + data_written, + .max = dev_data->mf_ul_data.data + NFC_MAX_BYTES}; -// size_t n_entries = -// crypto_ctx_dump_replay_dict(state->crypto_ctx, replay_dict_nfc_writer, &wr_ctx); -// data_written += n_entries * sizeof(struct ReplayDictNfcEntry); + size_t n_entries = + crypto_ctx_dump_replay_dict(state->crypto_ctx, replay_dict_nfc_writer, &wr_ctx); + data_written += n_entries * sizeof(struct ReplayDictNfcEntry); -// /* calculate size of data, add 16 for config pages */ -// dev_data->mf_ul_data.data_size = data_written + (NFC_CONFIG_PAGES * 4); -// } + /* calculate size of data, add 16 for config pages */ + dev_data->mf_ul_data.data_size = data_written + (NFC_CONFIG_PAGES * 4); +} -// /* Prepares the key share popup scene. */ -// void scene_on_enter_key_share_popup(void* context) { -// FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_key_share_popup"); +/* Prepares the key share popup scene. */ +void scene_on_enter_key_share_popup(void* context) { + FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_key_share_popup"); -// furi_assert(context); -// ESubGhzChatState* state = context; + furi_assert(context); + ESubGhzChatState* state = context; -// popup_reset(state->nfc_popup); + popup_reset(state->nfc_popup); -// popup_disable_timeout(state->nfc_popup); + popup_disable_timeout(state->nfc_popup); -// popup_set_header(state->nfc_popup, "Sharing...", 67, 13, AlignLeft, AlignTop); -// popup_set_icon(state->nfc_popup, 0, 3, &I_NFC_dolphin_emulation_51x64); -// popup_set_text(state->nfc_popup, "Sharing\nKey via\nNFC", 90, 28, AlignCenter, AlignTop); + popup_set_header(state->nfc_popup, "Sharing...", 67, 13, AlignLeft, AlignTop); + popup_set_icon(state->nfc_popup, 0, 3, &I_NFC_dolphin_emulation_51x64); + popup_set_text(state->nfc_popup, "Sharing\nKey via\nNFC", 90, 28, AlignCenter, AlignTop); -// prepare_nfc_dev_data(state); -// nfc_worker_start( -// state->nfc_worker, NfcWorkerStateMfUltralightEmulate, state->nfc_dev_data, NULL, NULL); + prepare_nfc_dev_data(state); + nfc_worker_start( + state->nfc_worker, NfcWorkerStateMfUltralightEmulate, state->nfc_dev_data, NULL, NULL); -// notification_message(state->notification, &sequence_blink_start_magenta); + notification_message(state->notification, &sequence_blink_start_magenta); -// view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_NfcPopup); -// } + view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_NfcPopup); +} -// /* Handles scene manager events for the key share popup scene. */ -// bool scene_on_event_key_share_popup(void* context, SceneManagerEvent event) { -// FURI_LOG_T(APPLICATION_NAME, "scene_on_event_key_share_popup"); +/* Handles scene manager events for the key share popup scene. */ +bool scene_on_event_key_share_popup(void* context, SceneManagerEvent event) { + FURI_LOG_T(APPLICATION_NAME, "scene_on_event_key_share_popup"); -// furi_assert(context); -// ESubGhzChatState* state = context; + furi_assert(context); + ESubGhzChatState* state = context; -// UNUSED(state); -// UNUSED(event); + UNUSED(state); + UNUSED(event); -// return false; -// } + return false; +} -// /* Cleans up the key share popup scene. */ -// void scene_on_exit_key_share_popup(void* context) { -// FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_key_share_popup"); +static bool temp_read_worker_cb(NfcWorkerEvent event, void* context) { + UNUSED(event); + UNUSED(context); + return true; +} -// furi_assert(context); -// ESubGhzChatState* state = context; +/* Cleans up the key share popup scene. */ +void scene_on_exit_key_share_popup(void* context) { + FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_key_share_popup"); -// popup_reset(state->nfc_popup); + furi_assert(context); + ESubGhzChatState* state = context; -// notification_message(state->notification, &sequence_blink_stop); + popup_reset(state->nfc_popup); -// nfc_worker_stop(state->nfc_worker); + notification_message(state->notification, &sequence_blink_stop); -// crypto_explicit_bzero(state->nfc_dev_data->mf_ul_data.data, KEY_BITS / 8); -// memset(state->nfc_dev_data, 0, sizeof(NfcDeviceData)); -// } + nfc_worker_stop(state->nfc_worker); + + nfc_worker_start( + state->nfc_worker, NfcWorkerStateRead, state->nfc_dev_data, temp_read_worker_cb, state); + + nfc_worker_stop(state->nfc_worker); + + crypto_explicit_bzero(state->nfc_dev_data->mf_ul_data.data, KEY_BITS / 8); + memset(state->nfc_dev_data, 0, sizeof(NfcDeviceData)); +} diff --git a/esubghz_chat/scenes/esubghz_chat_scene_config.h b/esubghz_chat/scenes/esubghz_chat_scene_config.h index d4ff555ecfd..85981c898a0 100644 --- a/esubghz_chat/scenes/esubghz_chat_scene_config.h +++ b/esubghz_chat/scenes/esubghz_chat_scene_config.h @@ -2,8 +2,8 @@ ADD_SCENE(esubghz_chat, freq_input, FreqInput) ADD_SCENE(esubghz_chat, key_menu, KeyMenu) ADD_SCENE(esubghz_chat, pass_input, PassInput) ADD_SCENE(esubghz_chat, hex_key_input, HexKeyInput) -// ADD_SCENE(esubghz_chat, key_read_popup, KeyReadPopup) +ADD_SCENE(esubghz_chat, key_read_popup, KeyReadPopup) ADD_SCENE(esubghz_chat, chat_input, ChatInput) ADD_SCENE(esubghz_chat, chat_box, ChatBox) ADD_SCENE(esubghz_chat, key_display, KeyDisplay) -// ADD_SCENE(esubghz_chat, key_share_popup, KeySharePopup) +ADD_SCENE(esubghz_chat, key_share_popup, KeySharePopup) diff --git a/flappy_bird/application.fam b/flappy_bird/application.fam index 3588de0b920..9ef48b89957 100644 --- a/flappy_bird/application.fam +++ b/flappy_bird/application.fam @@ -10,6 +10,6 @@ App( fap_category="Games", fap_icon_assets="assets", fap_author="@DroomOne & @xMasterX", - fap_version="1.1", + fap_version="1.2", fap_description="Flappy Bird Game", ) diff --git a/flappy_bird/flappy_bird.c b/flappy_bird/flappy_bird.c index a0a6310ef95..13681db0b6d 100644 --- a/flappy_bird/flappy_bird.c +++ b/flappy_bird/flappy_bird.c @@ -270,16 +270,16 @@ static void flappy_game_render_callback(Canvas* const canvas, void* ctx) { } static void flappy_game_input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); GameEvent event = {.type = EventTypeKey, .input = *input_event}; furi_message_queue_put(event_queue, &event, FuriWaitForever); } static void flappy_game_update_timer_callback(void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); GameEvent event = {.type = EventTypeTick}; furi_message_queue_put(event_queue, &event, 0); diff --git a/flashlight/flashlight.c b/flashlight/flashlight.c index f2975063870..2a36f455937 100644 --- a/flashlight/flashlight.c +++ b/flashlight/flashlight.c @@ -49,8 +49,8 @@ static void render_callback(Canvas* const canvas, void* ctx) { } static void input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); PluginEvent event = {.type = EventTypeKey, .input = *input_event}; furi_message_queue_put(event_queue, &event, FuriWaitForever); diff --git a/game15/application.fam b/game15/application.fam index de08f2ca5f0..2845aeb2381 100644 --- a/game15/application.fam +++ b/game15/application.fam @@ -9,6 +9,6 @@ App( order=30, fap_category="Games", fap_author="@x27", - fap_version="1.1", + fap_version="1.2", fap_description="Logic Game", ) diff --git a/game15/sandbox.c b/game15/sandbox.c index e6fcfc61295..db19191eb65 100644 --- a/game15/sandbox.c +++ b/game15/sandbox.c @@ -3,7 +3,7 @@ #include "sandbox.h" FuriMessageQueue* sandbox_event_queue; -FuriMutex** sandbox_mutex; +FuriMutex* sandbox_mutex; ViewPort* sandbox_view_port; Gui* sandbox_gui; FuriTimer* sandbox_timer; diff --git a/game_of_life/application.fam b/game_of_life/application.fam index fad1cdd326c..36eb1b26c6f 100644 --- a/game_of_life/application.fam +++ b/game_of_life/application.fam @@ -11,6 +11,6 @@ App( fap_category="Games", fap_author="@tgxn (original by @itsyourbedtime)", fap_weburl="https://github.com/tgxn/flipperzero-firmware/blob/dev/applications/game_of_life/game_of_life.c", - fap_version="1.1", + fap_version="1.2", fap_description="Life, is a cellular automaton devised by the British mathematician John Horton Conway in 1970.", ) diff --git a/game_of_life/game_of_life.c b/game_of_life/game_of_life.c index cba54d3dca6..f4c21204ce9 100644 --- a/game_of_life/game_of_life.c +++ b/game_of_life/game_of_life.c @@ -86,8 +86,8 @@ static void update_field(State* state) { } static void input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); AppEvent event = {.type = EventTypeKey, .input = *input_event}; furi_message_queue_put(event_queue, &event, 0); diff --git a/geiger/application.fam b/geiger/application.fam index cd9018d599a..c4c7c493587 100644 --- a/geiger/application.fam +++ b/geiger/application.fam @@ -12,6 +12,6 @@ App( fap_category="GPIO/Sensors", fap_author="@nmrr", fap_weburl="https://github.com/nmrr/flipperzero-geigercounter", - fap_version="1.3", + fap_version="1.4", fap_description="Works with J305 Geiger tube on external board", ) diff --git a/gpio_reader_a/GPIO_reader.c b/gpio_reader_a/GPIO_reader.c index 836b65bf148..7a46a713d52 100644 --- a/gpio_reader_a/GPIO_reader.c +++ b/gpio_reader_a/GPIO_reader.c @@ -1,153 +1,153 @@ -#include -#include -#include -#include -#include "GPIO_reader_item.h" - -typedef enum { - EventTypeTick, - EventTypeKey, -} EventType; - -typedef struct { - EventType type; - InputEvent input; -} PluginEvent; - -typedef struct { - int pin; - int pullMode; - FuriMutex* mutex; -} PluginState; - -static void render_callback(Canvas* const canvas, void* ctx) { - furi_assert(ctx); - const PluginState* plugin_state = ctx; - furi_mutex_acquire(plugin_state->mutex, FuriWaitForever); - - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned( - canvas, - canvas_width(canvas) / 2, - canvas_height(canvas) / 10, - AlignCenter, - AlignCenter, - "GPIO reader"); - - canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned( - canvas, - canvas_width(canvas) / 2, - canvas_height(canvas) / 10 * 3, - AlignCenter, - AlignCenter, - gpio_item_get_pin_name(plugin_state->pin)); - - canvas_draw_str_aligned( - canvas, - canvas_width(canvas) / 2, - canvas_height(canvas) / 10 * 5, - AlignCenter, - AlignCenter, - gpio_item_get_pull_mode(plugin_state->pullMode)); - - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned( - canvas, - canvas_width(canvas) / 2, - canvas_height(canvas) / 10 * 8, - AlignCenter, - AlignCenter, - gpio_item_get_pin_level(plugin_state->pin)); - - furi_mutex_release(plugin_state->mutex); -} - -static void input_callback(InputEvent* input_event, void* ctx) { - FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); - - PluginEvent event = {.type = EventTypeKey, .input = *input_event}; - furi_message_queue_put(event_queue, &event, FuriWaitForever); -} - -static void GPIO_reader_state_init(PluginState* const plugin_state) { - plugin_state->pin = 0; - plugin_state->pullMode = 0; - gpio_item_configure_pin(plugin_state->pin, plugin_state->pullMode); -} - -int32_t GPIO_reader_app(void* p) { - UNUSED(p); - FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent)); - - PluginState* plugin_state = malloc(sizeof(PluginState)); - GPIO_reader_state_init(plugin_state); - plugin_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal); - if(!plugin_state->mutex) { - FURI_LOG_E("GPIO_reader", "cannot create mutex\r\n"); - free(plugin_state); - return 255; - } - - // Set system callbacks - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, render_callback, plugin_state); - view_port_input_callback_set(view_port, input_callback, event_queue); - - // Open GUI and register view_port - Gui* gui = furi_record_open("gui"); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - - PluginEvent event; - for(bool processing = true; processing;) { - FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); - furi_mutex_acquire(plugin_state->mutex, FuriWaitForever); - - if(event_status == FuriStatusOk) { - // press events - if(event.type == EventTypeKey) { - if(event.input.type == InputTypePress || event.input.type == InputTypeRepeat) { - switch(event.input.key) { - case InputKeyRight: - plugin_state->pin = (plugin_state->pin + 1) % GPIO_ITEM_COUNT; - gpio_item_configure_pin(plugin_state->pin, plugin_state->pullMode); - break; - case InputKeyLeft: - plugin_state->pin = - (plugin_state->pin - 1 + GPIO_ITEM_COUNT) % GPIO_ITEM_COUNT; - gpio_item_configure_pin(plugin_state->pin, plugin_state->pullMode); - break; - case InputKeyUp: - plugin_state->pullMode = (plugin_state->pullMode + 1) % GPIO_PULL_COUNT; - gpio_item_configure_pin(plugin_state->pin, plugin_state->pullMode); - break; - case InputKeyDown: - plugin_state->pullMode = - (plugin_state->pullMode - 1 + GPIO_PULL_COUNT) % GPIO_PULL_COUNT; - gpio_item_configure_pin(plugin_state->pin, plugin_state->pullMode); - break; - case InputKeyBack: - processing = false; - break; - default: - break; - } - } - } - } - - furi_mutex_release(plugin_state->mutex); - view_port_update(view_port); - } - - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - furi_record_close("gui"); - view_port_free(view_port); - furi_mutex_free(plugin_state->mutex); - furi_message_queue_free(event_queue); - free(plugin_state); - - return 0; +#include +#include +#include +#include +#include "GPIO_reader_item.h" + +typedef enum { + EventTypeTick, + EventTypeKey, +} EventType; + +typedef struct { + EventType type; + InputEvent input; +} PluginEvent; + +typedef struct { + int pin; + int pullMode; + FuriMutex* mutex; +} PluginState; + +static void render_callback(Canvas* const canvas, void* ctx) { + furi_assert(ctx); + const PluginState* plugin_state = ctx; + furi_mutex_acquire(plugin_state->mutex, FuriWaitForever); + + canvas_set_font(canvas, FontPrimary); + canvas_draw_str_aligned( + canvas, + canvas_width(canvas) / 2, + canvas_height(canvas) / 10, + AlignCenter, + AlignCenter, + "GPIO reader"); + + canvas_set_font(canvas, FontSecondary); + canvas_draw_str_aligned( + canvas, + canvas_width(canvas) / 2, + canvas_height(canvas) / 10 * 3, + AlignCenter, + AlignCenter, + gpio_item_get_pin_name(plugin_state->pin)); + + canvas_draw_str_aligned( + canvas, + canvas_width(canvas) / 2, + canvas_height(canvas) / 10 * 5, + AlignCenter, + AlignCenter, + gpio_item_get_pull_mode(plugin_state->pullMode)); + + canvas_set_font(canvas, FontPrimary); + canvas_draw_str_aligned( + canvas, + canvas_width(canvas) / 2, + canvas_height(canvas) / 10 * 8, + AlignCenter, + AlignCenter, + gpio_item_get_pin_level(plugin_state->pin)); + + furi_mutex_release(plugin_state->mutex); +} + +static void input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); + FuriMessageQueue* event_queue = ctx; + + PluginEvent event = {.type = EventTypeKey, .input = *input_event}; + furi_message_queue_put(event_queue, &event, FuriWaitForever); +} + +static void GPIO_reader_state_init(PluginState* const plugin_state) { + plugin_state->pin = 0; + plugin_state->pullMode = 0; + gpio_item_configure_pin(plugin_state->pin, plugin_state->pullMode); +} + +int32_t GPIO_reader_app(void* p) { + UNUSED(p); + FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent)); + + PluginState* plugin_state = malloc(sizeof(PluginState)); + GPIO_reader_state_init(plugin_state); + plugin_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal); + if(!plugin_state->mutex) { + FURI_LOG_E("GPIO_reader", "cannot create mutex\r\n"); + free(plugin_state); + return 255; + } + + // Set system callbacks + ViewPort* view_port = view_port_alloc(); + view_port_draw_callback_set(view_port, render_callback, plugin_state); + view_port_input_callback_set(view_port, input_callback, event_queue); + + // Open GUI and register view_port + Gui* gui = furi_record_open("gui"); + gui_add_view_port(gui, view_port, GuiLayerFullscreen); + + PluginEvent event; + for(bool processing = true; processing;) { + FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); + furi_mutex_acquire(plugin_state->mutex, FuriWaitForever); + + if(event_status == FuriStatusOk) { + // press events + if(event.type == EventTypeKey) { + if(event.input.type == InputTypePress || event.input.type == InputTypeRepeat) { + switch(event.input.key) { + case InputKeyRight: + plugin_state->pin = (plugin_state->pin + 1) % GPIO_ITEM_COUNT; + gpio_item_configure_pin(plugin_state->pin, plugin_state->pullMode); + break; + case InputKeyLeft: + plugin_state->pin = + (plugin_state->pin - 1 + GPIO_ITEM_COUNT) % GPIO_ITEM_COUNT; + gpio_item_configure_pin(plugin_state->pin, plugin_state->pullMode); + break; + case InputKeyUp: + plugin_state->pullMode = (plugin_state->pullMode + 1) % GPIO_PULL_COUNT; + gpio_item_configure_pin(plugin_state->pin, plugin_state->pullMode); + break; + case InputKeyDown: + plugin_state->pullMode = + (plugin_state->pullMode - 1 + GPIO_PULL_COUNT) % GPIO_PULL_COUNT; + gpio_item_configure_pin(plugin_state->pin, plugin_state->pullMode); + break; + case InputKeyBack: + processing = false; + break; + default: + break; + } + } + } + } + + furi_mutex_release(plugin_state->mutex); + view_port_update(view_port); + } + + view_port_enabled_set(view_port, false); + gui_remove_view_port(gui, view_port); + furi_record_close("gui"); + view_port_free(view_port); + furi_mutex_free(plugin_state->mutex); + furi_message_queue_free(event_queue); + free(plugin_state); + + return 0; } \ No newline at end of file diff --git a/gpio_reader_a/application.fam b/gpio_reader_a/application.fam index 860af180b29..5eeb05b5780 100644 --- a/gpio_reader_a/application.fam +++ b/gpio_reader_a/application.fam @@ -9,6 +9,6 @@ App( fap_icon="icon.png", fap_author="@aureli1c", fap_weburl="https://github.com/aureli1c/flipperzero_GPIO_read", - fap_version="1.1", + fap_version="1.2", fap_description="Read GPIO pins states, and display them on the screen", ) diff --git a/gps_nmea/README.md b/gps_nmea/README.md index 5cc350fb58e..cfa843b5db8 100644 --- a/gps_nmea/README.md +++ b/gps_nmea/README.md @@ -62,6 +62,7 @@ the hardware setup. * [u-Blox NEO-7M] * [Uputronics u-blox MAX-M8C Pico] * [Quectel L80] +* [M10Q-5883] If you have verified this application working with a module not listed here, please submit a PR adding it to the list. @@ -80,3 +81,4 @@ of the repository. [uFBT]: https://github.com/flipperdevices/flipperzero-ufbt [Uputronics u-blox MAX-M8C Pico]: https://store.uputronics.com/index.php?route=product/product&product_id=72 [Quectel L80]: https://www.quectel.com/ProductDownload/L80.html +[M10Q-5883]: https://www.mateksys.com/?portfolio=m10q-5883 diff --git a/gps_nmea/application.fam b/gps_nmea/application.fam index 7f6e605eed5..af2043345fc 100644 --- a/gps_nmea/application.fam +++ b/gps_nmea/application.fam @@ -16,6 +16,6 @@ App( ), ], fap_author="@ezod & @xMasterX", - fap_version="1.3", + fap_version="1.4", fap_description="Works with GPS modules via UART, using NMEA protocol.", ) diff --git a/gps_nmea/gps.c b/gps_nmea/gps.c index 3ecbe5da5b2..905c90c9208 100644 --- a/gps_nmea/gps.c +++ b/gps_nmea/gps.c @@ -123,9 +123,9 @@ static void render_callback(Canvas* const canvas, void* context) { furi_mutex_release(gps_uart->mutex); } -static void input_callback(InputEvent* input_event, void* context) { - furi_assert(context); - FuriMessageQueue* event_queue = context; +static void input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); + FuriMessageQueue* event_queue = ctx; PluginEvent event = {.type = EventTypeKey, .input = *input_event}; furi_message_queue_put(event_queue, &event, FuriWaitForever); diff --git a/hc_sr04/hc_sr04.c b/hc_sr04/hc_sr04.c index 5a64554ac43..0a61fc77409 100644 --- a/hc_sr04/hc_sr04.c +++ b/hc_sr04/hc_sr04.c @@ -90,8 +90,8 @@ static void render_callback(Canvas* const canvas, void* ctx) { } static void input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); PluginEvent event = {.type = EventTypeKey, .input = *input_event}; furi_message_queue_put(event_queue, &event, FuriWaitForever); diff --git a/heap_defence/application.fam b/heap_defence/application.fam index 2942f30f8c0..ab71b353939 100644 --- a/heap_defence/application.fam +++ b/heap_defence/application.fam @@ -9,6 +9,6 @@ App( fap_icon="box.png", fap_icon_assets="assets_images", fap_author="@xMasterX (original implementation by @wquinoa & @Vedmein)", - fap_version="1.2", + fap_version="1.3", fap_description="Heap Defence game from hackathon (aka Stack Attack)", ) diff --git a/ir_intervalometer/application.fam b/ir_intervalometer/application.fam index 066ae0fb93f..6dd870a56ab 100644 --- a/ir_intervalometer/application.fam +++ b/ir_intervalometer/application.fam @@ -11,6 +11,6 @@ App( fap_author="@Nitepone", fap_category="Infrared", fap_description="Intervalometer for Canon, Nikon, and Sony cameras. Uses IR shutter release.", - fap_version="1.2", + fap_version="2.2", fap_weburl="https://github.com/Nitepone/flipper-intervalometer", ) diff --git a/ir_intervalometer/intervalometer.c b/ir_intervalometer/intervalometer.c index c7f24961f74..296fb06a67d 100644 --- a/ir_intervalometer/intervalometer.c +++ b/ir_intervalometer/intervalometer.c @@ -478,8 +478,8 @@ static void flipvalo_run_state_init(struct flipvalo_run_state* fv_run_state) { fv_run_state->tick_cur = 0; } -static void input_callback(InputEvent* input_event, void* ctx) { - FuriMessageQueue* event_queue = ctx; +static void input_callback(InputEvent* input_event, void* event_queue_void) { + FuriMessageQueue* event_queue = (FuriMessageQueue*)event_queue_void; furi_assert(event_queue); struct plugin_event event = {.type = EventTypeKey, .input = *input_event}; furi_message_queue_put(event_queue, &event, FuriWaitForever); diff --git a/ir_scope/application.fam b/ir_scope/application.fam index ceaa629f712..6fd3192df56 100644 --- a/ir_scope/application.fam +++ b/ir_scope/application.fam @@ -8,6 +8,6 @@ App( fap_icon="ir_scope.png", fap_category="Infrared", fap_author="@kallanreed", - fap_version="1.2", + fap_version="1.3", fap_description="App allows to see incoming IR signals.", ) diff --git a/jetpack_joyride/jetpack.c b/jetpack_joyride/jetpack.c index 6f45bccc1e1..07834d265e2 100644 --- a/jetpack_joyride/jetpack.c +++ b/jetpack_joyride/jetpack.c @@ -252,16 +252,16 @@ static void jetpack_game_render_callback(Canvas* const canvas, void* ctx) { } static void jetpack_game_input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); GameEvent event = {.type = EventTypeKey, .input = *input_event}; furi_message_queue_put(event_queue, &event, FuriWaitForever); } static void jetpack_game_update_timer_callback(void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); GameEvent event = {.type = EventTypeTick}; furi_message_queue_put(event_queue, &event, 0); diff --git a/magspoof/.github/workflows/md_links.yml b/magspoof/.github/workflows/md_links.yml new file mode 100644 index 00000000000..d578b7dc811 --- /dev/null +++ b/magspoof/.github/workflows/md_links.yml @@ -0,0 +1,17 @@ +name: Check Markdown links + +on: + workflow_dispatch: + push: + schedule: + # Run everyday at 9:00 AM (See https://pubs.opengroup.org/onlinepubs/9699919799/utilities/crontab.html#tag_20_25_07) + - cron: "0 9 * * *" + +jobs: + markdown-link-check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - uses: gaurav-nelson/github-action-markdown-link-check@1.0.15 + with: + use-verbose-mode: 'yes' diff --git a/magspoof/NOTES.md b/magspoof/NOTES.md index 23a87e9d329..9cb10e5dbba 100644 --- a/magspoof/NOTES.md +++ b/magspoof/NOTES.md @@ -1,7 +1,7 @@ ## TODO Known bugs: - [X] File format issues when Track 2 data exists but Track 1 is left empty; doesn't seem to be setting the Track 2 field with anything (doesn't overwrite existing data). However, `flipper_format_read_string()` doesn't seem to return `false`. Is the bug in my code, or with `flipper_format`? - - [X] Review how it's done in [unirfremix (Sub-GHz Remote)](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/applications/main/unirfremix/unirfremix_app.c), as IIRC that can handle empty keys, despite using the `flipper_format` lib for parsing. + - [X] Review how it's done in unirfremix (Sub-GHz Remote), as IIRC that can handle empty keys, despite using the `flipper_format` lib for parsing. - [X] Attempting to play a track that doesn't have data results in a crash (as one might expect). Need to lock out users from selecting empty tracks in the config menu or do better error handling (*Doesn't crash now, but still should probably prevent users from being able to select*) - [ ] Custom text input scene with expanded characterset (Add Manually) has odd behavior when navigating the keys near the numpad diff --git a/magspoof/README.md b/magspoof/README.md index b78e0874a12..377871a089c 100644 --- a/magspoof/README.md +++ b/magspoof/README.md @@ -1,18 +1,41 @@ -# magspoof_flipper -WIP of MagSpoof for the Flipper Zero. Basic TX of saved files confirmed working against an MSR90 with an external H-bridge module mirroring Samy Kamkar's design. Sample files are included in `resources`. +# MagSpoof for the Flipper Zero +MagSpoof-ing, as [coined / invented by Samy Kamkar](https://github.com/samyk/magspoof), is the use of an electromagnet to emulate the data on a traditional magstripe card — wirelessly! - RFID coil output weaker; able to be picked up/detected by more compact mag readers such as Square, but yet to have success with it being decoded/parsed properly. Additional investigation was made into alternate internal TX options (CC1101, ST25R3916, piezo); tentatively, RFID coil + speaker (`LF + P` config setting) results in the strongest internal TX tested to date but still weaker than a dedicated external module or an actual card swipe (and sounds like a dial-up modem from hell). For information on the state of internal TX &/or misc TODOs, known bugs, etc, confer `NOTES.md`. +This app ports the original MagSpoof project to the Flipper Zero, adding file management and emulation controls, along with [some experimental features](#skunkworks-and-experimental-features). Visit the [Wiki](https://github.com/zacharyweiss/magspoof_flipper/wiki) for information on getting started. -**Disclaimer**: use responsibly, and at your own risk. ***I neither condone nor am sympathetic to malicious uses of my code.*** Please only use this with magstripe cards and mag readers you own — this is solely meant as a proof of concept for educational purposes. Similarly, if using internal TX: while in my testing, I've seen no reason to believe this could damage the RFID (or other) hardware, this is inherently driving the coil in ways it was not designed or intended for; I take no responsibility for fried/bricked Flippers. +> [!TIP] +> After the first launch of the app, the `/apps_data/magspoof/` folder will be created on your Flipper's SD card, and populated with sample `.mag` files. Place your own files here, using the [sample files](resources) as a template. +> [!WARNING] +> Use responsibly, and at your own risk. MagSpoof is intended solely for authorized security audits and educational purposes. Ensure legal compliance and obtain necessary permissions before using this tool. +> +> ***I neither condone nor am sympathetic to malicious uses of my code.*** + -## GPIO TX Module -For those desiring better TX than the internal RFID coil can offer, one can build the module below, consisting of an H-bridge, a capacitor, and a coil. Custom GPIO pin selection is a planned future feature. +## TX Module +The GPIO module is a simple electromagnet consisting of an H-bridge, a capacitor, and a coil. One can build the pictured circuit, or purchase a MagSpoof board from the community. There is no "official board", but the following are popular choices: +- [Rabbit-Labs'](https://www.rabbit-labs.com/) [Multi Pass MagSpoof](https://rabbit-labs.com/product/rabbit-labs-multi-pass-magspoof-flipper-board/) +- [astro's](https://cyberpa.ws/) [flipspoof](https://www.tindie.com/products/astrowave/flipper-zero-magspoof-module/) +- [Electronic Cats'](https://electroniccats.com) [Magspoof](https://electroniccats.com/store/flipper-add-on-magspoof/) and [Marauder_Spoof](https://electroniccats.com/store/flipper-add-on-marauder_spoof/) + +> [!IMPORTANT] +> The linked boards ***do not read magstripes***, they solely ***emulate***. + +> [!TIP] +> Positioning can be finicky, especially on readers with significant EMF shielding. Situating the corner of one's coil over the read-head tends to give the most consistent results; try a few different angles / depths / positions until you find the sweet spot for your module. Wiring diagram +A7, A6, and A4 are the default pins used by the app, but can be changed in the app's settings for custom boards. + +## Skunkworks and Experimental Features +Additional efforts have been made towards internal TX over the RFID / NFC / RF / Piezo systems. While there has been some success with internal TX being picked up/detected by more compact mag readers such as Square, it typically cannot produce a strong enough field for any reader I've tested to decode/parse all the transmitted data properly; as such, all alternate internal TX options are hidden behind debug mode. Old testing, notes, ideas, and planning can be found in [`NOTES.md`](NOTES.md). + +There exists a `Read` scene in the app courtesy of hummusec. This is untested, and exclusively for use with UART magstripe readers; hence, as with the experimental internal TX, it is locked behind debug mode and intended only for developers. There do not exist any purchase-able / manufactured boards that include a reader. Independently, I am working on creating a general USB host for the Flipper using a MAX3421E; if and when this is completed one will be able to use a generic USB magstripe reader with the app, however, there is still much to do before this is ready. + +> [!CAUTION] +> If using experimental internal TX — while in my testing I've seen no reason to believe this could damage the RFID (or other) hardware, this is inherently using those systems in ways they were neither designed nor intended for; I take no responsibility for fried/bricked Flippers. ----- ## Credits This project interpolates work from [Samy Kamkar](https://github.com/samyk/)'s [original MagSpoof project](https://github.com/samyk/magspoof), [Alexey D. (dunaevai135)](https://github.com/dunaevai135/) & [Alexandr Yaroshevich](https://github.com/AYaro)'s [Flipper hackathon project](https://github.com/dunaevai135/flipperzero-firmware/tree/dev/applications/magspoof), and the [Flipper team](https://github.com/flipperdevices)'s [LF RFID](https://github.com/flipperdevices/flipperzero-firmware/tree/dev/applications/main/lfrfid) and [SubGhz](https://github.com/flipperdevices/flipperzero-firmware/tree/dev/applications/main/subghz) apps. diff --git a/malveke_gba_cartridge/gba_cartridge_app.h b/malveke_gba_cartridge/gba_cartridge_app.h index d2bc5e5e0db..74d6e5f7101 100644 --- a/malveke_gba_cartridge/gba_cartridge_app.h +++ b/malveke_gba_cartridge/gba_cartridge_app.h @@ -24,9 +24,6 @@ #define TAG "GBACartridge" -#define SUBGHZ_APP_EXTENSION ".sub" -#define SUBGHZ_APP_FOLDER ANY_PATH("subghz") - #define MALVEKE_APP_FOLDER_USER "apps_data/malveke" #define MALVEKE_APP_FOLDER EXT_PATH(MALVEKE_APP_FOLDER_USER) #define MALVEKE_APP_FOLDER_ROMS MALVEKE_APP_FOLDER "/roms" diff --git a/meal_pager/docs/changelog.md b/meal_pager/docs/changelog.md index 4863cfca8d3..443593c24da 100644 --- a/meal_pager/docs/changelog.md +++ b/meal_pager/docs/changelog.md @@ -1,3 +1,6 @@ +## v1.8 +- Compatibility Update for OFW 0.103.1-rc and above + ## v1.7 - Added code refactors from xMasterX and WillyJL - Minor update of Readme diff --git a/meal_pager/meal_pager_i.h b/meal_pager/meal_pager_i.h index 24c5a241bff..889b310e732 100644 --- a/meal_pager/meal_pager_i.h +++ b/meal_pager/meal_pager_i.h @@ -23,9 +23,7 @@ #define TAG "Meal_Pager" -#define SUBGHZ_APP_EXTENSION ".sub" -#define SUBGHZ_APP_FOLDER ANY_PATH("subghz") -#define MEAL_PAGER_VERSION "1.7" +#define MEAL_PAGER_VERSION "1.8" typedef struct Meal_PagerTransmit Meal_PagerTransmit; typedef struct SubGhz SubGhz; diff --git a/metronome/application.fam b/metronome/application.fam index 3bf5497a2c7..d81d9052364 100644 --- a/metronome/application.fam +++ b/metronome/application.fam @@ -12,6 +12,6 @@ App( stack_size=2 * 1024, order=20, fap_author="@panki27 & @xMasterX", - fap_version="1.2", + fap_version="1.3", fap_description="Metronome app", ) diff --git a/metronome/metronome.c b/metronome/metronome.c index 3222b091fd9..b7967b65e12 100644 --- a/metronome/metronome.c +++ b/metronome/metronome.c @@ -136,9 +136,9 @@ static void render_callback(Canvas* const canvas, void* ctx) { furi_mutex_release(metronome_state->mutex); } -static void input_callback(InputEvent* input_event, void* context) { - furi_assert(context); - FuriMessageQueue* event_queue = context; +static void input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); + FuriMessageQueue* event_queue = ctx; PluginEvent event = {.type = EventTypeKey, .input = *input_event}; furi_message_queue_put(event_queue, &event, FuriWaitForever); diff --git a/mfkey/application.fam b/mfkey/application.fam index 23bd9a4ad99..6f83eb7658e 100644 --- a/mfkey/application.fam +++ b/mfkey/application.fam @@ -15,7 +15,7 @@ App( fap_icon_assets="images", fap_weburl="https://github.com/noproto/FlipperMfkey", fap_description="MIFARE Classic key recovery tool", - fap_version="2.2", + fap_version="2.7", ) App( @@ -24,4 +24,5 @@ App( entry_point="init_plugin_ep", requires=["mfkey"], sources=["init_plugin.c"], + fal_embedded=True, ) diff --git a/mfkey/crypto1.h b/mfkey/crypto1.h index 7a68d713c46..95696a9b377 100644 --- a/mfkey/crypto1.h +++ b/mfkey/crypto1.h @@ -21,6 +21,8 @@ static inline uint32_t crypt_word(struct Crypto1State* s); static inline void crypt_word_noret(struct Crypto1State* s, uint32_t in, int x); static inline uint32_t crypt_word_ret(struct Crypto1State* s, uint32_t in, int x); static inline void rollback_word_noret(struct Crypto1State* s, uint32_t in, int x); +static inline uint8_t napi_lfsr_rollback_bit(struct Crypto1State* s, uint32_t in, int fb); +static inline uint32_t napi_lfsr_rollback_word(struct Crypto1State* s, uint32_t in, int fb); static const uint8_t lookup1[256] = { 0, 0, 16, 16, 0, 16, 0, 0, 0, 16, 0, 0, 16, 16, 16, 16, 0, 0, 16, 16, 0, 16, 0, 0, @@ -147,6 +149,53 @@ static inline void rollback_word_noret(struct Crypto1State* s, uint32_t in, int return; } +// TODO: +/* +uint32_t rollback_word(struct Crypto1State *s, uint32_t in, int x) { + uint32_t res_ret = 0; + uint8_t ret; + uint32_t feedin, t, next_in; + for (int i = 31; i >= 0; i--) { + next_in = BEBIT(in, i); + s->odd &= 0xffffff; + t = s->odd, s->odd = s->even, s->even = t; + ret = filter(s->odd); + feedin = ret & (!!x); + feedin ^= s->even & 1; + feedin ^= LF_POLY_EVEN & (s->even >>= 1); + feedin ^= LF_POLY_ODD & s->odd; + feedin ^= !!next_in; + s->even |= (evenparity32(feedin)) << 23; + res_ret |= (ret << (24 ^ i)); + } + return res_ret; +} +*/ + +uint8_t napi_lfsr_rollback_bit(struct Crypto1State* s, uint32_t in, int fb) { + int out; + uint8_t ret; + uint32_t t; + s->odd &= 0xffffff; + t = s->odd, s->odd = s->even, s->even = t; + + out = s->even & 1; + out ^= LF_POLY_EVEN & (s->even >>= 1); + out ^= LF_POLY_ODD & s->odd; + out ^= !!in; + out ^= (ret = filter(s->odd)) & !!fb; + + s->even |= evenparity32(out) << 23; + return ret; +} + +uint32_t napi_lfsr_rollback_word(struct Crypto1State* s, uint32_t in, int fb) { + int i; + uint32_t ret = 0; + for(i = 31; i >= 0; --i) ret |= napi_lfsr_rollback_bit(s, BEBIT(in, i), fb) << (i ^ 24); + return ret; +} + static inline uint32_t prng_successor(uint32_t x, uint32_t n) { SWAPENDIAN(x); while(n--) x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31; diff --git a/mfkey/mfkey.c b/mfkey/mfkey.c index 1e90e9a4f43..1c03e218469 100644 --- a/mfkey/mfkey.c +++ b/mfkey/mfkey.c @@ -52,15 +52,18 @@ ((x) = ((x) >> 8 & 0xff00ff) | ((x) & 0xff00ff) << 8, (x) = (x) >> 16 | (x) << 16) //#define SIZEOF(arr) sizeof(arr) / sizeof(*arr) -static int eta_round_time = 56; -static int eta_total_time = 900; +static int eta_round_time = 44; +static int eta_total_time = 705; // MSB_LIMIT: Chunk size (out of 256) static int MSB_LIMIT = 16; int check_state(struct Crypto1State* t, MfClassicNonce* n) { if(!(t->odd | t->even)) return 0; if(n->attack == mfkey32) { - rollback_word_noret(t, 0, 0); + uint32_t rb = (napi_lfsr_rollback_word(t, 0, 0) ^ n->p64); + if(rb != n->ar0_enc) { + return 0; + } rollback_word_noret(t, n->nr0_enc, 1); rollback_word_noret(t, n->uid_xor_nt0, 0); struct Crypto1State temp = {t->odd, t->even}; @@ -419,6 +422,10 @@ void** allocate_blocks(const size_t* block_sizes, int num_blocks) { return block_pointers; } +bool is_full_speed() { + return MSB_LIMIT == 16; +} + bool recover(MfClassicNonce* n, int ks2, unsigned int in, ProgramState* program_state) { bool found = false; const size_t block_sizes[] = {49216, 49216, 5120, 5120, 4096}; @@ -427,9 +434,11 @@ bool recover(MfClassicNonce* n, int ks2, unsigned int in, ProgramState* program_ void** block_pointers = allocate_blocks(block_sizes, num_blocks); if(block_pointers == NULL) { // System has less than the guaranteed amount of RAM (140 KB) - adjust some parameters to run anyway at half speed - eta_round_time *= 2; - eta_total_time *= 2; - MSB_LIMIT /= 2; + if(is_full_speed()) { + //eta_round_time *= 2; + eta_total_time *= 2; + MSB_LIMIT /= 2; + } block_pointers = allocate_blocks(reduced_block_sizes, num_blocks); if(block_pointers == NULL) { // System has less than 70 KB of RAM - should never happen so we don't reduce speed further @@ -532,7 +541,7 @@ void mfkey(ProgramState* program_state) { //FURI_LOG_I(TAG, "Free heap before alloc(): %zub", memmgr_get_free_heap()); Storage* storage = furi_record_open(RECORD_STORAGE); FlipperApplication* app = flipper_application_alloc(storage, firmware_api_interface); - flipper_application_preload(app, APP_DATA_PATH("plugins/mfkey_init_plugin.fal")); + flipper_application_preload(app, APP_ASSETS_PATH("plugins/mfkey_init_plugin.fal")); flipper_application_map_to_memory(app); const FlipperAppPluginDescriptor* app_descriptor = flipper_application_plugin_get_descriptor(app); @@ -721,7 +730,9 @@ static void render_callback(Canvas* const canvas, void* ctx) { } else if(program_state->mfkey_state == Complete) { // TODO: Scrollable list view to see cracked keys if user presses down elements_progress_bar(canvas, 5, 18, 118, 1); - canvas_draw_str_aligned(canvas, 40, 31, AlignLeft, AlignTop, "Complete"); + canvas_set_font(canvas, FontSecondary); + snprintf(draw_str, sizeof(draw_str), "Complete"); + canvas_draw_str_aligned(canvas, 40, 31, AlignLeft, AlignTop, draw_str); snprintf( draw_str, sizeof(draw_str), @@ -756,12 +767,11 @@ static void render_callback(Canvas* const canvas, void* ctx) { furi_mutex_release(program_state->mutex); } -static void input_callback(InputEvent* input_event, void* ctx) { - FuriMessageQueue* event_queue = ctx; +static void input_callback(InputEvent* input_event, void* event_queue) { furi_assert(event_queue); PluginEvent event = {.type = EventTypeKey, .input = *input_event}; - furi_message_queue_put(event_queue, &event, FuriWaitForever); + furi_message_queue_put((FuriMessageQueue*)event_queue, &event, FuriWaitForever); } static void mfkey_state_init(ProgramState* program_state) { diff --git a/mifare_fuzzer/application.fam b/mifare_fuzzer/application.fam index bedca88d22f..327e3b20ed8 100644 --- a/mifare_fuzzer/application.fam +++ b/mifare_fuzzer/application.fam @@ -16,6 +16,6 @@ App( fap_icon_assets="images", fap_author="@spheeere98 @Sil333033", fap_weburl="https://github.com/spheeere98/mifare_fuzzer", - fap_version="1.3", + fap_version="1.4", fap_description="App emulates Mifare Classic cards with various UIDs to check how reader reacts on them", ) diff --git a/mifare_nested/application.fam b/mifare_nested/application.fam index 5d72e246186..f7fc9a2083a 100644 --- a/mifare_nested/application.fam +++ b/mifare_nested/application.fam @@ -18,5 +18,5 @@ App( fap_author="AloneLiberty & xMasterX", fap_description="Recover Mifare Classic keys", fap_weburl="https://github.com/AloneLiberty/FlipperNested", - fap_version="1.6.5", + fap_version="1.6.6", ) diff --git a/mifare_nested/lib/nfclegacy/ST25RFAL002/platform.c b/mifare_nested/lib/nfclegacy/ST25RFAL002/platform.c index 6b9c6f595a2..cc1a1f19366 100644 --- a/mifare_nested/lib/nfclegacy/ST25RFAL002/platform.c +++ b/mifare_nested/lib/nfclegacy/ST25RFAL002/platform.c @@ -49,7 +49,6 @@ void platformSetIrqCallback(PlatformIrqCallback callback) { if(!rfal_platform.thread) { rfal_platform.thread = furi_thread_alloc_ex("RfalIrqDriver", 1024, rfal_platform_irq_thread, NULL); - furi_thread_mark_as_service(rfal_platform.thread); furi_thread_set_priority(rfal_platform.thread, FuriThreadPriorityIsr); furi_thread_start(rfal_platform.thread); } diff --git a/mifare_nested/lib/nfclegacy/helpers/nfc_debug_log.c b/mifare_nested/lib/nfclegacy/helpers/nfc_debug_log.c deleted file mode 100644 index 0bfbc2c62f6..00000000000 --- a/mifare_nested/lib/nfclegacy/helpers/nfc_debug_log.c +++ /dev/null @@ -1,71 +0,0 @@ -#include "nfc_debug_log.h" - -#include -#include - -#define TAG "NfcDebugLog" - -#define NFC_DEBUG_PCAP_FILENAME EXT_PATH("nfc/debug.txt") - -struct NfcDebugLog { - Stream* file_stream; - FuriString* data_str; -}; - -NfcDebugLog* nfc_debug_log_alloc() { - NfcDebugLog* instance = malloc(sizeof(NfcDebugLog)); - - Storage* storage = furi_record_open(RECORD_STORAGE); - instance->file_stream = buffered_file_stream_alloc(storage); - - if(!buffered_file_stream_open( - instance->file_stream, NFC_DEBUG_PCAP_FILENAME, FSAM_WRITE, FSOM_OPEN_APPEND)) { - buffered_file_stream_close(instance->file_stream); - stream_free(instance->file_stream); - instance->file_stream = NULL; - } - - if(!instance->file_stream) { - free(instance); - instance = NULL; - } else { - instance->data_str = furi_string_alloc(); - } - furi_record_close(RECORD_STORAGE); - - return instance; -} - -void nfc_debug_log_free(NfcDebugLog* instance) { - furi_assert(instance); - furi_assert(instance->file_stream); - furi_assert(instance->data_str); - - buffered_file_stream_close(instance->file_stream); - stream_free(instance->file_stream); - furi_string_free(instance->data_str); - - free(instance); -} - -void nfc_debug_log_process_data( - NfcDebugLog* instance, - uint8_t* data, - uint16_t len, - bool reader_to_tag, - bool crc_dropped) { - furi_assert(instance); - furi_assert(instance->file_stream); - furi_assert(instance->data_str); - furi_assert(data); - UNUSED(crc_dropped); - - furi_string_printf(instance->data_str, "%lu %c:", furi_get_tick(), reader_to_tag ? 'R' : 'T'); - uint16_t data_len = len; - for(size_t i = 0; i < data_len; i++) { - furi_string_cat_printf(instance->data_str, " %02x", data[i]); - } - furi_string_push_back(instance->data_str, '\n'); - - stream_write_string(instance->file_stream, instance->data_str); -} diff --git a/mifare_nested/lib/nfclegacy/helpers/nfc_debug_log.h b/mifare_nested/lib/nfclegacy/helpers/nfc_debug_log.h deleted file mode 100644 index 261b8008b8e..00000000000 --- a/mifare_nested/lib/nfclegacy/helpers/nfc_debug_log.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include -#include - -typedef struct NfcDebugLog NfcDebugLog; - -NfcDebugLog* nfc_debug_log_alloc(); - -void nfc_debug_log_free(NfcDebugLog* instance); - -void nfc_debug_log_process_data( - NfcDebugLog* instance, - uint8_t* data, - uint16_t len, - bool reader_to_tag, - bool crc_dropped); diff --git a/mifare_nested/lib/nfclegacy/helpers/nfc_debug_pcap.c b/mifare_nested/lib/nfclegacy/helpers/nfc_debug_pcap.c deleted file mode 100644 index 10b19994c51..00000000000 --- a/mifare_nested/lib/nfclegacy/helpers/nfc_debug_pcap.c +++ /dev/null @@ -1,128 +0,0 @@ -#include "nfc_debug_pcap.h" - -#include -#include -#include "../furi_hal_nfc.h" -#include - -#define TAG "NfcDebugPcap" - -#define PCAP_MAGIC 0xa1b2c3d4 -#define PCAP_MAJOR 2 -#define PCAP_MINOR 4 -#define DLT_ISO_14443 264 - -#define DATA_PICC_TO_PCD 0xFF -#define DATA_PCD_TO_PICC 0xFE -#define DATA_PICC_TO_PCD_CRC_DROPPED 0xFB -#define DATA_PCD_TO_PICC_CRC_DROPPED 0xFA - -#define NFC_DEBUG_PCAP_FILENAME EXT_PATH("nfc/debug.pcap") - -struct NfcDebugPcap { - Stream* file_stream; -}; - -static Stream* nfc_debug_pcap_open(Storage* storage) { - Stream* stream = NULL; - stream = buffered_file_stream_alloc(storage); - if(!buffered_file_stream_open(stream, NFC_DEBUG_PCAP_FILENAME, FSAM_WRITE, FSOM_OPEN_APPEND)) { - buffered_file_stream_close(stream); - stream_free(stream); - stream = NULL; - } else { - if(!stream_tell(stream)) { - struct { - uint32_t magic; - uint16_t major, minor; - uint32_t reserved[2]; - uint32_t snaplen; - uint32_t link_type; - } __attribute__((__packed__)) pcap_hdr = { - .magic = PCAP_MAGIC, - .major = PCAP_MAJOR, - .minor = PCAP_MINOR, - .snaplen = FURRY_HAL_NFC_DATA_BUFF_SIZE, - .link_type = DLT_ISO_14443, - }; - if(stream_write(stream, (uint8_t*)&pcap_hdr, sizeof(pcap_hdr)) != sizeof(pcap_hdr)) { - FURI_LOG_E(TAG, "Failed to write pcap header"); - buffered_file_stream_close(stream); - stream_free(stream); - stream = NULL; - } - } - } - return stream; -} - -NfcDebugPcap* nfc_debug_pcap_alloc() { - NfcDebugPcap* instance = malloc(sizeof(NfcDebugPcap)); - - Storage* storage = furi_record_open(RECORD_STORAGE); - instance->file_stream = nfc_debug_pcap_open(storage); - if(!instance->file_stream) { - free(instance); - instance = NULL; - } - furi_record_close(RECORD_STORAGE); - - return instance; -} - -void nfc_debug_pcap_free(NfcDebugPcap* instance) { - furi_assert(instance); - furi_assert(instance->file_stream); - - buffered_file_stream_close(instance->file_stream); - stream_free(instance->file_stream); - - free(instance); -} - -void nfc_debug_pcap_process_data( - NfcDebugPcap* instance, - uint8_t* data, - uint16_t len, - bool reader_to_tag, - bool crc_dropped) { - furi_assert(instance); - furi_assert(data); - - uint8_t event = 0; - if(reader_to_tag) { - if(crc_dropped) { - event = DATA_PCD_TO_PICC_CRC_DROPPED; - } else { - event = DATA_PCD_TO_PICC; - } - } else { - if(crc_dropped) { - event = DATA_PICC_TO_PCD_CRC_DROPPED; - } else { - event = DATA_PICC_TO_PCD; - } - } - - struct { - // https://wiki.wireshark.org/Development/LibpcapFileFormat#record-packet-header - uint32_t ts_sec; - uint32_t ts_usec; - uint32_t incl_len; - uint32_t orig_len; - // https://www.kaiser.cx/posts/pcap-iso14443/#_packet_data - uint8_t version; - uint8_t event; - uint16_t len; - } __attribute__((__packed__)) pkt_hdr = { - .ts_sec = furi_hal_rtc_get_timestamp(), - .ts_usec = 0, - .incl_len = len + 4, - .orig_len = len + 4, - .version = 0, - .event = event, - .len = len << 8 | len >> 8, - }; - stream_write(instance->file_stream, (uint8_t*)&pkt_hdr, sizeof(pkt_hdr)); - stream_write(instance->file_stream, data, len); -} diff --git a/mifare_nested/lib/nfclegacy/helpers/nfc_debug_pcap.h b/mifare_nested/lib/nfclegacy/helpers/nfc_debug_pcap.h deleted file mode 100644 index eeddc56112c..00000000000 --- a/mifare_nested/lib/nfclegacy/helpers/nfc_debug_pcap.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include -#include - -typedef struct NfcDebugPcap NfcDebugPcap; - -NfcDebugPcap* nfc_debug_pcap_alloc(); - -void nfc_debug_pcap_free(NfcDebugPcap* instance); - -void nfc_debug_pcap_process_data( - NfcDebugPcap* instance, - uint8_t* data, - uint16_t len, - bool reader_to_tag, - bool crc_dropped); diff --git a/mifare_nested/lib/nfclegacy/helpers/nfc_generators.c b/mifare_nested/lib/nfclegacy/helpers/nfc_generators.c deleted file mode 100644 index 5ab6280680b..00000000000 --- a/mifare_nested/lib/nfclegacy/helpers/nfc_generators.c +++ /dev/null @@ -1,548 +0,0 @@ -#include -#include "nfc_generators.h" - -#define NXP_MANUFACTURER_ID (0x04) - -static const uint8_t version_bytes_mf0ulx1[] = {0x00, 0x04, 0x03, 0x00, 0x01, 0x00, 0x00, 0x03}; -static const uint8_t version_bytes_ntag21x[] = {0x00, 0x04, 0x04, 0x02, 0x01, 0x00, 0x00, 0x03}; -static const uint8_t version_bytes_ntag_i2c[] = {0x00, 0x04, 0x04, 0x05, 0x02, 0x00, 0x00, 0x03}; -static const uint8_t default_data_ntag203[] = - {0xE1, 0x10, 0x12, 0x00, 0x01, 0x03, 0xA0, 0x10, 0x44, 0x03, 0x00, 0xFE}; -static const uint8_t default_data_ntag213[] = {0x01, 0x03, 0xA0, 0x0C, 0x34, 0x03, 0x00, 0xFE}; -static const uint8_t default_data_ntag215_216[] = {0x03, 0x00, 0xFE}; -static const uint8_t default_data_ntag_i2c[] = {0xE1, 0x10, 0x00, 0x00, 0x03, 0x00, 0xFE}; -static const uint8_t default_config_ntag_i2c[] = {0x01, 0x00, 0xF8, 0x48, 0x08, 0x01, 0x00, 0x00}; - -static void nfc_generate_common_start(NfcDeviceData* data) { - nfc_device_data_clear(data); -} - -static void nfc_generate_mf_ul_uid(uint8_t* uid) { - uid[0] = NXP_MANUFACTURER_ID; - furi_hal_random_fill_buf(&uid[1], 6); - // I'm not sure how this is generated, but the upper nybble always seems to be 8 - uid[6] &= 0x0F; - uid[6] |= 0x80; -} - -static void nfc_generate_mf_classic_uid(uint8_t* uid, uint8_t length) { - uid[0] = NXP_MANUFACTURER_ID; - furi_hal_random_fill_buf(&uid[1], length - 1); -} - -static void nfc_generate_mf_classic_block_0( - uint8_t* block, - uint8_t uid_len, - uint8_t sak, - uint8_t atqa0, - uint8_t atqa1) { - // Block length is always 16 bytes, and the UID can be either 4 or 7 bytes - furi_assert(uid_len == 4 || uid_len == 7); - furi_assert(block); - - if(uid_len == 4) { - // Calculate BCC - block[uid_len] = 0; - - for(int i = 0; i < uid_len; i++) { - block[uid_len] ^= block[i]; - } - } else { - uid_len -= 1; - } - - block[uid_len + 1] = sak; - block[uid_len + 2] = atqa0; - block[uid_len + 3] = atqa1; - - for(int i = uid_len + 4; i < 16; i++) { - block[i] = 0xFF; - } -} - -static void nfc_generate_mf_classic_sector_trailer(MfClassicData* data, uint8_t block) { - // All keys are set to FFFF FFFF FFFFh at chip delivery and the bytes 6, 7 and 8 are set to FF0780h. - MfClassicSectorTrailer* sec_tr = (MfClassicSectorTrailer*)data->block[block].value; - sec_tr->access_bits[0] = 0xFF; - sec_tr->access_bits[1] = 0x07; - sec_tr->access_bits[2] = 0x80; - sec_tr->access_bits[3] = 0x69; // Nice - - memset(sec_tr->key_a, 0xff, sizeof(sec_tr->key_a)); - memset(sec_tr->key_b, 0xff, sizeof(sec_tr->key_b)); - - mf_classic_set_block_read(data, block, &data->block[block]); - mf_classic_set_key_found( - data, mf_classic_get_sector_by_block(block), MfClassicKeyA, 0xFFFFFFFFFFFF); - mf_classic_set_key_found( - data, mf_classic_get_sector_by_block(block), MfClassicKeyB, 0xFFFFFFFFFFFF); -} - -static void nfc_generate_mf_ul_common(NfcDeviceData* data) { - data->nfc_data.type = FurryHalNfcTypeA; - data->nfc_data.interface = FurryHalNfcInterfaceRf; - data->nfc_data.uid_len = 7; - nfc_generate_mf_ul_uid(data->nfc_data.uid); - data->nfc_data.atqa[0] = 0x44; - data->nfc_data.atqa[1] = 0x00; - data->nfc_data.sak = 0x00; - data->protocol = NfcDeviceProtocolMifareUl; -} - -static void - nfc_generate_mf_classic_common(NfcDeviceData* data, uint8_t uid_len, MfClassicType type) { - data->nfc_data.type = FurryHalNfcTypeA; - data->nfc_data.interface = FurryHalNfcInterfaceRf; - data->nfc_data.uid_len = uid_len; - data->nfc_data.atqa[0] = 0x44; - data->nfc_data.atqa[1] = 0x00; - data->nfc_data.sak = 0x08; - data->protocol = NfcDeviceProtocolMifareClassic; - data->mf_classic_data.type = type; -} - -static void nfc_generate_calc_bcc(uint8_t* uid, uint8_t* bcc0, uint8_t* bcc1) { - *bcc0 = 0x88 ^ uid[0] ^ uid[1] ^ uid[2]; - *bcc1 = uid[3] ^ uid[4] ^ uid[5] ^ uid[6]; -} - -static void nfc_generate_mf_ul_copy_uid_with_bcc(NfcDeviceData* data) { - MfUltralightData* mful = &data->mf_ul_data; - memcpy(mful->data, data->nfc_data.uid, 3); - memcpy(&mful->data[4], &data->nfc_data.uid[3], 4); - nfc_generate_calc_bcc(data->nfc_data.uid, &mful->data[3], &mful->data[8]); -} - -static void nfc_generate_mf_ul_orig(NfcDeviceData* data) { - nfc_generate_common_start(data); - nfc_generate_mf_ul_common(data); - - MfUltralightData* mful = &data->mf_ul_data; - mful->type = MfUltralightTypeUnknown; - mful->data_size = 16 * 4; - mful->data_read = mful->data_size; - nfc_generate_mf_ul_copy_uid_with_bcc(data); - // TODO: what's internal byte on page 2? - memset(&mful->data[4 * 4], 0xFF, 4); -} - -static void nfc_generate_mf_ul_ntag203(NfcDeviceData* data) { - nfc_generate_common_start(data); - nfc_generate_mf_ul_common(data); - - MfUltralightData* mful = &data->mf_ul_data; - mful->type = MfUltralightTypeNTAG203; - mful->data_size = 42 * 4; - mful->data_read = mful->data_size; - nfc_generate_mf_ul_copy_uid_with_bcc(data); - mful->data[9] = 0x48; // Internal byte - memcpy(&mful->data[3 * 4], default_data_ntag203, sizeof(default_data_ntag203)); -} - -static void nfc_generate_mf_ul_with_config_common(NfcDeviceData* data, uint8_t num_pages) { - nfc_generate_common_start(data); - nfc_generate_mf_ul_common(data); - - MfUltralightData* mful = &data->mf_ul_data; - mful->data_size = num_pages * 4; - mful->data_read = mful->data_size; - nfc_generate_mf_ul_copy_uid_with_bcc(data); - uint16_t config_index = (num_pages - 4) * 4; - mful->data[config_index] = 0x04; // STRG_MOD_EN - mful->data[config_index + 3] = 0xFF; // AUTH0 - mful->data[config_index + 5] = 0x05; // VCTID - memset(&mful->data[config_index + 8], 0xFF, 4); // Default PWD - if(num_pages > 20) mful->data[config_index - 1] = MF_UL_TEARING_FLAG_DEFAULT; -} - -static void nfc_generate_mf_ul_ev1_common(NfcDeviceData* data, uint8_t num_pages) { - nfc_generate_mf_ul_with_config_common(data, num_pages); - MfUltralightData* mful = &data->mf_ul_data; - memcpy(&mful->version, version_bytes_mf0ulx1, sizeof(version_bytes_mf0ulx1)); - for(size_t i = 0; i < 3; ++i) { - mful->tearing[i] = MF_UL_TEARING_FLAG_DEFAULT; - } - // TODO: what's internal byte on page 2? -} - -static void nfc_generate_mf_ul_11(NfcDeviceData* data) { - nfc_generate_mf_ul_ev1_common(data, 20); - MfUltralightData* mful = &data->mf_ul_data; - mful->type = MfUltralightTypeUL11; - mful->version.prod_subtype = 0x01; - mful->version.storage_size = 0x0B; - mful->data[16 * 4] = 0x00; // Low capacitance version does not have STRG_MOD_EN -} - -static void nfc_generate_mf_ul_h11(NfcDeviceData* data) { - nfc_generate_mf_ul_ev1_common(data, 20); - MfUltralightData* mful = &data->mf_ul_data; - mful->type = MfUltralightTypeUL11; - mful->version.prod_subtype = 0x02; - mful->version.storage_size = 0x0B; -} - -static void nfc_generate_mf_ul_21(NfcDeviceData* data) { - nfc_generate_mf_ul_ev1_common(data, 41); - MfUltralightData* mful = &data->mf_ul_data; - mful->type = MfUltralightTypeUL21; - mful->version.prod_subtype = 0x01; - mful->version.storage_size = 0x0E; - mful->data[37 * 4] = 0x00; // Low capacitance version does not have STRG_MOD_EN -} - -static void nfc_generate_mf_ul_h21(NfcDeviceData* data) { - nfc_generate_mf_ul_ev1_common(data, 41); - MfUltralightData* mful = &data->mf_ul_data; - mful->type = MfUltralightTypeUL21; - mful->version.prod_subtype = 0x02; - mful->version.storage_size = 0x0E; -} - -static void nfc_generate_ntag21x_common(NfcDeviceData* data, uint8_t num_pages) { - nfc_generate_mf_ul_with_config_common(data, num_pages); - MfUltralightData* mful = &data->mf_ul_data; - memcpy(&mful->version, version_bytes_ntag21x, sizeof(version_bytes_mf0ulx1)); - mful->data[9] = 0x48; // Internal byte - // Capability container - mful->data[12] = 0xE1; - mful->data[13] = 0x10; -} - -static void nfc_generate_ntag213(NfcDeviceData* data) { - nfc_generate_ntag21x_common(data, 45); - MfUltralightData* mful = &data->mf_ul_data; - mful->type = MfUltralightTypeNTAG213; - mful->version.storage_size = 0x0F; - mful->data[14] = 0x12; - // Default contents - memcpy(&mful->data[16], default_data_ntag213, sizeof(default_data_ntag213)); -} - -static void nfc_generate_ntag215(NfcDeviceData* data) { - nfc_generate_ntag21x_common(data, 135); - MfUltralightData* mful = &data->mf_ul_data; - mful->type = MfUltralightTypeNTAG215; - mful->version.storage_size = 0x11; - mful->data[14] = 0x3E; - // Default contents - memcpy(&mful->data[16], default_data_ntag215_216, sizeof(default_data_ntag215_216)); -} - -static void nfc_generate_ntag216(NfcDeviceData* data) { - nfc_generate_ntag21x_common(data, 231); - MfUltralightData* mful = &data->mf_ul_data; - mful->type = MfUltralightTypeNTAG216; - mful->version.storage_size = 0x13; - mful->data[14] = 0x6D; - // Default contents - memcpy(&mful->data[16], default_data_ntag215_216, sizeof(default_data_ntag215_216)); -} - -static void - nfc_generate_ntag_i2c_common(NfcDeviceData* data, MfUltralightType type, uint16_t num_pages) { - nfc_generate_common_start(data); - nfc_generate_mf_ul_common(data); - - MfUltralightData* mful = &data->mf_ul_data; - mful->type = type; - memcpy(&mful->version, version_bytes_ntag_i2c, sizeof(version_bytes_ntag_i2c)); - mful->data_size = num_pages * 4; - mful->data_read = mful->data_size; - memcpy(mful->data, data->nfc_data.uid, data->nfc_data.uid_len); - mful->data[7] = data->nfc_data.sak; - mful->data[8] = data->nfc_data.atqa[0]; - mful->data[9] = data->nfc_data.atqa[1]; - - uint16_t config_register_page; - uint16_t session_register_page; - - // Sync with mifare_ultralight.c - switch(type) { - case MfUltralightTypeNTAGI2C1K: - config_register_page = 227; - session_register_page = 229; - break; - case MfUltralightTypeNTAGI2C2K: - config_register_page = 481; - session_register_page = 483; - break; - case MfUltralightTypeNTAGI2CPlus1K: - case MfUltralightTypeNTAGI2CPlus2K: - config_register_page = 232; - session_register_page = 234; - break; - default: - furi_crash("Unknown MFUL"); - break; - } - - memcpy( - &mful->data[config_register_page * 4], - default_config_ntag_i2c, - sizeof(default_config_ntag_i2c)); - memcpy( - &mful->data[session_register_page * 4], - default_config_ntag_i2c, - sizeof(default_config_ntag_i2c)); -} - -static void nfc_generate_ntag_i2c_1k(NfcDeviceData* data) { - nfc_generate_ntag_i2c_common(data, MfUltralightTypeNTAGI2C1K, 231); - MfUltralightData* mful = &data->mf_ul_data; - mful->version.prod_ver_minor = 0x01; - mful->version.storage_size = 0x13; - - memcpy(&mful->data[12], default_data_ntag_i2c, sizeof(default_data_ntag_i2c)); - mful->data[14] = 0x6D; // Size of tag in CC -} - -static void nfc_generate_ntag_i2c_2k(NfcDeviceData* data) { - nfc_generate_ntag_i2c_common(data, MfUltralightTypeNTAGI2C2K, 485); - MfUltralightData* mful = &data->mf_ul_data; - mful->version.prod_ver_minor = 0x01; - mful->version.storage_size = 0x15; - - memcpy(&mful->data[12], default_data_ntag_i2c, sizeof(default_data_ntag_i2c)); - mful->data[14] = 0xEA; // Size of tag in CC -} - -static void nfc_generate_ntag_i2c_plus_common( - NfcDeviceData* data, - MfUltralightType type, - uint16_t num_pages) { - nfc_generate_ntag_i2c_common(data, type, num_pages); - - MfUltralightData* mful = &data->mf_ul_data; - uint16_t config_index = 227 * 4; - mful->data[config_index + 3] = 0xFF; // AUTH0 - memset(&mful->data[config_index + 8], 0xFF, 4); // Default PWD -} - -static void nfc_generate_ntag_i2c_plus_1k(NfcDeviceData* data) { - nfc_generate_ntag_i2c_plus_common(data, MfUltralightTypeNTAGI2CPlus1K, 236); - MfUltralightData* mful = &data->mf_ul_data; - mful->version.prod_ver_minor = 0x02; - mful->version.storage_size = 0x13; -} - -static void nfc_generate_ntag_i2c_plus_2k(NfcDeviceData* data) { - nfc_generate_ntag_i2c_plus_common(data, MfUltralightTypeNTAGI2CPlus2K, 492); - MfUltralightData* mful = &data->mf_ul_data; - mful->version.prod_ver_minor = 0x02; - mful->version.storage_size = 0x15; -} - -void nfc_generate_mf_classic_ext( - NfcDeviceData* data, - uint8_t uid_len, - MfClassicType type, - bool random_uid, - uint8_t* uid) { - nfc_generate_common_start(data); - if(random_uid) { - nfc_generate_mf_classic_uid(data->mf_classic_data.block[0].value, uid_len); - } else { - memcpy(data->mf_classic_data.block[0].value, uid, uid_len); - } - nfc_generate_mf_classic_common(data, uid_len, type); - - // Set the UID - if(random_uid) { - data->nfc_data.uid[0] = NXP_MANUFACTURER_ID; - for(int i = 1; i < uid_len; i++) { - data->nfc_data.uid[i] = data->mf_classic_data.block[0].value[i]; - } - } else { - for(int i = 0; i < uid_len; i++) { - data->nfc_data.uid[i] = data->mf_classic_data.block[0].value[i]; - } - } - - MfClassicData* mfc = &data->mf_classic_data; - mf_classic_set_block_read(mfc, 0, &mfc->block[0]); - - if(type == MfClassicType4k) { - // Set every block to 0xFF - for(uint16_t i = 1; i < 256; i += 1) { - if(mf_classic_is_sector_trailer(i)) { - nfc_generate_mf_classic_sector_trailer(mfc, i); - } else { - memset(&mfc->block[i].value, 0xFF, 16); - } - mf_classic_set_block_read(mfc, i, &mfc->block[i]); - } - // Set SAK to 18 - data->nfc_data.sak = 0x18; - } else if(type == MfClassicType1k) { - // Set every block to 0xFF - for(uint16_t i = 1; i < MF_CLASSIC_1K_TOTAL_SECTORS_NUM * 4; i += 1) { - if(mf_classic_is_sector_trailer(i)) { - nfc_generate_mf_classic_sector_trailer(mfc, i); - } else { - memset(&mfc->block[i].value, 0xFF, 16); - } - mf_classic_set_block_read(mfc, i, &mfc->block[i]); - } - // Set SAK to 08 - data->nfc_data.sak = 0x08; - } else if(type == MfClassicTypeMini) { - // Set every block to 0xFF - for(uint16_t i = 1; i < MF_MINI_TOTAL_SECTORS_NUM * 4; i += 1) { - if(mf_classic_is_sector_trailer(i)) { - nfc_generate_mf_classic_sector_trailer(mfc, i); - } else { - memset(&mfc->block[i].value, 0xFF, 16); - } - mf_classic_set_block_read(mfc, i, &mfc->block[i]); - } - // Set SAK to 09 - data->nfc_data.sak = 0x09; - } - - nfc_generate_mf_classic_block_0( - data->mf_classic_data.block[0].value, - uid_len, - data->nfc_data.sak, - data->nfc_data.atqa[0], - data->nfc_data.atqa[1]); - - mfc->type = type; -} - -void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClassicType type) { - uint8_t uid = 0; - nfc_generate_mf_classic_ext(data, uid_len, type, true, &uid); -} - -static void nfc_generate_mf_mini(NfcDeviceData* data) { - nfc_generate_mf_classic(data, 4, MfClassicTypeMini); -} - -static void nfc_generate_mf_classic_1k_4b_uid(NfcDeviceData* data) { - nfc_generate_mf_classic(data, 4, MfClassicType1k); -} - -static void nfc_generate_mf_classic_1k_7b_uid(NfcDeviceData* data) { - nfc_generate_mf_classic(data, 7, MfClassicType1k); -} - -static void nfc_generate_mf_classic_4k_4b_uid(NfcDeviceData* data) { - nfc_generate_mf_classic(data, 4, MfClassicType4k); -} - -static void nfc_generate_mf_classic_4k_7b_uid(NfcDeviceData* data) { - nfc_generate_mf_classic(data, 7, MfClassicType4k); -} - -static const NfcGenerator mf_ul_generator = { - .name = "Mifare Ultralight", - .generator_func = nfc_generate_mf_ul_orig, -}; - -static const NfcGenerator mf_ul_11_generator = { - .name = "Mifare Ultralight EV1 11", - .generator_func = nfc_generate_mf_ul_11, -}; - -static const NfcGenerator mf_ul_h11_generator = { - .name = "Mifare Ultralight EV1 H11", - .generator_func = nfc_generate_mf_ul_h11, -}; - -static const NfcGenerator mf_ul_21_generator = { - .name = "Mifare Ultralight EV1 21", - .generator_func = nfc_generate_mf_ul_21, -}; - -static const NfcGenerator mf_ul_h21_generator = { - .name = "Mifare Ultralight EV1 H21", - .generator_func = nfc_generate_mf_ul_h21, -}; - -static const NfcGenerator ntag203_generator = { - .name = "NTAG203", - .generator_func = nfc_generate_mf_ul_ntag203, -}; - -static const NfcGenerator ntag213_generator = { - .name = "NTAG213", - .generator_func = nfc_generate_ntag213, -}; - -static const NfcGenerator ntag215_generator = { - .name = "NTAG215", - .generator_func = nfc_generate_ntag215, -}; - -static const NfcGenerator ntag216_generator = { - .name = "NTAG216", - .generator_func = nfc_generate_ntag216, -}; - -static const NfcGenerator ntag_i2c_1k_generator = { - .name = "NTAG I2C 1k", - .generator_func = nfc_generate_ntag_i2c_1k, -}; - -static const NfcGenerator ntag_i2c_2k_generator = { - .name = "NTAG I2C 2k", - .generator_func = nfc_generate_ntag_i2c_2k, -}; - -static const NfcGenerator ntag_i2c_plus_1k_generator = { - .name = "NTAG I2C Plus 1k", - .generator_func = nfc_generate_ntag_i2c_plus_1k, -}; - -static const NfcGenerator ntag_i2c_plus_2k_generator = { - .name = "NTAG I2C Plus 2k", - .generator_func = nfc_generate_ntag_i2c_plus_2k, -}; - -static const NfcGenerator mifare_mini_generator = { - .name = "Mifare Mini", - .generator_func = nfc_generate_mf_mini, -}; - -static const NfcGenerator mifare_classic_1k_4b_uid_generator = { - .name = "Mifare Classic 1k 4byte UID", - .generator_func = nfc_generate_mf_classic_1k_4b_uid, -}; - -static const NfcGenerator mifare_classic_1k_7b_uid_generator = { - .name = "Mifare Classic 1k 7byte UID", - .generator_func = nfc_generate_mf_classic_1k_7b_uid, -}; - -static const NfcGenerator mifare_classic_4k_4b_uid_generator = { - .name = "Mifare Classic 4k 4byte UID", - .generator_func = nfc_generate_mf_classic_4k_4b_uid, -}; - -static const NfcGenerator mifare_classic_4k_7b_uid_generator = { - .name = "Mifare Classic 4k 7byte UID", - .generator_func = nfc_generate_mf_classic_4k_7b_uid, -}; - -const NfcGenerator* const nfc_generators[] = { - &mf_ul_generator, - &mf_ul_11_generator, - &mf_ul_h11_generator, - &mf_ul_21_generator, - &mf_ul_h21_generator, - &ntag203_generator, - &ntag213_generator, - &ntag215_generator, - &ntag216_generator, - &ntag_i2c_1k_generator, - &ntag_i2c_2k_generator, - &ntag_i2c_plus_1k_generator, - &ntag_i2c_plus_2k_generator, - &mifare_mini_generator, - &mifare_classic_1k_4b_uid_generator, - &mifare_classic_1k_7b_uid_generator, - &mifare_classic_4k_4b_uid_generator, - &mifare_classic_4k_7b_uid_generator, - NULL, -}; diff --git a/mifare_nested/lib/nfclegacy/helpers/nfc_generators.h b/mifare_nested/lib/nfclegacy/helpers/nfc_generators.h deleted file mode 100644 index 5102d0bc309..00000000000 --- a/mifare_nested/lib/nfclegacy/helpers/nfc_generators.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include "../nfc_device.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void (*NfcGeneratorFunc)(NfcDeviceData* data); - -typedef struct { - const char* name; - NfcGeneratorFunc generator_func; -} NfcGenerator; - -extern const NfcGenerator* const nfc_generators[]; - -void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClassicType type); - -void nfc_generate_mf_classic_ext( - NfcDeviceData* data, - uint8_t uid_len, - MfClassicType type, - bool random_uid, - uint8_t* uid); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/mifare_nested/lib/nfclegacy/helpers/reader_analyzer.c b/mifare_nested/lib/nfclegacy/helpers/reader_analyzer.c deleted file mode 100644 index a3d82c67525..00000000000 --- a/mifare_nested/lib/nfclegacy/helpers/reader_analyzer.c +++ /dev/null @@ -1,265 +0,0 @@ -#include "reader_analyzer.h" -#include "../protocols/nfc_util.h" -#include "../protocols/mifare_classic.h" -#include - -#include "mfkey32.h" -#include "nfc_debug_pcap.h" -#include "nfc_debug_log.h" - -#define TAG "ReaderAnalyzer" - -#define READER_ANALYZER_MAX_BUFF_SIZE (1024) - -typedef struct { - bool reader_to_tag; - bool crc_dropped; - uint16_t len; -} ReaderAnalyzerHeader; - -typedef enum { - ReaderAnalyzerNfcDataMfClassic, -} ReaderAnalyzerNfcData; - -struct ReaderAnalyzer { - FurryHalNfcDevData nfc_data; - - bool alive; - FuriStreamBuffer* stream; - FuriThread* thread; - - ReaderAnalyzerParseDataCallback callback; - void* context; - - ReaderAnalyzerMode mode; - Mfkey32* mfkey32; - NfcDebugLog* debug_log; - NfcDebugPcap* pcap; -}; - -const FurryHalNfcDevData reader_analyzer_nfc_data[] = { - [ReaderAnalyzerNfcDataMfClassic] = - {.sak = 0x08, - .atqa = {0x44, 0x00}, - .interface = FurryHalNfcInterfaceRf, - .type = FurryHalNfcTypeA, - .uid_len = 7, - .uid = {0x04, 0x77, 0x70, 0x2A, 0x23, 0x4F, 0x80}, - .cuid = 0x2A234F80}, -}; - -void reader_analyzer_parse(ReaderAnalyzer* instance, uint8_t* buffer, size_t size) { - if(size < sizeof(ReaderAnalyzerHeader)) return; - - size_t bytes_i = 0; - while(bytes_i < size) { - ReaderAnalyzerHeader* header = (ReaderAnalyzerHeader*)&buffer[bytes_i]; - uint16_t len = header->len; - if(bytes_i + len > size) break; - bytes_i += sizeof(ReaderAnalyzerHeader); - if(instance->mfkey32) { - mfkey32_process_data( - instance->mfkey32, - &buffer[bytes_i], - len, - header->reader_to_tag, - header->crc_dropped); - } - if(instance->pcap) { - nfc_debug_pcap_process_data( - instance->pcap, &buffer[bytes_i], len, header->reader_to_tag, header->crc_dropped); - } - if(instance->debug_log) { - nfc_debug_log_process_data( - instance->debug_log, - &buffer[bytes_i], - len, - header->reader_to_tag, - header->crc_dropped); - } - bytes_i += len; - } -} - -int32_t reader_analyzer_thread(void* context) { - ReaderAnalyzer* reader_analyzer = context; - uint8_t buffer[READER_ANALYZER_MAX_BUFF_SIZE] = {}; - - while(reader_analyzer->alive || !furi_stream_buffer_is_empty(reader_analyzer->stream)) { - size_t ret = furi_stream_buffer_receive( - reader_analyzer->stream, buffer, READER_ANALYZER_MAX_BUFF_SIZE, 50); - if(ret) { - reader_analyzer_parse(reader_analyzer, buffer, ret); - } - } - - return 0; -} - -ReaderAnalyzer* reader_analyzer_alloc() { - ReaderAnalyzer* instance = malloc(sizeof(ReaderAnalyzer)); - - instance->nfc_data = reader_analyzer_nfc_data[ReaderAnalyzerNfcDataMfClassic]; - instance->alive = false; - instance->stream = - furi_stream_buffer_alloc(READER_ANALYZER_MAX_BUFF_SIZE, sizeof(ReaderAnalyzerHeader)); - - instance->thread = - furi_thread_alloc_ex("ReaderAnalyzerWorker", 2048, reader_analyzer_thread, instance); - furi_thread_set_priority(instance->thread, FuriThreadPriorityLow); - - return instance; -} - -static void reader_analyzer_mfkey_callback(Mfkey32Event event, void* context) { - furi_assert(context); - ReaderAnalyzer* instance = context; - - if(event == Mfkey32EventParamCollected) { - if(instance->callback) { - instance->callback(ReaderAnalyzerEventMfkeyCollected, instance->context); - } - } -} - -void reader_analyzer_start(ReaderAnalyzer* instance, ReaderAnalyzerMode mode) { - furi_assert(instance); - - furi_stream_buffer_reset(instance->stream); - if(mode & ReaderAnalyzerModeDebugLog) { - instance->debug_log = nfc_debug_log_alloc(); - } - if(mode & ReaderAnalyzerModeMfkey) { - instance->mfkey32 = mfkey32_alloc(instance->nfc_data.cuid); - if(instance->mfkey32) { - mfkey32_set_callback(instance->mfkey32, reader_analyzer_mfkey_callback, instance); - } - } - if(mode & ReaderAnalyzerModeDebugPcap) { - instance->pcap = nfc_debug_pcap_alloc(); - } - - instance->alive = true; - furi_thread_start(instance->thread); -} - -void reader_analyzer_stop(ReaderAnalyzer* instance) { - furi_assert(instance); - - instance->alive = false; - furi_thread_join(instance->thread); - - if(instance->debug_log) { - nfc_debug_log_free(instance->debug_log); - instance->debug_log = NULL; - } - if(instance->mfkey32) { - mfkey32_free(instance->mfkey32); - instance->mfkey32 = NULL; - } - if(instance->pcap) { - nfc_debug_pcap_free(instance->pcap); - instance->pcap = NULL; - } -} - -void reader_analyzer_free(ReaderAnalyzer* instance) { - furi_assert(instance); - - reader_analyzer_stop(instance); - furi_thread_free(instance->thread); - furi_stream_buffer_free(instance->stream); - free(instance); -} - -void reader_analyzer_set_callback( - ReaderAnalyzer* instance, - ReaderAnalyzerParseDataCallback callback, - void* context) { - furi_assert(instance); - furi_assert(callback); - - instance->callback = callback; - instance->context = context; -} - -NfcProtocol - reader_analyzer_guess_protocol(ReaderAnalyzer* instance, uint8_t* buff_rx, uint16_t len) { - furi_assert(instance); - furi_assert(buff_rx); - UNUSED(len); - NfcProtocol protocol = NfcDeviceProtocolUnknown; - - if((buff_rx[0] == 0x60) || (buff_rx[0] == 0x61)) { - protocol = NfcDeviceProtocolMifareClassic; - } - - return protocol; -} - -FurryHalNfcDevData* reader_analyzer_get_nfc_data(ReaderAnalyzer* instance) { - furi_assert(instance); - instance->nfc_data = reader_analyzer_nfc_data[ReaderAnalyzerNfcDataMfClassic]; - return &instance->nfc_data; -} - -void reader_analyzer_set_nfc_data(ReaderAnalyzer* instance, FurryHalNfcDevData* nfc_data) { - furi_assert(instance); - furi_assert(nfc_data); - - memcpy(&instance->nfc_data, nfc_data, sizeof(FurryHalNfcDevData)); -} - -static void reader_analyzer_write( - ReaderAnalyzer* instance, - uint8_t* data, - uint16_t len, - bool reader_to_tag, - bool crc_dropped) { - ReaderAnalyzerHeader header = { - .reader_to_tag = reader_to_tag, .crc_dropped = crc_dropped, .len = len}; - size_t data_sent = 0; - data_sent = furi_stream_buffer_send( - instance->stream, &header, sizeof(ReaderAnalyzerHeader), FuriWaitForever); - if(data_sent != sizeof(ReaderAnalyzerHeader)) { - FURI_LOG_W(TAG, "Sent %zu out of %zu bytes", data_sent, sizeof(ReaderAnalyzerHeader)); - } - data_sent = furi_stream_buffer_send(instance->stream, data, len, FuriWaitForever); - if(data_sent != len) { - FURI_LOG_W(TAG, "Sent %zu out of %u bytes", data_sent, len); - } -} - -static void - reader_analyzer_write_rx(uint8_t* data, uint16_t bits, bool crc_dropped, void* context) { - UNUSED(crc_dropped); - ReaderAnalyzer* reader_analyzer = context; - uint16_t bytes = bits < 8 ? 1 : bits / 8; - reader_analyzer_write(reader_analyzer, data, bytes, false, crc_dropped); -} - -static void - reader_analyzer_write_tx(uint8_t* data, uint16_t bits, bool crc_dropped, void* context) { - UNUSED(crc_dropped); - ReaderAnalyzer* reader_analyzer = context; - uint16_t bytes = bits < 8 ? 1 : bits / 8; - reader_analyzer_write(reader_analyzer, data, bytes, true, crc_dropped); -} - -void reader_analyzer_prepare_tx_rx( - ReaderAnalyzer* instance, - FurryHalNfcTxRxContext* tx_rx, - bool is_picc) { - furi_assert(instance); - furi_assert(tx_rx); - - if(is_picc) { - tx_rx->sniff_tx = reader_analyzer_write_rx; - tx_rx->sniff_rx = reader_analyzer_write_tx; - } else { - tx_rx->sniff_rx = reader_analyzer_write_rx; - tx_rx->sniff_tx = reader_analyzer_write_tx; - } - - tx_rx->sniff_context = instance; -} diff --git a/mifare_nested/lib/nfclegacy/helpers/reader_analyzer.h b/mifare_nested/lib/nfclegacy/helpers/reader_analyzer.h deleted file mode 100644 index 5b9124a733d..00000000000 --- a/mifare_nested/lib/nfclegacy/helpers/reader_analyzer.h +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#include -#include "../nfc_device.h" - -typedef enum { - ReaderAnalyzerModeDebugLog = 0x01, - ReaderAnalyzerModeMfkey = 0x02, - ReaderAnalyzerModeDebugPcap = 0x04, -} ReaderAnalyzerMode; - -typedef enum { - ReaderAnalyzerEventMfkeyCollected, -} ReaderAnalyzerEvent; - -typedef struct ReaderAnalyzer ReaderAnalyzer; - -typedef void (*ReaderAnalyzerParseDataCallback)(ReaderAnalyzerEvent event, void* context); - -ReaderAnalyzer* reader_analyzer_alloc(); - -void reader_analyzer_free(ReaderAnalyzer* instance); - -void reader_analyzer_set_callback( - ReaderAnalyzer* instance, - ReaderAnalyzerParseDataCallback callback, - void* context); - -void reader_analyzer_start(ReaderAnalyzer* instance, ReaderAnalyzerMode mode); - -void reader_analyzer_stop(ReaderAnalyzer* instance); - -NfcProtocol - reader_analyzer_guess_protocol(ReaderAnalyzer* instance, uint8_t* buff_rx, uint16_t len); - -FurryHalNfcDevData* reader_analyzer_get_nfc_data(ReaderAnalyzer* instance); - -void reader_analyzer_set_nfc_data(ReaderAnalyzer* instance, FurryHalNfcDevData* nfc_data); - -void reader_analyzer_prepare_tx_rx( - ReaderAnalyzer* instance, - FurryHalNfcTxRxContext* tx_rx, - bool is_picc); diff --git a/mifare_nested/lib/nfclegacy/nfc_device.c b/mifare_nested/lib/nfclegacy/nfc_device.c index 47dcea74e20..ee9f1bcd917 100644 --- a/mifare_nested/lib/nfclegacy/nfc_device.c +++ b/mifare_nested/lib/nfclegacy/nfc_device.c @@ -18,7 +18,6 @@ static const uint32_t nfc_keys_file_version = 1; // Protocols format versions static const uint32_t nfc_mifare_classic_data_format_version = 2; -static const uint32_t nfc_mifare_ultralight_data_format_version = 1; NfcDevice* nfc_device_alloc() { NfcDevice* nfc_dev = malloc(sizeof(NfcDevice)); @@ -47,16 +46,8 @@ void nfc_device_free(NfcDevice* nfc_dev) { static void nfc_device_prepare_format_string(NfcDevice* dev, FuriString* format_string) { if(dev->format == NfcDeviceSaveFormatUid) { furi_string_set(format_string, "UID"); - } else if(dev->format == NfcDeviceSaveFormatBankCard) { - furi_string_set(format_string, "Bank card"); - } else if(dev->format == NfcDeviceSaveFormatMifareUl) { - furi_string_set(format_string, nfc_mf_ul_type(dev->dev_data.mf_ul_data.type, true)); } else if(dev->format == NfcDeviceSaveFormatMifareClassic) { furi_string_set(format_string, "Mifare Classic"); - } else if(dev->format == NfcDeviceSaveFormatMifareDesfire) { - furi_string_set(format_string, "Mifare DESFire"); - } else if(dev->format == NfcDeviceSaveFormatNfcV) { - furi_string_set(format_string, "ISO15693"); } else { furi_string_set(format_string, "Unknown"); } @@ -68,172 +59,14 @@ static bool nfc_device_parse_format_string(NfcDevice* dev, FuriString* format_st dev->dev_data.protocol = NfcDeviceProtocolUnknown; return true; } - if(furi_string_start_with_str(format_string, "Bank card")) { - dev->format = NfcDeviceSaveFormatBankCard; - dev->dev_data.protocol = NfcDeviceProtocolEMV; - return true; - } - // Check Mifare Ultralight types - for(MfUltralightType type = MfUltralightTypeUnknown; type < MfUltralightTypeNum; type++) { - if(furi_string_equal(format_string, nfc_mf_ul_type(type, true))) { - dev->format = NfcDeviceSaveFormatMifareUl; - dev->dev_data.protocol = NfcDeviceProtocolMifareUl; - dev->dev_data.mf_ul_data.type = type; - return true; - } - } + // Check Mifare if(furi_string_start_with_str(format_string, "Mifare Classic")) { dev->format = NfcDeviceSaveFormatMifareClassic; dev->dev_data.protocol = NfcDeviceProtocolMifareClassic; return true; } - if(furi_string_start_with_str(format_string, "Mifare DESFire")) { - dev->format = NfcDeviceSaveFormatMifareDesfire; - dev->dev_data.protocol = NfcDeviceProtocolMifareDesfire; - return true; - } - if(furi_string_start_with_str(format_string, "ISO15693")) { - dev->format = NfcDeviceSaveFormatNfcV; - dev->dev_data.protocol = NfcDeviceProtocolNfcV; - return true; - } - return false; -} - -static bool nfc_device_save_mifare_ul_data(FlipperFormat* file, NfcDevice* dev) { - bool saved = false; - MfUltralightData* data = &dev->dev_data.mf_ul_data; - FuriString* temp_str; - temp_str = furi_string_alloc(); - - // Save Mifare Ultralight specific data - do { - if(!flipper_format_write_comment_cstr(file, "Mifare Ultralight specific data")) break; - if(!flipper_format_write_uint32( - file, "Data format version", &nfc_mifare_ultralight_data_format_version, 1)) - break; - if(!flipper_format_write_hex(file, "Signature", data->signature, sizeof(data->signature))) - break; - if(!flipper_format_write_hex( - file, "Mifare version", (uint8_t*)&data->version, sizeof(data->version))) - break; - // Write conters and tearing flags data - bool counters_saved = true; - for(uint8_t i = 0; i < 3; i++) { - furi_string_printf(temp_str, "Counter %d", i); - if(!flipper_format_write_uint32( - file, furi_string_get_cstr(temp_str), &data->counter[i], 1)) { - counters_saved = false; - break; - } - furi_string_printf(temp_str, "Tearing %d", i); - if(!flipper_format_write_hex( - file, furi_string_get_cstr(temp_str), &data->tearing[i], 1)) { - counters_saved = false; - break; - } - } - if(!counters_saved) break; - // Write pages data - uint32_t pages_total = data->data_size / 4; - if(!flipper_format_write_uint32(file, "Pages total", &pages_total, 1)) break; - uint32_t pages_read = data->data_read / 4; - if(!flipper_format_write_uint32(file, "Pages read", &pages_read, 1)) break; - bool pages_saved = true; - for(uint16_t i = 0; i < data->data_size; i += 4) { - furi_string_printf(temp_str, "Page %d", i / 4); - if(!flipper_format_write_hex(file, furi_string_get_cstr(temp_str), &data->data[i], 4)) { - pages_saved = false; - break; - } - } - if(!pages_saved) break; - - // Write authentication counter - uint32_t auth_counter = data->curr_authlim; - if(!flipper_format_write_uint32(file, "Failed authentication attempts", &auth_counter, 1)) - break; - - saved = true; - } while(false); - - furi_string_free(temp_str); - return saved; -} - -bool nfc_device_load_mifare_ul_data(FlipperFormat* file, NfcDevice* dev) { - bool parsed = false; - MfUltralightData* data = &dev->dev_data.mf_ul_data; - FuriString* temp_str; - temp_str = furi_string_alloc(); - uint32_t data_format_version = 0; - - do { - // Read Mifare Ultralight format version - if(!flipper_format_read_uint32(file, "Data format version", &data_format_version, 1)) { - if(!flipper_format_rewind(file)) break; - } - - // Read signature - if(!flipper_format_read_hex(file, "Signature", data->signature, sizeof(data->signature))) - break; - // Read Mifare version - if(!flipper_format_read_hex( - file, "Mifare version", (uint8_t*)&data->version, sizeof(data->version))) - break; - // Read counters and tearing flags - bool counters_parsed = true; - for(uint8_t i = 0; i < 3; i++) { - furi_string_printf(temp_str, "Counter %d", i); - if(!flipper_format_read_uint32( - file, furi_string_get_cstr(temp_str), &data->counter[i], 1)) { - counters_parsed = false; - break; - } - furi_string_printf(temp_str, "Tearing %d", i); - if(!flipper_format_read_hex( - file, furi_string_get_cstr(temp_str), &data->tearing[i], 1)) { - counters_parsed = false; - break; - } - } - if(!counters_parsed) break; - // Read pages - uint32_t pages_total = 0; - if(!flipper_format_read_uint32(file, "Pages total", &pages_total, 1)) break; - uint32_t pages_read = 0; - if(data_format_version < nfc_mifare_ultralight_data_format_version) { - pages_read = pages_total; - } else { - if(!flipper_format_read_uint32(file, "Pages read", &pages_read, 1)) break; - } - data->data_size = pages_total * 4; - data->data_read = pages_read * 4; - if(data->data_size > MF_UL_MAX_DUMP_SIZE || data->data_read > MF_UL_MAX_DUMP_SIZE) break; - bool pages_parsed = true; - for(uint16_t i = 0; i < pages_total; i++) { - furi_string_printf(temp_str, "Page %d", i); - if(!flipper_format_read_hex( - file, furi_string_get_cstr(temp_str), &data->data[i * 4], 4)) { - pages_parsed = false; - break; - } - } - if(!pages_parsed) break; - - // Read authentication counter - uint32_t auth_counter; - if(!flipper_format_read_uint32(file, "Failed authentication attempts", &auth_counter, 1)) - auth_counter = 0; - data->curr_authlim = auth_counter; - - data->auth_success = mf_ul_is_full_capture(data); - - parsed = true; - } while(false); - furi_string_free(temp_str); - return parsed; + return false; } static void nfc_device_write_mifare_classic_block( @@ -626,19 +459,17 @@ bool nfc_device_save(NfcDevice* dev, const char* dev_name) { if(!flipper_format_write_comment_cstr(file, "UID is common for all formats")) break; if(!flipper_format_write_hex(file, "UID", data->uid, data->uid_len)) break; - if(dev->format != NfcDeviceSaveFormatNfcV) { - // Write ATQA, SAK - if(!flipper_format_write_comment_cstr(file, "ISO14443 specific fields")) break; - // Save ATQA in MSB order for correct companion apps display - uint8_t atqa[2] = {data->atqa[1], data->atqa[0]}; - if(!flipper_format_write_hex(file, "ATQA", atqa, 2)) break; - if(!flipper_format_write_hex(file, "SAK", &data->sak, 1)) break; - } + //if(dev->format != NfcDeviceSaveFormatNfcV) { + // Write ATQA, SAK + if(!flipper_format_write_comment_cstr(file, "ISO14443 specific fields")) break; + // Save ATQA in MSB order for correct companion apps display + uint8_t atqa[2] = {data->atqa[1], data->atqa[0]}; + if(!flipper_format_write_hex(file, "ATQA", atqa, 2)) break; + if(!flipper_format_write_hex(file, "SAK", &data->sak, 1)) break; + //} // Save more data if necessary - if(dev->format == NfcDeviceSaveFormatMifareUl) { - if(!nfc_device_save_mifare_ul_data(file, dev)) break; - } else if(dev->format == NfcDeviceSaveFormatMifareClassic) { + if(dev->format == NfcDeviceSaveFormatMifareClassic) { // Save data if(!nfc_device_save_mifare_classic_data(file, dev)) break; // Save keys cache @@ -716,17 +547,17 @@ static bool nfc_device_load_data(NfcDevice* dev, FuriString* path, bool show_dia if(!(data_cnt == 4 || data_cnt == 7 || data_cnt == 8)) break; data->uid_len = data_cnt; if(!flipper_format_read_hex(file, "UID", data->uid, data->uid_len)) break; - if(dev->format != NfcDeviceSaveFormatNfcV) { - if(version == version_with_lsb_atqa) { - if(!flipper_format_read_hex(file, "ATQA", data->atqa, 2)) break; - } else { - uint8_t atqa[2] = {}; - if(!flipper_format_read_hex(file, "ATQA", atqa, 2)) break; - data->atqa[0] = atqa[1]; - data->atqa[1] = atqa[0]; - } - if(!flipper_format_read_hex(file, "SAK", &data->sak, 1)) break; + //if(dev->format != NfcDeviceSaveFormatNfcV) { + if(version == version_with_lsb_atqa) { + if(!flipper_format_read_hex(file, "ATQA", data->atqa, 2)) break; + } else { + uint8_t atqa[2] = {}; + if(!flipper_format_read_hex(file, "ATQA", atqa, 2)) break; + data->atqa[0] = atqa[1]; + data->atqa[1] = atqa[0]; } + if(!flipper_format_read_hex(file, "SAK", &data->sak, 1)) break; + //} // Load CUID uint8_t* cuid_start = data->uid; if(data->uid_len == 7) { @@ -735,9 +566,7 @@ static bool nfc_device_load_data(NfcDevice* dev, FuriString* path, bool show_dia data->cuid = (cuid_start[0] << 24) | (cuid_start[1] << 16) | (cuid_start[2] << 8) | (cuid_start[3]); // Parse other data - if(dev->format == NfcDeviceSaveFormatMifareUl) { - if(!nfc_device_load_mifare_ul_data(file, dev)) break; - } else if(dev->format == NfcDeviceSaveFormatMifareClassic) { + if(dev->format == NfcDeviceSaveFormatMifareClassic) { if(!nfc_device_load_mifare_classic_data(file, dev)) break; } parsed = true; @@ -782,8 +611,6 @@ bool nfc_device_load(NfcDevice* dev, const char* file_path, bool show_dialog) { void nfc_device_data_clear(NfcDeviceData* dev_data) { if(dev_data->protocol == NfcDeviceProtocolMifareClassic) { memset(&dev_data->mf_classic_data, 0, sizeof(MfClassicData)); - } else if(dev_data->protocol == NfcDeviceProtocolMifareUl) { - mf_ul_reset(&dev_data->mf_ul_data); } memset(&dev_data->nfc_data, 0, sizeof(FurryHalNfcDevData)); diff --git a/mifare_nested/lib/nfclegacy/nfc_device.h b/mifare_nested/lib/nfclegacy/nfc_device.h index ebfcdaa6282..3b1b468e551 100644 --- a/mifare_nested/lib/nfclegacy/nfc_device.h +++ b/mifare_nested/lib/nfclegacy/nfc_device.h @@ -7,7 +7,6 @@ #include "./furi_hal_nfc.h" #include "helpers/mf_classic_dict.h" -#include "protocols/mifare_ultralight.h" #include "protocols/mifare_classic.h" #ifdef __cplusplus @@ -26,20 +25,12 @@ typedef void (*NfcLoadingCallback)(void* context, bool state); typedef enum { NfcDeviceProtocolUnknown, - NfcDeviceProtocolEMV, - NfcDeviceProtocolMifareUl, NfcDeviceProtocolMifareClassic, - NfcDeviceProtocolMifareDesfire, - NfcDeviceProtocolNfcV } NfcProtocol; typedef enum { NfcDeviceSaveFormatUid, - NfcDeviceSaveFormatBankCard, - NfcDeviceSaveFormatMifareUl, NfcDeviceSaveFormatMifareClassic, - NfcDeviceSaveFormatMifareDesfire, - NfcDeviceSaveFormatNfcV, } NfcDeviceSaveFormat; typedef struct { @@ -55,9 +46,6 @@ typedef struct { typedef enum { NfcReadModeAuto, NfcReadModeMfClassic, - NfcReadModeMfUltralight, - NfcReadModeMfDesfire, - NfcReadModeEMV, NfcReadModeNFCA, } NfcReadMode; @@ -68,10 +56,8 @@ typedef struct { union { NfcReaderRequestData reader_data; NfcMfClassicDictAttackData mf_classic_dict_attack_data; - MfUltralightAuth mf_ul_auth; }; union { - MfUltralightData mf_ul_data; MfClassicData mf_classic_data; }; FuriString* parsed_data; diff --git a/mifare_nested/lib/nfclegacy/nfc_types.c b/mifare_nested/lib/nfclegacy/nfc_types.c index c3ebb7a4636..34a42145db6 100644 --- a/mifare_nested/lib/nfclegacy/nfc_types.c +++ b/mifare_nested/lib/nfclegacy/nfc_types.c @@ -15,47 +15,13 @@ const char* nfc_get_dev_type(FurryHalNfcType type) { } const char* nfc_guess_protocol(NfcProtocol protocol) { - if(protocol == NfcDeviceProtocolEMV) { - return "EMV bank card"; - } else if(protocol == NfcDeviceProtocolMifareUl) { - return "Mifare Ultral/NTAG"; - } else if(protocol == NfcDeviceProtocolMifareClassic) { + if(protocol == NfcDeviceProtocolMifareClassic) { return "Mifare Classic"; - } else if(protocol == NfcDeviceProtocolMifareDesfire) { - return "Mifare DESFire"; } else { return "Unrecognized"; } } -const char* nfc_mf_ul_type(MfUltralightType type, bool full_name) { - if(type == MfUltralightTypeNTAG213) { - return "NTAG213"; - } else if(type == MfUltralightTypeNTAG215) { - return "NTAG215"; - } else if(type == MfUltralightTypeNTAG216) { - return "NTAG216"; - } else if(type == MfUltralightTypeNTAGI2C1K) { - return "NTAG I2C 1K"; - } else if(type == MfUltralightTypeNTAGI2C2K) { - return "NTAG I2C 2K"; - } else if(type == MfUltralightTypeNTAGI2CPlus1K) { - return "NTAG I2C Plus 1K"; - } else if(type == MfUltralightTypeNTAGI2CPlus2K) { - return "NTAG I2C Plus 2K"; - } else if(type == MfUltralightTypeNTAG203) { - return "NTAG203"; - } else if(type == MfUltralightTypeULC) { - return "Mifare Ultralight C"; - } else if(type == MfUltralightTypeUL11 && full_name) { - return "Mifare Ultralight 11"; - } else if(type == MfUltralightTypeUL21 && full_name) { - return "Mifare Ultralight 21"; - } else { - return "Mifare Ultralight"; - } -} - const char* nfc_mf_classic_type(MfClassicType type) { if(type == MfClassicTypeMini) { return "Mifare Mini 0.3K"; diff --git a/mifare_nested/lib/nfclegacy/nfc_types.h b/mifare_nested/lib/nfclegacy/nfc_types.h index 4cdfac50c4e..99506ac4862 100644 --- a/mifare_nested/lib/nfclegacy/nfc_types.h +++ b/mifare_nested/lib/nfclegacy/nfc_types.h @@ -10,8 +10,6 @@ const char* nfc_get_dev_type(FurryHalNfcType type); const char* nfc_guess_protocol(NfcProtocol protocol); -const char* nfc_mf_ul_type(MfUltralightType type, bool full_name); - const char* nfc_mf_classic_type(MfClassicType type); #ifdef __cplusplus diff --git a/mifare_nested/lib/nfclegacy/nfc_worker.c b/mifare_nested/lib/nfclegacy/nfc_worker.c index aebd8b65908..db82a804dba 100644 --- a/mifare_nested/lib/nfclegacy/nfc_worker.c +++ b/mifare_nested/lib/nfclegacy/nfc_worker.c @@ -23,8 +23,6 @@ NfcWorker* nfc_worker_alloc() { } nfc_worker_change_state(nfc_worker, NfcWorkerStateReady); - nfc_worker->reader_analyzer = reader_analyzer_alloc(nfc_worker->storage); - return nfc_worker; } @@ -35,8 +33,6 @@ void nfc_worker_free(NfcWorker* nfc_worker) { furi_record_close(RECORD_STORAGE); - reader_analyzer_free(nfc_worker->reader_analyzer); - free(nfc_worker); } @@ -94,20 +90,14 @@ int32_t nfc_worker_task(void* context) { } } else if(nfc_worker->state == NfcWorkerStateUidEmulate) { nfc_worker_emulate_uid(nfc_worker); - } else if(nfc_worker->state == NfcWorkerStateMfUltralightEmulate) { - nfc_worker_emulate_mf_ultralight(nfc_worker); } else if(nfc_worker->state == NfcWorkerStateMfClassicEmulate) { nfc_worker_emulate_mf_classic(nfc_worker); } else if(nfc_worker->state == NfcWorkerStateMfClassicWrite) { nfc_worker_write_mf_classic(nfc_worker); } else if(nfc_worker->state == NfcWorkerStateMfClassicUpdate) { nfc_worker_update_mf_classic(nfc_worker); - } else if(nfc_worker->state == NfcWorkerStateReadMfUltralightReadAuth) { - nfc_worker_mf_ultralight_read_auth(nfc_worker); } else if(nfc_worker->state == NfcWorkerStateMfClassicDictAttack) { nfc_worker_mf_classic_dict_attack(nfc_worker); - } else if(nfc_worker->state == NfcWorkerStateAnalyzeReader) { - nfc_worker_analyze_reader(nfc_worker); } furry_hal_nfc_sleep(); nfc_worker_change_state(nfc_worker, NfcWorkerStateReady); @@ -115,43 +105,10 @@ int32_t nfc_worker_task(void* context) { return 0; } -static bool nfc_worker_read_mf_ultralight(NfcWorker* nfc_worker, FurryHalNfcTxRxContext* tx_rx) { - bool read_success = false; - MfUltralightReader reader = {}; - MfUltralightData data = {}; - - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - reader_analyzer_prepare_tx_rx(nfc_worker->reader_analyzer, tx_rx, false); - reader_analyzer_start(nfc_worker->reader_analyzer, ReaderAnalyzerModeDebugLog); - } - - do { - furry_hal_nfc_sleep(); - - // Otherwise, try to read as usual - if(!furry_hal_nfc_detect(&nfc_worker->dev_data->nfc_data, 200)) break; - if(!mf_ul_read_card(tx_rx, &reader, &data)) break; - // Copy data - nfc_worker->dev_data->mf_ul_data = data; - read_success = true; - } while(false); - - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - reader_analyzer_stop(nfc_worker->reader_analyzer); - } - - return read_success; -} - static bool nfc_worker_read_mf_classic(NfcWorker* nfc_worker, FurryHalNfcTxRxContext* tx_rx) { furi_assert(nfc_worker->callback); bool read_success = false; - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - reader_analyzer_prepare_tx_rx(nfc_worker->reader_analyzer, tx_rx, false); - reader_analyzer_start(nfc_worker->reader_analyzer, ReaderAnalyzerModeDebugLog); - } - do { // Try to read card with key cache FURI_LOG_I(TAG, "Search for key cache ..."); @@ -166,9 +123,6 @@ static bool nfc_worker_read_mf_classic(NfcWorker* nfc_worker, FurryHalNfcTxRxCon } } while(false); - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - reader_analyzer_stop(nfc_worker->reader_analyzer); - } return read_success; } @@ -177,11 +131,7 @@ static bool nfc_worker_read_nfca(NfcWorker* nfc_worker, FurryHalNfcTxRxContext* bool card_read = false; furry_hal_nfc_sleep(); - if(mf_ul_check_card_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak)) { - FURI_LOG_I(TAG, "Mifare Ultralight / NTAG detected"); - nfc_worker->dev_data->protocol = NfcDeviceProtocolMifareUl; - card_read = nfc_worker_read_mf_ultralight(nfc_worker, tx_rx); - } else if(mf_classic_check_card_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak)) { + if(mf_classic_check_card_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak)) { FURI_LOG_I(TAG, "Mifare Classic detected"); nfc_worker->dev_data->protocol = NfcDeviceProtocolMifareClassic; nfc_worker->dev_data->mf_classic_data.type = @@ -219,18 +169,9 @@ void nfc_worker_read(NfcWorker* nfc_worker) { card_not_detected_notified = false; if(nfc_data->type == FurryHalNfcTypeA) { if(nfc_worker_read_nfca(nfc_worker, &tx_rx)) { - if(dev_data->protocol == NfcDeviceProtocolMifareUl) { - event = NfcWorkerEventReadMfUltralight; - break; - } else if(dev_data->protocol == NfcDeviceProtocolMifareClassic) { + if(dev_data->protocol == NfcDeviceProtocolMifareClassic) { event = NfcWorkerEventReadMfClassicDone; break; - } else if(dev_data->protocol == NfcDeviceProtocolMifareDesfire) { - event = NfcWorkerEventReadMfDesfire; - break; - } else if(dev_data->protocol == NfcDeviceProtocolEMV) { - event = NfcWorkerEventReadBankCard; - break; } else if(dev_data->protocol == NfcDeviceProtocolUnknown) { event = NfcWorkerEventReadUidNfcA; break; @@ -298,13 +239,6 @@ void nfc_worker_read_type(NfcWorker* nfc_worker) { event = NfcWorkerEventReadMfClassicDictAttackRequired; break; } - } else if(read_mode == NfcReadModeMfUltralight) { - FURI_LOG_I(TAG, "Mifare Ultralight / NTAG"); - nfc_worker->dev_data->protocol = NfcDeviceProtocolMifareUl; - if(nfc_worker_read_mf_ultralight(nfc_worker, &tx_rx)) { - event = NfcWorkerEventReadMfUltralight; - break; - } } else if(read_mode == NfcReadModeNFCA) { nfc_worker->dev_data->protocol = NfcDeviceProtocolUnknown; event = NfcWorkerEventReadUidNfcA; @@ -351,50 +285,6 @@ void nfc_worker_emulate_uid(NfcWorker* nfc_worker) { } } -void nfc_worker_mf_ultralight_auth_received_callback(MfUltralightAuth auth, void* context) { - furi_assert(context); - - NfcWorker* nfc_worker = context; - nfc_worker->dev_data->mf_ul_auth = auth; - if(nfc_worker->callback) { - nfc_worker->callback(NfcWorkerEventMfUltralightPwdAuth, nfc_worker->context); - } -} - -void nfc_worker_emulate_mf_ultralight(NfcWorker* nfc_worker) { - FurryHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; - MfUltralightEmulator emulator = {}; - mf_ul_prepare_emulation(&emulator, &nfc_worker->dev_data->mf_ul_data); - - // TODO rework with reader analyzer - emulator.auth_received_callback = nfc_worker_mf_ultralight_auth_received_callback; - emulator.context = nfc_worker; - - rfal_platform_spi_acquire(); - - while(nfc_worker->state == NfcWorkerStateMfUltralightEmulate) { - mf_ul_reset_emulation(&emulator, true); - furry_hal_nfc_emulate_nfca( - nfc_data->uid, - nfc_data->uid_len, - nfc_data->atqa, - nfc_data->sak, - mf_ul_prepare_emulation_response, - &emulator, - 5000); - // Check if data was modified - if(emulator.data_changed) { - nfc_worker->dev_data->mf_ul_data = emulator.data; - if(nfc_worker->callback) { - nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); - } - emulator.data_changed = false; - } - } - - rfal_platform_spi_release(); -} - static bool nfc_worker_mf_get_b_key_from_sector_trailer( FurryHalNfcTxRxContext* tx_rx, uint16_t sector, @@ -642,330 +532,3 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { nfc_worker->callback(NfcWorkerEventAborted, nfc_worker->context); } } - -void nfc_worker_emulate_mf_classic(NfcWorker* nfc_worker) { - FurryHalNfcTxRxContext tx_rx = {}; - FurryHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; - MfClassicEmulator emulator = { - .cuid = nfc_util_bytes2num(&nfc_data->uid[nfc_data->uid_len - 4], 4), - .data = nfc_worker->dev_data->mf_classic_data, - .data_changed = false, - }; - NfcaSignal* nfca_signal = nfca_signal_alloc(); - tx_rx.nfca_signal = nfca_signal; - - rfal_platform_spi_acquire(); - - furry_hal_nfc_listen_start(nfc_data); - while(nfc_worker->state == NfcWorkerStateMfClassicEmulate) { //-V1044 - if(furry_hal_nfc_listen_rx(&tx_rx, 300)) { - if(!mf_classic_emulator(&emulator, &tx_rx, false)) { - furry_hal_nfc_listen_start(nfc_data); - } - } - } - if(emulator.data_changed) { - nfc_worker->dev_data->mf_classic_data = emulator.data; - if(nfc_worker->callback) { - nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); - } - emulator.data_changed = false; - } - - nfca_signal_free(nfca_signal); - - rfal_platform_spi_release(); -} - -void nfc_worker_write_mf_classic(NfcWorker* nfc_worker) { - FurryHalNfcTxRxContext tx_rx = {}; - bool card_found_notified = false; - FurryHalNfcDevData nfc_data = {}; - MfClassicData* src_data = &nfc_worker->dev_data->mf_classic_data; - MfClassicData dest_data = *src_data; - - while(nfc_worker->state == NfcWorkerStateMfClassicWrite) { - if(furry_hal_nfc_detect(&nfc_data, 200)) { - if(!card_found_notified) { - nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context); - card_found_notified = true; - } - furry_hal_nfc_sleep(); - - FURI_LOG_I(TAG, "Check low level nfc data"); - if(memcmp(&nfc_data, &nfc_worker->dev_data->nfc_data, sizeof(FurryHalNfcDevData)) != - 0) { - FURI_LOG_E(TAG, "Wrong card"); - nfc_worker->callback(NfcWorkerEventWrongCard, nfc_worker->context); - break; - } - - FURI_LOG_I(TAG, "Check mf classic type"); - MfClassicType type = - mf_classic_get_classic_type(nfc_data.atqa[0], nfc_data.atqa[1], nfc_data.sak); - if(type != nfc_worker->dev_data->mf_classic_data.type) { - FURI_LOG_E(TAG, "Wrong mf classic type"); - nfc_worker->callback(NfcWorkerEventWrongCard, nfc_worker->context); - break; - } - - // Set blocks not read - mf_classic_set_sector_data_not_read(&dest_data); - FURI_LOG_I(TAG, "Updating card sectors"); - uint8_t total_sectors = mf_classic_get_total_sectors_num(type); - bool write_success = true; - for(uint8_t i = 0; i < total_sectors; i++) { - FURI_LOG_I(TAG, "Reading sector %d", i); - mf_classic_read_sector(&tx_rx, &dest_data, i); - bool old_data_read = mf_classic_is_sector_data_read(src_data, i); - bool new_data_read = mf_classic_is_sector_data_read(&dest_data, i); - if(old_data_read != new_data_read) { - FURI_LOG_E(TAG, "Failed to update sector %d", i); - write_success = false; - break; - } - if(nfc_worker->state != NfcWorkerStateMfClassicWrite) break; - if(!mf_classic_write_sector(&tx_rx, &dest_data, src_data, i)) { - FURI_LOG_E(TAG, "Failed to write %d sector", i); - write_success = false; - break; - } - } - if(nfc_worker->state != NfcWorkerStateMfClassicWrite) break; - if(write_success) { - nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); - break; - } else { - nfc_worker->callback(NfcWorkerEventFail, nfc_worker->context); - break; - } - - } else { - if(card_found_notified) { - nfc_worker->callback(NfcWorkerEventNoCardDetected, nfc_worker->context); - card_found_notified = false; - } - } - furi_delay_ms(300); - } -} - -void nfc_worker_update_mf_classic(NfcWorker* nfc_worker) { - FurryHalNfcTxRxContext tx_rx = {}; - bool card_found_notified = false; - FurryHalNfcDevData nfc_data = {}; - MfClassicData* old_data = &nfc_worker->dev_data->mf_classic_data; - MfClassicData new_data = *old_data; - - while(nfc_worker->state == NfcWorkerStateMfClassicUpdate) { - if(furry_hal_nfc_detect(&nfc_data, 200)) { - if(!card_found_notified) { - nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context); - card_found_notified = true; - } - furry_hal_nfc_sleep(); - - FURI_LOG_I(TAG, "Check low level nfc data"); - if(memcmp(&nfc_data, &nfc_worker->dev_data->nfc_data, sizeof(FurryHalNfcDevData)) != - 0) { - FURI_LOG_E(TAG, "Low level nfc data mismatch"); - nfc_worker->callback(NfcWorkerEventWrongCard, nfc_worker->context); - break; - } - - FURI_LOG_I(TAG, "Check MF classic type"); - MfClassicType type = - mf_classic_get_classic_type(nfc_data.atqa[0], nfc_data.atqa[1], nfc_data.sak); - if(type != nfc_worker->dev_data->mf_classic_data.type) { - FURI_LOG_E(TAG, "MF classic type mismatch"); - nfc_worker->callback(NfcWorkerEventWrongCard, nfc_worker->context); - break; - } - - // Set blocks not read - mf_classic_set_sector_data_not_read(&new_data); - FURI_LOG_I(TAG, "Updating card sectors"); - uint8_t total_sectors = mf_classic_get_total_sectors_num(type); - bool update_success = true; - for(uint8_t i = 0; i < total_sectors; i++) { - FURI_LOG_I(TAG, "Reading sector %d", i); - mf_classic_read_sector(&tx_rx, &new_data, i); - bool old_data_read = mf_classic_is_sector_data_read(old_data, i); - bool new_data_read = mf_classic_is_sector_data_read(&new_data, i); - if(old_data_read != new_data_read) { - FURI_LOG_E(TAG, "Failed to update sector %d", i); - update_success = false; - break; - } - if(nfc_worker->state != NfcWorkerStateMfClassicUpdate) break; - } - if(nfc_worker->state != NfcWorkerStateMfClassicUpdate) break; - - // Check updated data - if(update_success) { - *old_data = new_data; - nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); - break; - } - } else { - if(card_found_notified) { - nfc_worker->callback(NfcWorkerEventNoCardDetected, nfc_worker->context); - card_found_notified = false; - } - } - furi_delay_ms(300); - } -} - -void nfc_worker_mf_ultralight_read_auth(NfcWorker* nfc_worker) { - furi_assert(nfc_worker); - furi_assert(nfc_worker->callback); - - MfUltralightData* data = &nfc_worker->dev_data->mf_ul_data; - FurryHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; - FurryHalNfcTxRxContext tx_rx = {}; - MfUltralightReader reader = {}; - mf_ul_reset(data); - - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - reader_analyzer_prepare_tx_rx(nfc_worker->reader_analyzer, &tx_rx, true); - reader_analyzer_start(nfc_worker->reader_analyzer, ReaderAnalyzerModeDebugLog); - } - - uint32_t key = 0; - uint16_t pack = 0; - while(nfc_worker->state == NfcWorkerStateReadMfUltralightReadAuth) { - furry_hal_nfc_sleep(); - if(furry_hal_nfc_detect(nfc_data, 300) && nfc_data->type == FurryHalNfcTypeA) { - if(mf_ul_check_card_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak)) { - nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context); - if(data->auth_method == MfUltralightAuthMethodManual || - data->auth_method == MfUltralightAuthMethodAuto) { - nfc_worker->callback(NfcWorkerEventMfUltralightPassKey, nfc_worker->context); - key = nfc_util_bytes2num(data->auth_key, 4); - } else if(data->auth_method == MfUltralightAuthMethodAmeebo) { - key = mf_ul_pwdgen_amiibo(nfc_data); - } else if(data->auth_method == MfUltralightAuthMethodXiaomi) { - key = mf_ul_pwdgen_xiaomi(nfc_data); - } else { - FURI_LOG_E(TAG, "Incorrect auth method"); - break; - } - - data->auth_success = mf_ultralight_authenticate(&tx_rx, key, &pack); - - if(!data->auth_success) { - // Reset card - furry_hal_nfc_sleep(); - if(!furry_hal_nfc_activate_nfca(300, NULL)) { - nfc_worker->callback(NfcWorkerEventFail, nfc_worker->context); - break; - } - } - - mf_ul_read_card(&tx_rx, &reader, data); - if(data->auth_success) { - MfUltralightConfigPages* config_pages = mf_ultralight_get_config_pages(data); - if(config_pages != NULL) { - config_pages->auth_data.pwd.value = REVERSE_BYTES_U32(key); - config_pages->auth_data.pack.value = pack; - } - nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); - break; - } else { - nfc_worker->callback(NfcWorkerEventFail, nfc_worker->context); - break; - } - } else { - nfc_worker->callback(NfcWorkerEventWrongCardDetected, nfc_worker->context); - furi_delay_ms(10); - } - } else { - nfc_worker->callback(NfcWorkerEventNoCardDetected, nfc_worker->context); - furi_delay_ms(10); - } - } - - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - reader_analyzer_stop(nfc_worker->reader_analyzer); - } -} - -static void nfc_worker_reader_analyzer_callback(ReaderAnalyzerEvent event, void* context) { - furi_assert(context); - NfcWorker* nfc_worker = context; - - if((nfc_worker->state == NfcWorkerStateAnalyzeReader) && - (event == ReaderAnalyzerEventMfkeyCollected)) { - if(nfc_worker->callback) { - nfc_worker->callback(NfcWorkerEventDetectReaderMfkeyCollected, nfc_worker->context); - } - } -} - -void nfc_worker_analyze_reader(NfcWorker* nfc_worker) { - furi_assert(nfc_worker); - furi_assert(nfc_worker->callback); - - FurryHalNfcTxRxContext tx_rx = {}; - - ReaderAnalyzer* reader_analyzer = nfc_worker->reader_analyzer; - FurryHalNfcDevData* nfc_data = NULL; - if(nfc_worker->dev_data->protocol == NfcDeviceProtocolMifareClassic) { - nfc_data = &nfc_worker->dev_data->nfc_data; - reader_analyzer_set_nfc_data(reader_analyzer, nfc_data); - } else { - nfc_data = reader_analyzer_get_nfc_data(reader_analyzer); - } - MfClassicEmulator emulator = { - .cuid = nfc_util_bytes2num(&nfc_data->uid[nfc_data->uid_len - 4], 4), - .data = nfc_worker->dev_data->mf_classic_data, - .data_changed = false, - }; - NfcaSignal* nfca_signal = nfca_signal_alloc(); - tx_rx.nfca_signal = nfca_signal; - reader_analyzer_prepare_tx_rx(reader_analyzer, &tx_rx, true); - reader_analyzer_start(nfc_worker->reader_analyzer, ReaderAnalyzerModeMfkey); - reader_analyzer_set_callback(reader_analyzer, nfc_worker_reader_analyzer_callback, nfc_worker); - - rfal_platform_spi_acquire(); - - FURI_LOG_D(TAG, "Start reader analyzer"); - - uint8_t reader_no_data_received_cnt = 0; - bool reader_no_data_notified = true; - - while(nfc_worker->state == NfcWorkerStateAnalyzeReader) { - furry_hal_nfc_listen_start(nfc_data); - if(furry_hal_nfc_listen_rx(&tx_rx, 300)) { - if(reader_no_data_notified) { - nfc_worker->callback(NfcWorkerEventDetectReaderDetected, nfc_worker->context); - } - reader_no_data_received_cnt = 0; - reader_no_data_notified = false; - NfcProtocol protocol = - reader_analyzer_guess_protocol(reader_analyzer, tx_rx.rx_data, tx_rx.rx_bits / 8); - if(protocol == NfcDeviceProtocolMifareClassic) { - if(!mf_classic_emulator(&emulator, &tx_rx, true)) { - furry_hal_nfc_listen_start(nfc_data); - } - } - } else { - reader_no_data_received_cnt++; - if(!reader_no_data_notified && (reader_no_data_received_cnt > 5)) { - nfc_worker->callback(NfcWorkerEventDetectReaderLost, nfc_worker->context); - reader_no_data_received_cnt = 0; - reader_no_data_notified = true; - } - FURI_LOG_D(TAG, "No data from reader"); - continue; - } - furi_delay_ms(1); - } - - rfal_platform_spi_release(); - - reader_analyzer_stop(nfc_worker->reader_analyzer); - - nfca_signal_free(nfca_signal); -} diff --git a/mifare_nested/lib/nfclegacy/nfc_worker.h b/mifare_nested/lib/nfclegacy/nfc_worker.h index 7733b791914..70469a489da 100644 --- a/mifare_nested/lib/nfclegacy/nfc_worker.h +++ b/mifare_nested/lib/nfclegacy/nfc_worker.h @@ -15,17 +15,10 @@ typedef enum { // Main worker states NfcWorkerStateRead, NfcWorkerStateUidEmulate, - NfcWorkerStateMfUltralightEmulate, NfcWorkerStateMfClassicEmulate, NfcWorkerStateMfClassicWrite, NfcWorkerStateMfClassicUpdate, - NfcWorkerStateReadMfUltralightReadAuth, NfcWorkerStateMfClassicDictAttack, - NfcWorkerStateAnalyzeReader, - NfcWorkerStateNfcVEmulate, - NfcWorkerStateNfcVUnlock, - NfcWorkerStateNfcVUnlockAndSave, - NfcWorkerStateNfcVSniff, // Debug NfcWorkerStateEmulateApdu, NfcWorkerStateField, @@ -42,13 +35,9 @@ typedef enum { NfcWorkerEventReadUidNfcV, NfcWorkerEventReadUidNfcF, NfcWorkerEventReadUidNfcA, - NfcWorkerEventReadMfUltralight, - NfcWorkerEventReadMfDesfire, NfcWorkerEventReadMfClassicDone, NfcWorkerEventReadMfClassicLoadKeyCache, NfcWorkerEventReadMfClassicDictAttackRequired, - NfcWorkerEventReadBankCard, - NfcWorkerEventReadNfcV, // Nfc worker common events NfcWorkerEventSuccess, @@ -71,17 +60,6 @@ typedef enum { // Write Mifare Classic events NfcWorkerEventWrongCard, - // Detect Reader events - NfcWorkerEventDetectReaderDetected, - NfcWorkerEventDetectReaderLost, - NfcWorkerEventDetectReaderMfkeyCollected, - - // Mifare Ultralight events - NfcWorkerEventMfUltralightPassKey, // NFC worker requesting manual key - NfcWorkerEventMfUltralightPwdAuth, // Reader sent auth command - NfcWorkerEventNfcVPassKey, // NFC worker requesting manual key - NfcWorkerEventNfcVCommandExecuted, - NfcWorkerEventNfcVContentChanged, } NfcWorkerEvent; typedef bool (*NfcWorkerCallback)(NfcWorkerEvent event, void* context); @@ -100,9 +78,6 @@ void nfc_worker_start( void* context); void nfc_worker_stop(NfcWorker* nfc_worker); -void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker); -void nfc_worker_nfcv_emulate(NfcWorker* nfc_worker); -void nfc_worker_nfcv_sniff(NfcWorker* nfc_worker); #ifdef __cplusplus } diff --git a/mifare_nested/lib/nfclegacy/nfc_worker_i.h b/mifare_nested/lib/nfclegacy/nfc_worker_i.h index d0fd50d9cd7..4dd6f94c7fe 100644 --- a/mifare_nested/lib/nfclegacy/nfc_worker_i.h +++ b/mifare_nested/lib/nfclegacy/nfc_worker_i.h @@ -7,10 +7,8 @@ #include "protocols/nfc_util.h" #include "protocols/mifare_common.h" -#include "protocols/mifare_ultralight.h" #include "protocols/mifare_classic.h" #include "protocols/nfca.h" -#include "helpers/reader_analyzer.h" struct NfcWorker { FuriThread* thread; @@ -23,8 +21,6 @@ struct NfcWorker { void* context; NfcWorkerState state; - - ReaderAnalyzer* reader_analyzer; }; void nfc_worker_change_state(NfcWorker* nfc_worker, NfcWorkerState state); @@ -37,8 +33,6 @@ void nfc_worker_read_type(NfcWorker* nfc_worker); void nfc_worker_emulate_uid(NfcWorker* nfc_worker); -void nfc_worker_emulate_mf_ultralight(NfcWorker* nfc_worker); - void nfc_worker_emulate_mf_classic(NfcWorker* nfc_worker); void nfc_worker_write_mf_classic(NfcWorker* nfc_worker); @@ -47,10 +41,4 @@ void nfc_worker_update_mf_classic(NfcWorker* nfc_worker); void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker); -void nfc_worker_mf_ultralight_read_auth(NfcWorker* nfc_worker); - -void nfc_worker_mf_ul_auth_attack(NfcWorker* nfc_worker); - -void nfc_worker_emulate_apdu(NfcWorker* nfc_worker); - -void nfc_worker_analyze_reader(NfcWorker* nfc_worker); +void nfc_worker_emulate_apdu(NfcWorker* nfc_worker); \ No newline at end of file diff --git a/mifare_nested/lib/nfclegacy/pulse_reader/pulse_reader.c b/mifare_nested/lib/nfclegacy/pulse_reader/pulse_reader.c deleted file mode 100644 index 1c3cb4a586f..00000000000 --- a/mifare_nested/lib/nfclegacy/pulse_reader/pulse_reader.c +++ /dev/null @@ -1,236 +0,0 @@ -#include "pulse_reader.h" - -#include -#include -#include -#include - -#include -#include -#include -#include - -struct PulseReader { - uint32_t* timer_buffer; - uint32_t* gpio_buffer; - uint32_t size; - uint32_t pos; - uint32_t timer_value; - uint32_t gpio_value; - uint32_t gpio_mask; - uint32_t unit_multiplier; - uint32_t unit_divider; - uint32_t bit_time; - uint32_t dma_channel; - const GpioPin* gpio; - GpioPull pull; - LL_DMA_InitTypeDef dma_config_timer; - LL_DMA_InitTypeDef dma_config_gpio; -}; - -#define GPIO_PIN_MAP(pin, prefix) \ - (((pin) == (LL_GPIO_PIN_0)) ? prefix##0 : \ - ((pin) == (LL_GPIO_PIN_1)) ? prefix##1 : \ - ((pin) == (LL_GPIO_PIN_2)) ? prefix##2 : \ - ((pin) == (LL_GPIO_PIN_3)) ? prefix##3 : \ - ((pin) == (LL_GPIO_PIN_4)) ? prefix##4 : \ - ((pin) == (LL_GPIO_PIN_5)) ? prefix##5 : \ - ((pin) == (LL_GPIO_PIN_6)) ? prefix##6 : \ - ((pin) == (LL_GPIO_PIN_7)) ? prefix##7 : \ - ((pin) == (LL_GPIO_PIN_8)) ? prefix##8 : \ - ((pin) == (LL_GPIO_PIN_9)) ? prefix##9 : \ - ((pin) == (LL_GPIO_PIN_10)) ? prefix##10 : \ - ((pin) == (LL_GPIO_PIN_11)) ? prefix##11 : \ - ((pin) == (LL_GPIO_PIN_12)) ? prefix##12 : \ - ((pin) == (LL_GPIO_PIN_13)) ? prefix##13 : \ - ((pin) == (LL_GPIO_PIN_14)) ? prefix##14 : \ - prefix##15) - -#define GET_DMAMUX_EXTI_LINE(pin) GPIO_PIN_MAP(pin, LL_DMAMUX_REQ_GEN_EXTI_LINE) - -PulseReader* pulse_reader_alloc(const GpioPin* gpio, uint32_t size) { - PulseReader* signal = malloc(sizeof(PulseReader)); - signal->timer_buffer = malloc(size * sizeof(uint32_t)); - signal->gpio_buffer = malloc(size * sizeof(uint32_t)); - signal->dma_channel = LL_DMA_CHANNEL_4; - signal->gpio = gpio; - signal->pull = GpioPullNo; - signal->size = size; - signal->timer_value = 0; - signal->pos = 0; - - pulse_reader_set_timebase(signal, PulseReaderUnit64MHz); - pulse_reader_set_bittime(signal, 1); - - signal->dma_config_timer.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY; - signal->dma_config_timer.PeriphOrM2MSrcAddress = (uint32_t) & (TIM2->CNT); - signal->dma_config_timer.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; - signal->dma_config_timer.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD; - signal->dma_config_timer.MemoryOrM2MDstAddress = (uint32_t)signal->timer_buffer; - signal->dma_config_timer.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; - signal->dma_config_timer.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD; - signal->dma_config_timer.Mode = LL_DMA_MODE_CIRCULAR; - signal->dma_config_timer.PeriphRequest = - LL_DMAMUX_REQ_GENERATOR0; /* executes LL_DMA_SetPeriphRequest */ - signal->dma_config_timer.Priority = LL_DMA_PRIORITY_VERYHIGH; - - signal->dma_config_gpio.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY; - signal->dma_config_gpio.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; - signal->dma_config_gpio.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD; - signal->dma_config_gpio.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; - signal->dma_config_gpio.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD; - signal->dma_config_gpio.Mode = LL_DMA_MODE_CIRCULAR; - signal->dma_config_gpio.PeriphRequest = - LL_DMAMUX_REQ_GENERATOR0; /* executes LL_DMA_SetPeriphRequest */ - signal->dma_config_gpio.Priority = LL_DMA_PRIORITY_VERYHIGH; - - return signal; -} - -void pulse_reader_set_timebase(PulseReader* signal, PulseReaderUnit unit) { - switch(unit) { - case PulseReaderUnit64MHz: - signal->unit_multiplier = 1; - signal->unit_divider = 1; - break; - case PulseReaderUnitPicosecond: - signal->unit_multiplier = 15625; - signal->unit_divider = 1; - break; - case PulseReaderUnitNanosecond: - signal->unit_multiplier = 15625; - signal->unit_divider = 1000; - break; - case PulseReaderUnitMicrosecond: - signal->unit_multiplier = 15625; - signal->unit_divider = 1000000; - break; - } -} - -void pulse_reader_set_bittime(PulseReader* signal, uint32_t bit_time) { - signal->bit_time = bit_time; -} - -void pulse_reader_set_pull(PulseReader* signal, GpioPull pull) { - signal->pull = pull; -} - -void pulse_reader_free(PulseReader* signal) { - furi_assert(signal); - - free(signal->timer_buffer); - free(signal->gpio_buffer); - free(signal); -} - -uint32_t pulse_reader_samples(PulseReader* signal) { - uint32_t dma_pos = signal->size - (uint32_t)LL_DMA_GetDataLength(DMA1, signal->dma_channel); - - return ((signal->pos + signal->size) - dma_pos) % signal->size; -} - -void pulse_reader_stop(PulseReader* signal) { - LL_DMA_DisableChannel(DMA1, signal->dma_channel); - LL_DMA_DisableChannel(DMA1, signal->dma_channel + 1); - LL_DMAMUX_DisableRequestGen(NULL, LL_DMAMUX_REQ_GEN_0); - LL_TIM_DisableCounter(TIM2); - furi_hal_bus_disable(FuriHalBusTIM2); - furi_hal_gpio_init_simple(signal->gpio, GpioModeAnalog); -} - -void pulse_reader_start(PulseReader* signal) { - /* configure DMA to read from a timer peripheral */ - signal->dma_config_timer.NbData = signal->size; - - signal->dma_config_gpio.PeriphOrM2MSrcAddress = (uint32_t) & (signal->gpio->port->IDR); - signal->dma_config_gpio.MemoryOrM2MDstAddress = (uint32_t)signal->gpio_buffer; - signal->dma_config_gpio.NbData = signal->size; - - furi_hal_bus_enable(FuriHalBusTIM2); - - /* start counter */ - LL_TIM_SetCounterMode(TIM2, LL_TIM_COUNTERMODE_UP); - LL_TIM_SetClockDivision(TIM2, LL_TIM_CLOCKDIVISION_DIV1); - LL_TIM_SetPrescaler(TIM2, 0); - LL_TIM_SetAutoReload(TIM2, 0xFFFFFFFF); - LL_TIM_SetCounter(TIM2, 0); - LL_TIM_EnableCounter(TIM2); - - /* generator 0 gets fed by EXTI_LINEn */ - LL_DMAMUX_SetRequestSignalID( - NULL, LL_DMAMUX_REQ_GEN_0, GET_DMAMUX_EXTI_LINE(signal->gpio->pin)); - /* trigger on rising edge of the interrupt */ - LL_DMAMUX_SetRequestGenPolarity(NULL, LL_DMAMUX_REQ_GEN_0, LL_DMAMUX_REQ_GEN_POL_RISING); - /* now enable request generation again */ - LL_DMAMUX_EnableRequestGen(NULL, LL_DMAMUX_REQ_GEN_0); - - /* we need the EXTI to be configured as interrupt generating line, but no ISR registered */ - furi_hal_gpio_init_ex( - signal->gpio, GpioModeInterruptRiseFall, signal->pull, GpioSpeedVeryHigh, GpioAltFnUnused); - - /* capture current timer */ - signal->pos = 0; - signal->timer_value = TIM2->CNT; - signal->gpio_mask = signal->gpio->pin; - signal->gpio_value = signal->gpio->port->IDR & signal->gpio_mask; - - /* now set up DMA with these settings */ - LL_DMA_Init(DMA1, signal->dma_channel, &signal->dma_config_timer); - LL_DMA_Init(DMA1, signal->dma_channel + 1, &signal->dma_config_gpio); - LL_DMA_EnableChannel(DMA1, signal->dma_channel); - LL_DMA_EnableChannel(DMA1, signal->dma_channel + 1); -} - -uint32_t pulse_reader_receive(PulseReader* signal, int timeout_us) { - uint32_t start_time = DWT->CYCCNT; - uint32_t timeout_ticks = timeout_us * (F_TIM2 / 1000000); - - do { - /* get the DMA's next write position by reading "remaining length" register */ - uint32_t dma_pos = - signal->size - (uint32_t)LL_DMA_GetDataLength(DMA1, signal->dma_channel); - - /* the DMA has advanced in the ringbuffer */ - if(dma_pos != signal->pos) { - uint32_t delta = signal->timer_buffer[signal->pos] - signal->timer_value; - uint32_t last_gpio_value = signal->gpio_value; - - signal->gpio_value = signal->gpio_buffer[signal->pos]; - - /* check if the GPIO really toggled. if not, we lost an edge :( */ - if(((last_gpio_value ^ signal->gpio_value) & signal->gpio_mask) != signal->gpio_mask) { - signal->gpio_value ^= signal->gpio_mask; - return PULSE_READER_LOST_EDGE; - } - signal->timer_value = signal->timer_buffer[signal->pos]; - - signal->pos++; - signal->pos %= signal->size; - - uint32_t delta_unit = 0; - - /* probably larger values, so choose a wider data type */ - if(signal->unit_divider > 1) { - delta_unit = - (uint32_t)((uint64_t)delta * (uint64_t)signal->unit_multiplier / signal->unit_divider); - } else { - delta_unit = delta * signal->unit_multiplier; - } - - /* if to be scaled to bit times, save a few instructions. should be faster */ - if(signal->bit_time > 1) { - return (delta_unit + signal->bit_time / 2) / signal->bit_time; - } - - return delta_unit; - } - - /* check for timeout */ - uint32_t elapsed = DWT->CYCCNT - start_time; - - if(elapsed > timeout_ticks) { - return PULSE_READER_NO_EDGE; - } - } while(true); -} diff --git a/mifare_nested/lib/nfclegacy/pulse_reader/pulse_reader.h b/mifare_nested/lib/nfclegacy/pulse_reader/pulse_reader.h deleted file mode 100644 index 62c5f2fa46d..00000000000 --- a/mifare_nested/lib/nfclegacy/pulse_reader/pulse_reader.h +++ /dev/null @@ -1,122 +0,0 @@ -#pragma once - -#include -#include -#include - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define PULSE_READER_NO_EDGE (0xFFFFFFFFUL) -#define PULSE_READER_LOST_EDGE (0xFFFFFFFEUL) -#define F_TIM2 (64000000UL) - -/** - * unit of the edge durations to return - */ -typedef enum { - PulseReaderUnit64MHz, - PulseReaderUnitPicosecond, - PulseReaderUnitNanosecond, - PulseReaderUnitMicrosecond, -} PulseReaderUnit; - -/* using an anonymous type */ -typedef struct PulseReader PulseReader; - -/** Allocate a PulseReader object - * - * Allocates memory for a ringbuffer and initalizes the object - * - * @param[in] gpio the GPIO to use. will get configured as input. - * @param[in] size number of edges to buffer - */ -PulseReader* pulse_reader_alloc(const GpioPin* gpio, uint32_t size); - -/** Free a PulseReader object - * - * Frees all memory of the given object - * - * @param[in] signal previously allocated PulseReader object. - */ -void pulse_reader_free(PulseReader* signal); - -/** Start signal capturing - * - * Initializes DMA1, TIM2 and DMAMUX_REQ_GEN_0 to automatically capture timer values. - * Ensure that interrupts are always enabled, as the used EXTI line is handled as one. - * - * @param[in] signal previously allocated PulseReader object. - */ -void pulse_reader_start(PulseReader* signal); - -/** Stop signal capturing - * - * Frees DMA1, TIM2 and DMAMUX_REQ_GEN_0 - * - * @param[in] signal previously allocated PulseReader object. - */ -void pulse_reader_stop(PulseReader* signal); - -/** Recevie a sample from ringbuffer - * - * Waits for the specified time until a new edge gets detected. - * If not configured otherwise, the pulse duration will be in picosecond resolution. - * If a bittime was configured, the return value will contain the properly rounded - * number of bit times measured. - * - * @param[in] signal previously allocated PulseReader object. - * @param[in] timeout_us time to wait for a signal [µs] - * - * @returns the scaled value of the pulse duration - */ -uint32_t pulse_reader_receive(PulseReader* signal, int timeout_us); - -/** Get available samples - * - * Get the number of available samples in the ringbuffer - * - * @param[in] signal previously allocated PulseReader object. - * - * @returns the number of samples in buffer - */ -uint32_t pulse_reader_samples(PulseReader* signal); - -/** Set timebase - * - * Set the timebase to be used when returning pulse duration. - * - * @param[in] signal previously allocated PulseReader object. - * @param[in] unit PulseReaderUnit64MHz or PulseReaderUnitPicosecond - */ -void pulse_reader_set_timebase(PulseReader* signal, PulseReaderUnit unit); - -/** Set bit time - * - * Set the number of timebase units per bit. - * When set, the pulse_reader_receive() will return an already rounded - * bit count value instead of the raw duration. - * - * Set to 1 to return duration again. - * - * @param[in] signal previously allocated PulseReader object. - * @param[in] bit_time - */ -void pulse_reader_set_bittime(PulseReader* signal, uint32_t bit_time); - -/** Set GPIO pull direction - * - * Some GPIOs need pulldown, others don't. By default the - * pull direction is GpioPullNo. - * - * @param[in] signal previously allocated PulseReader object. - * @param[in] pull GPIO pull direction - */ -void pulse_reader_set_pull(PulseReader* signal, GpioPull pull); - -#ifdef __cplusplus -} -#endif diff --git a/morse_code/application.fam b/morse_code/application.fam index 0cf89e0ec5b..c8fd767e87e 100644 --- a/morse_code/application.fam +++ b/morse_code/application.fam @@ -11,6 +11,6 @@ App( fap_icon="morse_code_10px.png", fap_category="Media", fap_author="@wh00hw & @xMasterX", - fap_version="1.1", + fap_version="1.2", fap_description="Simple Morse Code parser", ) diff --git a/morse_code/morse_code.c b/morse_code/morse_code.c index 3f96969e7db..bef9132e6da 100644 --- a/morse_code/morse_code.c +++ b/morse_code/morse_code.c @@ -17,7 +17,7 @@ typedef struct { typedef struct { MorseCodeModel* model; - FuriMutex** model_mutex; + FuriMutex* model_mutex; FuriMessageQueue* input_queue; diff --git a/multi_converter/application.fam b/multi_converter/application.fam index 25d7bc4c584..05403e9e142 100644 --- a/multi_converter/application.fam +++ b/multi_converter/application.fam @@ -9,6 +9,6 @@ App( fap_icon="converter_10px.png", fap_category="Tools", fap_author="@theisolinearchip", - fap_version="1.1", + fap_version="1.2", fap_description="A multi-unit converter written with an easy and expandable system for adding new units and conversion methods", ) diff --git a/multi_converter/multi_converter.c b/multi_converter/multi_converter.c index ac7fc94eefc..4c668bb028e 100644 --- a/multi_converter/multi_converter.c +++ b/multi_converter/multi_converter.c @@ -22,8 +22,8 @@ static void multi_converter_render_callback(Canvas* const canvas, void* ctx) { } static void multi_converter_input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); MultiConverterEvent event = {.type = EventTypeKey, .input = *input_event}; furi_message_queue_put(event_queue, &event, FuriWaitForever); diff --git a/multi_fuzzer/.gitignore b/multi_fuzzer/.gitignore index e2a15a10a84..fd6c84ea730 100644 --- a/multi_fuzzer/.gitignore +++ b/multi_fuzzer/.gitignore @@ -1,4 +1,5 @@ dist/* .vscode .clang-format -.editorconfig \ No newline at end of file +.editorconfig +.DS_Store diff --git a/multi_fuzzer/CHANGELOG.md b/multi_fuzzer/CHANGELOG.md index 67ef71b642c..9d4c8a75259 100644 --- a/multi_fuzzer/CHANGELOG.md +++ b/multi_fuzzer/CHANGELOG.md @@ -1,3 +1,5 @@ +## v1.4 +- Fix worker being not in LFRFIDWorkerIdle before next key (limit TD to 0.1) ## v1.3 - New systems in RFID Fuzzer: - IoProxXSF diff --git a/multi_fuzzer/application.fam b/multi_fuzzer/application.fam index 76c97c4120a..b15b82c5b79 100644 --- a/multi_fuzzer/application.fam +++ b/multi_fuzzer/application.fam @@ -14,7 +14,7 @@ App( stack_size=2 * 1024, fap_author="gid9798 xMasterX", fap_weburl="https://github.com/DarkFlippers/Multi_Fuzzer", - fap_version="1.3", + fap_version="1.4", targets=["f7"], fap_description="Fuzzer for ibutton readers", fap_icon="ibutt_10px.png", @@ -45,7 +45,7 @@ App( stack_size=2 * 1024, fap_author="gid9798 xMasterX", fap_weburl="https://github.com/DarkFlippers/Multi_Fuzzer", - fap_version="1.3", + fap_version="1.4", targets=["f7"], fap_description="Fuzzer for lfrfid readers", fap_icon="icons/rfid_10px.png", diff --git a/multi_fuzzer/views/attack.c b/multi_fuzzer/views/attack.c index 4748c36862d..86d2c6d2b22 100644 --- a/multi_fuzzer/views/attack.c +++ b/multi_fuzzer/views/attack.c @@ -438,7 +438,7 @@ FuzzerViewAttack* fuzzer_view_attack_alloc() { FuzzerViewAttackModel * model, { model->time_delay = fuzzer_proto_get_def_idle_time(); - model->time_delay_min = 0; // model->time_delay; + model->time_delay_min = 1; // model->time_delay; model->emu_time = fuzzer_proto_get_def_emu_time(); diff --git a/music_player/.catalog/changelog.md b/music_player/.catalog/changelog.md new file mode 100644 index 00000000000..23f1bb9f52a --- /dev/null +++ b/music_player/.catalog/changelog.md @@ -0,0 +1,8 @@ +## 1.3 + - Replacing the icon with black and white +## 1.2 + - Update API v65.0 +## 1.1 + - An example file moved to app assets +## 1.0 + - Initial release diff --git a/music_player/application.fam b/music_player/application.fam index a7ca945dc3f..6b4ac5c71f1 100644 --- a/music_player/application.fam +++ b/music_player/application.fam @@ -9,8 +9,8 @@ App( ], stack_size=2 * 1024, targets=["f7"], - fap_version="1.1", - fap_icon="music_10px.png", + fap_version="1.3", + fap_icon="music_player_icon_10px.png", fap_category="Media", fap_description="An app to play RTTL music files", fap_icon_assets="icons", diff --git a/music_player/music_10px.png b/music_player/music_10px.png deleted file mode 100644 index d41eb0db8c8..00000000000 Binary files a/music_player/music_10px.png and /dev/null differ diff --git a/music_player/music_player.c b/music_player/music_player.c index 96eb78b9a93..9b70ac02f28 100644 --- a/music_player/music_player.c +++ b/music_player/music_player.c @@ -30,7 +30,7 @@ typedef struct { typedef struct { MusicPlayerModel* model; - FuriMutex** model_mutex; + FuriMutex* model_mutex; FuriMessageQueue* input_queue; diff --git a/music_player/music_player_icon_10px.png b/music_player/music_player_icon_10px.png new file mode 100644 index 00000000000..9dfdfc2decf Binary files /dev/null and b/music_player/music_player_icon_10px.png differ diff --git a/nfc_magic/.catalog/changelog.md b/nfc_magic/.catalog/changelog.md index 3462d7e4c3e..7534dd4cf75 100644 --- a/nfc_magic/.catalog/changelog.md +++ b/nfc_magic/.catalog/changelog.md @@ -1,3 +1,6 @@ +## 1.11 + - Fixed Mifare Ultralight types with latest API update + ## 1.10 - Fixed the user dictionary dictionary attack results being discarded diff --git a/nfc_magic/application.fam b/nfc_magic/application.fam index ed75613c4a1..224740ee585 100644 --- a/nfc_magic/application.fam +++ b/nfc_magic/application.fam @@ -10,7 +10,7 @@ App( ], stack_size=4 * 1024, fap_description="Application for writing to NFC tags with modifiable sector 0", - fap_version="1.10", + fap_version="1.11", fap_icon="assets/125_10px.png", fap_category="NFC", fap_icon_assets="assets", diff --git a/nfc_magic/magic/protocols/gen4/gen4_poller.c b/nfc_magic/magic/protocols/gen4/gen4_poller.c index aab15b3c234..8798e569b8e 100644 --- a/nfc_magic/magic/protocols/gen4/gen4_poller.c +++ b/nfc_magic/magic/protocols/gen4/gen4_poller.c @@ -384,7 +384,7 @@ static NfcCommand gen4_poller_write_mf_ultralight(Gen4Poller* instance) { instance->total_blocks = 64 * 2; break; - case MfUltralightTypeUnknown: + case MfUltralightTypeOrigin: FURI_LOG_D(TAG, "Ultralight type"); instance->config.data_parsed.mfu_mode = Gen4UltralightModeUL; break; diff --git a/nfc_playlist/README.md b/nfc_playlist/README.md index 5c38a3e09a7..56c0a7133a9 100644 --- a/nfc_playlist/README.md +++ b/nfc_playlist/README.md @@ -29,10 +29,5 @@ As i know these firmwares are supported and working if you know any more please - Add NFC Item (Adds the selected nfc item to the currently selected playlist) - Remove NFC Item (Opens a menu allowing you to select a line to remove from the playlist) - View playlist content (Allows you to view the contents of the playlist) -## Development plans/ideas: -Things i would like to add: -- Ability to remove cards from the playlist -These features are not guaranteed to be added but are being looked at as features to add - -Any feedback is welcome and would be very much appreciated +Any feedback is welcome and would be very much appreciated \ No newline at end of file diff --git a/nfc_playlist/application.fam b/nfc_playlist/application.fam index 9532f952769..952ebddd75b 100644 --- a/nfc_playlist/application.fam +++ b/nfc_playlist/application.fam @@ -8,12 +8,12 @@ App( fap_category="NFC", fap_author="@acegoal07", fap_weburl="https://github.com/acegoal07/FlipperZero_NFC_Playlist/tree/main", - fap_version="2.1", + fap_version="2.3", fap_icon_assets="assets", - fap_icon="icon.png", + fap_icon="assets/Playlist_10px.png", fap_private_libs=[ Lib( - name="worker", + name="emulation_worker", ), ], ) diff --git a/nfc_playlist/assets/Playlist_10px.png b/nfc_playlist/assets/Playlist_10px.png new file mode 100644 index 00000000000..baa8785923a Binary files /dev/null and b/nfc_playlist/assets/Playlist_10px.png differ diff --git a/nfc_playlist/assets/unknown_10px.png b/nfc_playlist/assets/unknown_10px.png deleted file mode 100644 index 18d31c67caf..00000000000 Binary files a/nfc_playlist/assets/unknown_10px.png and /dev/null differ diff --git a/nfc_playlist/icon.png b/nfc_playlist/icon.png deleted file mode 100644 index 6bc027111a7..00000000000 Binary files a/nfc_playlist/icon.png and /dev/null differ diff --git a/nfc_playlist/lib/emulation_worker/nfc_playlist_emulation_worker.c b/nfc_playlist/lib/emulation_worker/nfc_playlist_emulation_worker.c new file mode 100644 index 00000000000..79855b49ef2 --- /dev/null +++ b/nfc_playlist/lib/emulation_worker/nfc_playlist_emulation_worker.c @@ -0,0 +1,84 @@ +#include "nfc_playlist_emulation_worker.h" + +NfcPlaylistEmulationWorker* nfc_playlist_emulation_worker_alloc() { + NfcPlaylistEmulationWorker* nfc_playlist_emulation_worker = + malloc(sizeof(NfcPlaylistEmulationWorker)); + nfc_playlist_emulation_worker->thread = furi_thread_alloc_ex( + "NfcPlaylistEmulationWorker", + 4096, + nfc_playlist_emulation_worker_task, + nfc_playlist_emulation_worker); + nfc_playlist_emulation_worker->state = NfcPlaylistEmulationWorkerState_Stopped; + nfc_playlist_emulation_worker->nfc = nfc_alloc(); + nfc_playlist_emulation_worker->nfc_device = nfc_device_alloc(); + return nfc_playlist_emulation_worker; +} + +void nfc_playlist_emulation_worker_free(NfcPlaylistEmulationWorker* nfc_playlist_emulation_worker) { + furi_assert(nfc_playlist_emulation_worker); + furi_thread_free(nfc_playlist_emulation_worker->thread); + nfc_free(nfc_playlist_emulation_worker->nfc); + nfc_device_free(nfc_playlist_emulation_worker->nfc_device); + free(nfc_playlist_emulation_worker); +} + +void nfc_playlist_emulation_worker_stop(NfcPlaylistEmulationWorker* nfc_playlist_emulation_worker) { + furi_assert(nfc_playlist_emulation_worker); + if(nfc_playlist_emulation_worker->state != NfcPlaylistEmulationWorkerState_Stopped) { + nfc_playlist_emulation_worker->state = NfcPlaylistEmulationWorkerState_Stopped; + furi_thread_join(nfc_playlist_emulation_worker->thread); + } +} + +void nfc_playlist_emulation_worker_start( + NfcPlaylistEmulationWorker* nfc_playlist_emulation_worker) { + furi_assert(nfc_playlist_emulation_worker); + nfc_playlist_emulation_worker->state = NfcPlaylistEmulationWorkerState_Emulating; + furi_thread_start(nfc_playlist_emulation_worker->thread); +} + +int32_t nfc_playlist_emulation_worker_task(void* context) { + NfcPlaylistEmulationWorker* nfc_playlist_emulation_worker = context; + + if(nfc_playlist_emulation_worker->state == NfcPlaylistEmulationWorkerState_Emulating) { + nfc_playlist_emulation_worker->nfc_listener = nfc_listener_alloc( + nfc_playlist_emulation_worker->nfc, + nfc_playlist_emulation_worker->nfc_protocol, + nfc_device_get_data( + nfc_playlist_emulation_worker->nfc_device, + nfc_playlist_emulation_worker->nfc_protocol)); + nfc_listener_start(nfc_playlist_emulation_worker->nfc_listener, NULL, NULL); + + while(nfc_playlist_emulation_worker->state == NfcPlaylistEmulationWorkerState_Emulating) { + furi_delay_ms(50); + } + + nfc_listener_stop(nfc_playlist_emulation_worker->nfc_listener); + nfc_listener_free(nfc_playlist_emulation_worker->nfc_listener); + } + + nfc_playlist_emulation_worker->state = NfcPlaylistEmulationWorkerState_Stopped; + + return 0; +} + +bool nfc_playlist_emulation_worker_is_emulating( + NfcPlaylistEmulationWorker* nfc_playlist_emulation_worker) { + furi_assert(nfc_playlist_emulation_worker); + return nfc_playlist_emulation_worker->state == NfcPlaylistEmulationWorkerState_Emulating; +} + +void nfc_playlist_emulation_worker_set_nfc_data( + NfcPlaylistEmulationWorker* nfc_playlist_emulation_worker, + char* file_path) { + furi_assert(nfc_playlist_emulation_worker); + nfc_device_load(nfc_playlist_emulation_worker->nfc_device, file_path); + nfc_playlist_emulation_worker->nfc_protocol = + nfc_device_get_protocol(nfc_playlist_emulation_worker->nfc_device); +} + +void nfc_playlist_emulation_worker_clear_nfc_data( + NfcPlaylistEmulationWorker* nfc_playlist_emulation_worker) { + furi_assert(nfc_playlist_emulation_worker); + nfc_device_clear(nfc_playlist_emulation_worker->nfc_device); +} \ No newline at end of file diff --git a/nfc_playlist/lib/emulation_worker/nfc_playlist_emulation_worker.h b/nfc_playlist/lib/emulation_worker/nfc_playlist_emulation_worker.h new file mode 100644 index 00000000000..baddbff44ac --- /dev/null +++ b/nfc_playlist/lib/emulation_worker/nfc_playlist_emulation_worker.h @@ -0,0 +1,35 @@ +#pragma once +#include +#include +#include +#include +#include + +typedef enum NfcPlaylistEmulationWorkerState { + NfcPlaylistEmulationWorkerState_Emulating, + NfcPlaylistEmulationWorkerState_Stopped +} NfcPlaylistEmulationWorkerState; + +typedef struct NfcPlaylistEmulationWorker { + FuriThread* thread; + NfcPlaylistEmulationWorkerState state; + NfcListener* nfc_listener; + NfcDevice* nfc_device; + NfcProtocol nfc_protocol; + Nfc* nfc; +} NfcPlaylistEmulationWorker; + +NfcPlaylistEmulationWorker* nfc_playlist_emulation_worker_alloc(); +void nfc_playlist_emulation_worker_free(NfcPlaylistEmulationWorker* nfc_playlist_emulation_worker); +void nfc_playlist_emulation_worker_stop(NfcPlaylistEmulationWorker* nfc_playlist_emulation_worker); +void nfc_playlist_emulation_worker_start(NfcPlaylistEmulationWorker* nfc_playlist_emulation_worker); + +int32_t nfc_playlist_emulation_worker_task(void* context); + +bool nfc_playlist_emulation_worker_is_emulating( + NfcPlaylistEmulationWorker* nfc_playlist_emulation_worker); +void nfc_playlist_emulation_worker_set_nfc_data( + NfcPlaylistEmulationWorker* nfc_playlist_emulation_worker, + char* file_path); +void nfc_playlist_emulation_worker_clear_nfc_data( + NfcPlaylistEmulationWorker* nfc_playlist_emulation_worker); \ No newline at end of file diff --git a/nfc_playlist/lib/worker/nfc_playlist_worker.c b/nfc_playlist/lib/worker/nfc_playlist_worker.c deleted file mode 100644 index 8ae0641e2fc..00000000000 --- a/nfc_playlist/lib/worker/nfc_playlist_worker.c +++ /dev/null @@ -1,73 +0,0 @@ -#include "nfc_playlist_worker.h" - -NfcPlaylistWorker* nfc_playlist_worker_alloc() { - NfcPlaylistWorker* nfc_playlist_worker = malloc(sizeof(NfcPlaylistWorker)); - nfc_playlist_worker->thread = furi_thread_alloc_ex("NfcPlaylistWorker", 8192, nfc_playlist_worker_task, nfc_playlist_worker); - nfc_playlist_worker->state = NfcPlaylistWorkerState_Stopped; - nfc_playlist_worker->nfc = nfc_alloc(); - nfc_playlist_worker->nfc_device = nfc_device_alloc(); - return nfc_playlist_worker; -} - -void nfc_playlist_worker_free(NfcPlaylistWorker* nfc_playlist_worker) { - furi_assert(nfc_playlist_worker); - furi_thread_free(nfc_playlist_worker->thread); - nfc_free(nfc_playlist_worker->nfc); - nfc_device_free(nfc_playlist_worker->nfc_device); - free(nfc_playlist_worker); -} - -void nfc_playlist_worker_stop(NfcPlaylistWorker* nfc_playlist_worker) { - furi_assert(nfc_playlist_worker); - if (nfc_playlist_worker->state != NfcPlaylistWorkerState_Stopped) { - nfc_playlist_worker->state = NfcPlaylistWorkerState_Stopped; - furi_thread_join(nfc_playlist_worker->thread); - } -} - -void nfc_playlist_worker_start(NfcPlaylistWorker* nfc_playlist_worker) { - furi_assert(nfc_playlist_worker); - nfc_playlist_worker->state = NfcPlaylistWorkerState_Emulating; - furi_thread_start(nfc_playlist_worker->thread); -} - -int32_t nfc_playlist_worker_task(void* context) { - NfcPlaylistWorker* nfc_playlist_worker = context; - - if (nfc_playlist_worker->state == NfcPlaylistWorkerState_Emulating) { - - nfc_playlist_worker->nfc_listener = - nfc_listener_alloc(nfc_playlist_worker->nfc, - nfc_playlist_worker->nfc_protocol, - nfc_device_get_data(nfc_playlist_worker->nfc_device, nfc_playlist_worker->nfc_protocol) - ); - nfc_listener_start(nfc_playlist_worker->nfc_listener, NULL, NULL); - - while(nfc_playlist_worker->state == NfcPlaylistWorkerState_Emulating) { - furi_delay_ms(50); - } - - nfc_listener_stop(nfc_playlist_worker->nfc_listener); - nfc_listener_free(nfc_playlist_worker->nfc_listener); - } - - nfc_playlist_worker->state = NfcPlaylistWorkerState_Stopped; - - return 0; -} - -bool nfc_playlist_worker_is_emulating(NfcPlaylistWorker* nfc_playlist_worker) { - furi_assert(nfc_playlist_worker); - return nfc_playlist_worker->state == NfcPlaylistWorkerState_Emulating; -} - -void nfc_playlist_worker_set_nfc_data(NfcPlaylistWorker* nfc_playlist_worker, char* file_path) { - furi_assert(nfc_playlist_worker); - nfc_device_load(nfc_playlist_worker->nfc_device, file_path); - nfc_playlist_worker->nfc_protocol = nfc_device_get_protocol(nfc_playlist_worker->nfc_device); -} - -void nfc_playlist_worker_clear_nfc_data(NfcPlaylistWorker* nfc_playlist_worker) { - furi_assert(nfc_playlist_worker); - nfc_device_clear(nfc_playlist_worker->nfc_device); -} \ No newline at end of file diff --git a/nfc_playlist/lib/worker/nfc_playlist_worker.h b/nfc_playlist/lib/worker/nfc_playlist_worker.h deleted file mode 100644 index 511ea7d2991..00000000000 --- a/nfc_playlist/lib/worker/nfc_playlist_worker.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -typedef enum NfcPlaylistWorkerState { - NfcPlaylistWorkerState_Emulating, - NfcPlaylistWorkerState_Stopped -} NfcPlaylistWorkerState; - -typedef struct NfcPlaylistWorker { - FuriThread* thread; - NfcPlaylistWorkerState state; - NfcListener* nfc_listener; - NfcDevice* nfc_device; - NfcProtocol nfc_protocol; - Nfc* nfc; -} NfcPlaylistWorker; - -NfcPlaylistWorker* nfc_playlist_worker_alloc(); -void nfc_playlist_worker_free(NfcPlaylistWorker* nfc_playlist_worker); -void nfc_playlist_worker_stop(NfcPlaylistWorker* nfc_playlist_worker); -void nfc_playlist_worker_start(NfcPlaylistWorker* nfc_playlist_worker); - -int32_t nfc_playlist_worker_task(void* context); - -bool nfc_playlist_worker_is_emulating(NfcPlaylistWorker* nfc_playlist_worker); -void nfc_playlist_worker_set_nfc_data(NfcPlaylistWorker* nfc_playlist_worker, char* file_path); -void nfc_playlist_worker_clear_nfc_data(NfcPlaylistWorker* nfc_playlist_worker); \ No newline at end of file diff --git a/nfc_playlist/nfc_playlist.c b/nfc_playlist/nfc_playlist.c index 2d6bc261188..b5d98542c7a 100644 --- a/nfc_playlist/nfc_playlist.c +++ b/nfc_playlist/nfc_playlist.c @@ -66,9 +66,8 @@ static NfcPlaylist* nfc_playlist_alloc() { text_input_get_view(nfc_playlist->text_input)); Storage* storage = furi_record_open(RECORD_STORAGE); - if(!storage_common_exists(storage, PLAYLIST_DIR)) { - storage_common_mkdir(storage, PLAYLIST_DIR); - } + storage_simply_mkdir(storage, PLAYLIST_DIR); + furi_record_close(RECORD_STORAGE); return nfc_playlist; @@ -86,11 +85,11 @@ static void nfc_playlist_free(NfcPlaylist* nfc_playlist) { scene_manager_free(nfc_playlist->scene_manager); view_dispatcher_free(nfc_playlist->view_dispatcher); + furi_record_close(RECORD_NOTIFICATION); + variable_item_list_free(nfc_playlist->variable_item_list); submenu_free(nfc_playlist->submenu); widget_free(nfc_playlist->widget); - - furi_record_close(RECORD_NOTIFICATION); file_browser_free(nfc_playlist->file_browser); text_input_free(nfc_playlist->text_input); popup_free(nfc_playlist->popup); @@ -150,10 +149,15 @@ const NotificationSequence blink_sequence_error = { void start_blink(NfcPlaylist* nfc_playlist, int state) { if(nfc_playlist->settings.emulate_led_indicator) { - if(state == NfcPlaylistLedState_Normal) { + switch(state) { + case NfcPlaylistLedState_Normal: notification_message_block(nfc_playlist->notification, &blink_sequence_normal); - } else if(state == NfcPlaylistLedState_Error) { + break; + case NfcPlaylistLedState_Error: notification_message_block(nfc_playlist->notification, &blink_sequence_error); + break; + default: + break; } } } diff --git a/nfc_playlist/nfc_playlist.h b/nfc_playlist/nfc_playlist.h index bd271a9d489..9625109eba7 100644 --- a/nfc_playlist/nfc_playlist.h +++ b/nfc_playlist/nfc_playlist.h @@ -23,11 +23,16 @@ #include #include +#include -#include "lib/worker/nfc_playlist_worker.h" +#include "lib/emulation_worker/nfc_playlist_emulation_worker.h" #include "scenes/nfc_playlist_scene.h" +#define PLAYLIST_LOCATION "/ext/apps_data/nfc_playlist/" +#define PLAYLIST_DIR "/ext/apps_data/nfc_playlist" +#define MAX_PLAYLIST_NAME_LEN 50 + typedef enum { NfcPlaylistView_Submenu, NfcPlaylistView_Popup, @@ -60,8 +65,7 @@ typedef struct { char* text_input_output; NotificationApp* notification; FuriThread* thread; - FuriString* temp_furi_string; - NfcPlaylistWorker* nfc_playlist_worker; + NfcPlaylistEmulationWorker* nfc_playlist_emulation_worker; NfcPlaylistSettings settings; } NfcPlaylist; @@ -72,9 +76,6 @@ static const int default_emulate_delay = 0; static const bool default_emulate_led_indicator = true; static const bool default_skip_error = false; -#define PLAYLIST_LOCATION "/ext/apps_data/nfc_playlist/" -#define PLAYLIST_DIR "/ext/apps_data/nfc_playlist" - typedef enum NfcPlaylistLedState { NfcPlaylistLedState_Normal, NfcPlaylistLedState_Error diff --git a/nfc_playlist/scenes/nfc_playlist_scene_config.h b/nfc_playlist/scenes/nfc_playlist_scene_config.h index 37d4215c82d..043dc64634e 100644 --- a/nfc_playlist/scenes/nfc_playlist_scene_config.h +++ b/nfc_playlist/scenes/nfc_playlist_scene_config.h @@ -4,7 +4,7 @@ ADD_SCENE(nfc_playlist, playlist_edit, PlaylistEdit) ADD_SCENE(nfc_playlist, playlist_rename, PlaylistRename) ADD_SCENE(nfc_playlist, main_menu, MainMenu) ADD_SCENE(nfc_playlist, name_new_playlist, NameNewPlaylist) -ADD_SCENE(nfc_playlist, nfc_select, NfcSelect) +ADD_SCENE(nfc_playlist, nfc_add, NfcAdd) ADD_SCENE(nfc_playlist, nfc_remove, NfcRemove) ADD_SCENE(nfc_playlist, playlist_select, PlaylistSelect) ADD_SCENE(nfc_playlist, settings, Settings) diff --git a/nfc_playlist/scenes/nfc_playlist_scene_confirm_delete.c b/nfc_playlist/scenes/nfc_playlist_scene_confirm_delete.c index 41fa831f9b2..a0dcd68f0e9 100644 --- a/nfc_playlist/scenes/nfc_playlist_scene_confirm_delete.c +++ b/nfc_playlist/scenes/nfc_playlist_scene_confirm_delete.c @@ -10,13 +10,12 @@ void nfc_playlist_confirm_delete_menu_callback(GuiButtonType result, InputType t void nfc_playlist_confirm_delete_scene_on_enter(void* context) { NfcPlaylist* nfc_playlist = context; - FuriString* temp_str = furi_string_alloc(); - char* file_path = (char*)furi_string_get_cstr(nfc_playlist->settings.playlist_path); - furi_string_printf( - temp_str, - "\e#Delete %s?\e#", - strchr(file_path, '/') != NULL ? &strrchr(file_path, '/')[1] : file_path); - furi_string_replace(temp_str, ".txt", ""); + FuriString* file_name = furi_string_alloc(); + path_extract_filename_no_ext( + furi_string_get_cstr(nfc_playlist->settings.playlist_path), file_name); + FuriString* temp_str = + furi_string_alloc_printf("\e#Delete %s?\e#", furi_string_get_cstr(file_name)); + furi_string_free(file_name); widget_add_text_box_element( nfc_playlist->widget, @@ -53,14 +52,15 @@ bool nfc_playlist_confirm_delete_scene_on_event(void* context, SceneManagerEvent switch(event.event) { case GuiButtonTypeRight: Storage* storage = furi_record_open(RECORD_STORAGE); - storage_simply_remove( - storage, furi_string_get_cstr(nfc_playlist->settings.playlist_path)); - nfc_playlist->settings.playlist_selected = false; - furi_string_reset(nfc_playlist->settings.playlist_path); + if(storage_simply_remove( + storage, furi_string_get_cstr(nfc_playlist->settings.playlist_path))) { + nfc_playlist->settings.playlist_selected = false; + furi_string_reset(nfc_playlist->settings.playlist_path); + } furi_record_close(RECORD_STORAGE); - consumed = true; scene_manager_search_and_switch_to_previous_scene( nfc_playlist->scene_manager, NfcPlaylistScene_MainMenu); + consumed = true; break; default: scene_manager_previous_scene(nfc_playlist->scene_manager); diff --git a/nfc_playlist/scenes/nfc_playlist_scene_emulation.c b/nfc_playlist/scenes/nfc_playlist_scene_emulation.c index 67f37a12b2c..78bd0dbd64c 100644 --- a/nfc_playlist/scenes/nfc_playlist_scene_emulation.c +++ b/nfc_playlist/scenes/nfc_playlist_scene_emulation.c @@ -20,17 +20,29 @@ int32_t nfc_playlist_emulation_task(void* context) { view_dispatcher_switch_to_view(nfc_playlist->view_dispatcher, NfcPlaylistView_Popup); - if(file_stream_open( - stream, - furi_string_get_cstr(nfc_playlist->settings.playlist_path), - FSAM_READ, - FSOM_OPEN_EXISTING)) { + if(nfc_playlist->settings.playlist_length == 0) { + popup_set_header( + nfc_playlist->popup, + "The playlist you have\nselected is empty", + 64, + 10, + AlignCenter, + AlignTop); + } else if(file_stream_open( + stream, + furi_string_get_cstr(nfc_playlist->settings.playlist_path), + FSAM_READ, + FSOM_OPEN_EXISTING)) { EmulationState = NfcPlaylistEmulationState_Emulating; - int file_position = 0; FuriString* line = furi_string_alloc(); FuriString* tmp_header_str = furi_string_alloc(); FuriString* tmp_counter_str = furi_string_alloc(); + FuriString* tmp_file_name = furi_string_alloc(); + FuriString* tmp_file_ext = furi_string_alloc(); + + bool delay_setting_on = nfc_playlist->settings.emulate_delay > 0; + bool delay_active = false; while(stream_read_line(stream, line) && EmulationState == NfcPlaylistEmulationState_Emulating) { @@ -40,45 +52,52 @@ int32_t nfc_playlist_emulation_task(void* context) { continue; } - if(nfc_playlist->settings.emulate_delay > 0 && file_position != 0 && !skip_delay) { - popup_set_header(nfc_playlist->popup, "Delaying", 64, 10, AlignCenter, AlignTop); - start_blink(nfc_playlist, NfcPlaylistLedState_Error); - int time_counter_delay_ms = - (options_emulate_delay[nfc_playlist->settings.emulate_delay] * 1000); - while(time_counter_delay_ms > 0 && - EmulationState == NfcPlaylistEmulationState_Emulating) { - furi_string_printf(tmp_counter_str, "%ds", (time_counter_delay_ms / 1000)); - popup_set_text( - nfc_playlist->popup, - furi_string_get_cstr(tmp_counter_str), - 64, - 50, - AlignCenter, - AlignTop); - furi_delay_ms(50); - time_counter_delay_ms -= 50; - }; - } else if(nfc_playlist->settings.emulate_delay > 0) { - skip_delay = false; - file_position++; + if(delay_setting_on) { + if(delay_active && !skip_delay) { + popup_set_header( + nfc_playlist->popup, "Delaying", 64, 10, AlignCenter, AlignTop); + start_blink(nfc_playlist, NfcPlaylistLedState_Error); + int time_counter_delay_ms = + (options_emulate_delay[nfc_playlist->settings.emulate_delay] * 1000); + while(time_counter_delay_ms > 0 && + EmulationState == NfcPlaylistEmulationState_Emulating) { + furi_string_printf(tmp_counter_str, "%ds", (time_counter_delay_ms / 1000)); + popup_set_text( + nfc_playlist->popup, + furi_string_get_cstr(tmp_counter_str), + 64, + 50, + AlignCenter, + AlignTop); + furi_delay_ms(50); + time_counter_delay_ms -= 50; + }; + } else if(!delay_active) { + delay_active = true; + } else if(skip_delay) { + skip_delay = false; + } } if(EmulationState != NfcPlaylistEmulationState_Emulating) { break; } - char* file_name = strchr(file_path, '/') != NULL ? &strrchr(file_path, '/')[1] : - file_path; - char const* file_ext = &strrchr(file_path, '.')[1]; + path_extract_filename(line, tmp_file_name, false); + path_extract_ext_str(line, tmp_file_ext); + int time_counter_ms = (options_emulate_timeout[nfc_playlist->settings.emulate_timeout] * 1000); - if(!strcasestr(file_ext, "nfc")) { + if(!strcasestr(furi_string_get_cstr(tmp_file_ext), ".nfc")) { if(nfc_playlist->settings.skip_error) { skip_delay = true; continue; } - furi_string_printf(tmp_header_str, "ERROR invalid file:\n%s", file_name); + furi_string_printf( + tmp_header_str, + "ERROR invalid file:\n%s", + furi_string_get_cstr(tmp_file_name)); popup_set_header( nfc_playlist->popup, furi_string_get_cstr(tmp_header_str), @@ -105,7 +124,8 @@ int32_t nfc_playlist_emulation_task(void* context) { skip_delay = true; continue; } - furi_string_printf(tmp_header_str, "ERROR not found:\n%s", file_name); + furi_string_printf( + tmp_header_str, "ERROR not found:\n%s", furi_string_get_cstr(tmp_file_name)); popup_set_header( nfc_playlist->popup, furi_string_get_cstr(tmp_header_str), @@ -128,7 +148,8 @@ int32_t nfc_playlist_emulation_task(void* context) { time_counter_ms -= 50; }; } else { - furi_string_printf(tmp_header_str, "Emulating:\n%s", file_name); + furi_string_printf( + tmp_header_str, "Emulating:\n%s", furi_string_get_cstr(tmp_file_name)); popup_set_header( nfc_playlist->popup, furi_string_get_cstr(tmp_header_str), @@ -136,10 +157,12 @@ int32_t nfc_playlist_emulation_task(void* context) { 10, AlignCenter, AlignTop); - nfc_playlist_worker_set_nfc_data(nfc_playlist->nfc_playlist_worker, file_path); - nfc_playlist_worker_start(nfc_playlist->nfc_playlist_worker); + nfc_playlist_emulation_worker_set_nfc_data( + nfc_playlist->nfc_playlist_emulation_worker, file_path); + nfc_playlist_emulation_worker_start(nfc_playlist->nfc_playlist_emulation_worker); start_blink(nfc_playlist, NfcPlaylistLedState_Normal); - while(nfc_playlist_worker_is_emulating(nfc_playlist->nfc_playlist_worker) && + while(nfc_playlist_emulation_worker_is_emulating( + nfc_playlist->nfc_playlist_emulation_worker) && time_counter_ms > 0 && EmulationState == NfcPlaylistEmulationState_Emulating) { furi_string_printf(tmp_counter_str, "%ds", (time_counter_ms / 1000)); @@ -153,10 +176,20 @@ int32_t nfc_playlist_emulation_task(void* context) { furi_delay_ms(50); time_counter_ms -= 50; }; - nfc_playlist_worker_stop(nfc_playlist->nfc_playlist_worker); - nfc_playlist_worker_clear_nfc_data(nfc_playlist->nfc_playlist_worker); + nfc_playlist_emulation_worker_stop(nfc_playlist->nfc_playlist_emulation_worker); + nfc_playlist_emulation_worker_clear_nfc_data( + nfc_playlist->nfc_playlist_emulation_worker); } } + stop_blink(nfc_playlist); + + furi_string_free(line); + furi_string_free(tmp_header_str); + furi_string_free(tmp_counter_str); + furi_string_free(tmp_file_name); + furi_string_free(tmp_file_ext); + file_stream_close(stream); + popup_reset(nfc_playlist->popup); popup_set_header( nfc_playlist->popup, @@ -166,39 +199,33 @@ int32_t nfc_playlist_emulation_task(void* context) { 10, AlignCenter, AlignTop); - popup_set_text(nfc_playlist->popup, "Press back", 64, 50, AlignCenter, AlignTop); - stop_blink(nfc_playlist); - - EmulationState = NfcPlaylistEmulationState_Stopped; - furi_string_free(line); - furi_string_free(tmp_header_str); - furi_string_free(tmp_counter_str); } else { popup_set_header( nfc_playlist->popup, "Failed to open playlist", 64, 10, AlignCenter, AlignTop); - popup_set_text(nfc_playlist->popup, "Press back", 64, 50, AlignCenter, AlignTop); } + popup_set_text(nfc_playlist->popup, "Press back", 64, 50, AlignCenter, AlignTop); - file_stream_close(stream); furi_record_close(RECORD_STORAGE); stream_free(stream); + EmulationState = NfcPlaylistEmulationState_Stopped; + return 0; } void nfc_playlist_emulation_setup(void* context) { NfcPlaylist* nfc_playlist = context; nfc_playlist->thread = furi_thread_alloc_ex( - "NfcPlaylistEmulationWorker", 8192, nfc_playlist_emulation_task, nfc_playlist); - nfc_playlist->nfc_playlist_worker = nfc_playlist_worker_alloc(); + "NfcPlaylistEmulationWorker", 4096, nfc_playlist_emulation_task, nfc_playlist); + nfc_playlist->nfc_playlist_emulation_worker = nfc_playlist_emulation_worker_alloc(); } void nfc_playlist_emulation_free(NfcPlaylist* nfc_playlist) { furi_assert(nfc_playlist); furi_thread_free(nfc_playlist->thread); - nfc_playlist_worker_free(nfc_playlist->nfc_playlist_worker); + nfc_playlist_emulation_worker_free(nfc_playlist->nfc_playlist_emulation_worker); nfc_playlist->thread = NULL; - nfc_playlist->nfc_playlist_worker = NULL; + nfc_playlist->nfc_playlist_emulation_worker = NULL; } void nfc_playlist_emulation_start(NfcPlaylist* nfc_playlist) { diff --git a/nfc_playlist/scenes/nfc_playlist_scene_main_menu.c b/nfc_playlist/scenes/nfc_playlist_scene_main_menu.c index 95d33f70e2c..c475678b96f 100644 --- a/nfc_playlist/scenes/nfc_playlist_scene_main_menu.c +++ b/nfc_playlist/scenes/nfc_playlist_scene_main_menu.c @@ -1,12 +1,5 @@ #include "../nfc_playlist.h" -typedef enum { - NfcPlaylistEvent_ShowEmulation, - NfcPlaylistEvent_ShowPlaylistSelect, - NfcPlaylistEvent_ShowFileEdit, - NfcPlaylistEvent_ShowSettings -} NfcPlaylistMainMenuEvent; - typedef enum { NfcPlaylistMenuSelection_Start, NfcPlaylistMenuSelection_PlaylistSelect, @@ -27,10 +20,9 @@ void nfc_playlist_main_menu_scene_on_enter(void* context) { return; } - FuriString* tmp_str = furi_string_alloc(); - furi_string_printf(tmp_str, "NFC Playlist v%s", FAP_VERSION); - submenu_set_header(nfc_playlist->submenu, furi_string_get_cstr(tmp_str)); - furi_string_free(tmp_str); + FuriString* header = furi_string_alloc_printf("NFC Playlist v%s", FAP_VERSION); + submenu_set_header(nfc_playlist->submenu, furi_string_get_cstr(header)); + furi_string_free(header); submenu_add_lockable_item( nfc_playlist->submenu, @@ -70,19 +62,19 @@ bool nfc_playlist_main_menu_scene_on_event(void* context, SceneManagerEvent even bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { switch(event.event) { - case NfcPlaylistEvent_ShowEmulation: + case NfcPlaylistMenuSelection_Start: scene_manager_next_scene(nfc_playlist->scene_manager, NfcPlaylistScene_Emulation); consumed = true; break; - case NfcPlaylistEvent_ShowPlaylistSelect: + case NfcPlaylistMenuSelection_PlaylistSelect: scene_manager_next_scene(nfc_playlist->scene_manager, NfcPlaylistScene_PlaylistSelect); consumed = true; break; - case NfcPlaylistEvent_ShowFileEdit: + case NfcPlaylistMenuSelection_FileEdit: scene_manager_next_scene(nfc_playlist->scene_manager, NfcPlaylistScene_PlaylistEdit); consumed = true; break; - case NfcPlaylistEvent_ShowSettings: + case NfcPlaylistMenuSelection_Settings: scene_manager_next_scene(nfc_playlist->scene_manager, NfcPlaylistScene_Settings); consumed = true; break; diff --git a/nfc_playlist/scenes/nfc_playlist_scene_name_new_playlist.c b/nfc_playlist/scenes/nfc_playlist_scene_name_new_playlist.c index 7637f560435..2686c923f15 100644 --- a/nfc_playlist/scenes/nfc_playlist_scene_name_new_playlist.c +++ b/nfc_playlist/scenes/nfc_playlist_scene_name_new_playlist.c @@ -1,30 +1,54 @@ #include "../nfc_playlist.h" -void nfc_playlist_name_new_playlist_menu_callback(void* context) { +int32_t nfc_playlist_name_new_playlist_thread_task(void* context) { NfcPlaylist* nfc_playlist = context; - Storage* storage = furi_record_open(RECORD_STORAGE); - FuriString* file_name = furi_string_alloc(); - furi_string_printf( - file_name, "/ext/apps_data/nfc_playlist/%s.txt", nfc_playlist->text_input_output); + FuriString* file_name = furi_string_alloc_printf( + "/ext/apps_data/nfc_playlist/%s.txt", nfc_playlist->text_input_output); + char const* file_name_cstr = furi_string_get_cstr(file_name); + Storage* storage = furi_record_open(RECORD_STORAGE); File* file = storage_file_alloc(storage); - if(storage_file_open(file, furi_string_get_cstr(file_name), FSAM_READ_WRITE, FSOM_CREATE_NEW)) { - storage_file_close(file); - furi_string_swap(nfc_playlist->settings.playlist_path, file_name); - } - nfc_playlist->settings.playlist_length = 0; + if(!storage_file_exists(storage, file_name_cstr)) { + if(storage_file_open(file, file_name_cstr, FSAM_READ_WRITE, FSOM_CREATE_NEW)) { + storage_file_close(file); + furi_string_swap(nfc_playlist->settings.playlist_path, file_name); + nfc_playlist->settings.playlist_length = 0; + } + } - storage_file_free(file); furi_string_free(file_name); + storage_file_free(file); furi_record_close(RECORD_STORAGE); - scene_manager_previous_scene(nfc_playlist->scene_manager); + + return 0; +} + +void nfc_playlist_name_new_playlist_thread_state_callback(FuriThreadState state, void* context) { + NfcPlaylist* nfc_playlist = context; + if(state == FuriThreadStateStopped) { + furi_thread_yield(); + nfc_playlist->thread = NULL; + scene_manager_search_and_switch_to_previous_scene( + nfc_playlist->scene_manager, NfcPlaylistScene_MainMenu); + } +} + +void nfc_playlist_name_new_playlist_menu_callback(void* context) { + NfcPlaylist* nfc_playlist = context; + nfc_playlist->thread = furi_thread_alloc_ex( + "NfcPlaylistCreator", 1024, nfc_playlist_name_new_playlist_thread_task, nfc_playlist); + furi_thread_set_state_context(nfc_playlist->thread, nfc_playlist); + furi_thread_set_state_callback( + nfc_playlist->thread, nfc_playlist_name_new_playlist_thread_state_callback); + furi_thread_start(nfc_playlist->thread); } void nfc_playlist_name_new_playlist_scene_on_enter(void* context) { NfcPlaylist* nfc_playlist = context; - nfc_playlist->text_input_output = (char*)malloc(50); + + nfc_playlist->text_input_output = malloc(MAX_PLAYLIST_NAME_LEN + 1); text_input_set_header_text(nfc_playlist->text_input, "Enter file name"); text_input_set_minimum_length(nfc_playlist->text_input, 1); text_input_set_result_callback( @@ -32,7 +56,7 @@ void nfc_playlist_name_new_playlist_scene_on_enter(void* context) { nfc_playlist_name_new_playlist_menu_callback, nfc_playlist, nfc_playlist->text_input_output, - 50, + MAX_PLAYLIST_NAME_LEN, true); view_dispatcher_switch_to_view(nfc_playlist->view_dispatcher, NfcPlaylistView_TextInput); diff --git a/nfc_playlist/scenes/nfc_playlist_scene_nfc_select.c b/nfc_playlist/scenes/nfc_playlist_scene_nfc_add.c similarity index 84% rename from nfc_playlist/scenes/nfc_playlist_scene_nfc_select.c rename to nfc_playlist/scenes/nfc_playlist_scene_nfc_add.c index 0a719a485e1..b0dcab100a0 100644 --- a/nfc_playlist/scenes/nfc_playlist_scene_nfc_select.c +++ b/nfc_playlist/scenes/nfc_playlist_scene_nfc_add.c @@ -1,6 +1,6 @@ #include "../nfc_playlist.h" -void nfc_playlist_nfc_select_menu_callback(void* context) { +void nfc_playlist_nfc_add_menu_callback(void* context) { NfcPlaylist* nfc_playlist = context; Storage* storage = furi_record_open(RECORD_STORAGE); @@ -16,6 +16,7 @@ void nfc_playlist_nfc_select_menu_callback(void* context) { while(stream_read_line(stream, line)) { furi_string_cat_printf(tmp_str, "%s", furi_string_get_cstr(line)); } + furi_string_free(line); if(!furi_string_empty(tmp_str)) { furi_string_cat_printf( @@ -26,7 +27,6 @@ void nfc_playlist_nfc_select_menu_callback(void* context) { } stream_clean(stream); - furi_string_free(line); stream_write_string(stream, tmp_str); file_stream_close(stream); furi_string_free(tmp_str); @@ -40,12 +40,12 @@ void nfc_playlist_nfc_select_menu_callback(void* context) { scene_manager_previous_scene(nfc_playlist->scene_manager); } -void nfc_playlist_nfc_select_scene_on_enter(void* context) { +void nfc_playlist_nfc_add_scene_on_enter(void* context) { NfcPlaylist* nfc_playlist = context; file_browser_configure( nfc_playlist->file_browser, ".nfc", "/ext/nfc/", true, true, &I_Nfc_10px, true); file_browser_set_callback( - nfc_playlist->file_browser, nfc_playlist_nfc_select_menu_callback, nfc_playlist); + nfc_playlist->file_browser, nfc_playlist_nfc_add_menu_callback, nfc_playlist); FuriString* tmp_str = furi_string_alloc_set_str("/ext/nfc/"); file_browser_start(nfc_playlist->file_browser, tmp_str); furi_string_free(tmp_str); @@ -53,13 +53,13 @@ void nfc_playlist_nfc_select_scene_on_enter(void* context) { view_dispatcher_switch_to_view(nfc_playlist->view_dispatcher, NfcPlaylistView_FileBrowser); } -bool nfc_playlist_nfc_select_scene_on_event(void* context, SceneManagerEvent event) { +bool nfc_playlist_nfc_add_scene_on_event(void* context, SceneManagerEvent event) { UNUSED(event); UNUSED(context); return false; } -void nfc_playlist_nfc_select_scene_on_exit(void* context) { +void nfc_playlist_nfc_add_scene_on_exit(void* context) { NfcPlaylist* nfc_playlist = context; file_browser_stop(nfc_playlist->file_browser); } \ No newline at end of file diff --git a/nfc_playlist/scenes/nfc_playlist_scene_nfc_remove.c b/nfc_playlist/scenes/nfc_playlist_scene_nfc_remove.c index 396a7f86b9e..9f92d1a0ac0 100644 --- a/nfc_playlist/scenes/nfc_playlist_scene_nfc_remove.c +++ b/nfc_playlist/scenes/nfc_playlist_scene_nfc_remove.c @@ -18,22 +18,22 @@ void nfc_playlist_nfc_remove_options_change_callback(VariableItem* item) { uint8_t current_option = variable_item_list_get_selected_item_index(nfc_playlist->variable_item_list); uint8_t option_value_index = variable_item_get_current_value_index(item); - FuriString* tmp_str = furi_string_alloc(); + switch(current_option) { - case NfcPlaylistSettings_LineSelector: + case NfcPlaylistSettings_LineSelector: { selected_line = option_value_index + 1; - furi_string_printf(tmp_str, "%d", selected_line); + FuriString* tmp_str = furi_string_alloc_printf("%d", selected_line); variable_item_set_current_value_text(item, furi_string_get_cstr(tmp_str)); + furi_string_free(tmp_str); break; + } default: break; } - furi_string_free(tmp_str); } void nfc_playlist_nfc_remove_scene_on_enter(void* context) { NfcPlaylist* nfc_playlist = context; - FuriString* tmp_str = furi_string_alloc(); selected_line = nfc_playlist->settings.playlist_length; @@ -47,8 +47,11 @@ void nfc_playlist_nfc_remove_scene_on_enter(void* context) { nfc_playlist); variable_item_set_current_value_index( Line_selector, nfc_playlist->settings.playlist_length - 1); - furi_string_printf(tmp_str, "%d", selected_line); + + FuriString* tmp_str = furi_string_alloc_printf("%d", selected_line); variable_item_set_current_value_text(Line_selector, furi_string_get_cstr(tmp_str)); + furi_string_free(tmp_str); + variable_item_set_locked( Line_selector, nfc_playlist->settings.playlist_length == 0 ? true : false, @@ -62,7 +65,6 @@ void nfc_playlist_nfc_remove_scene_on_enter(void* context) { variable_item_list_set_enter_callback( nfc_playlist->variable_item_list, nfc_playlist_nfc_remove_menu_callback, nfc_playlist); - furi_string_free(tmp_str); view_dispatcher_switch_to_view( nfc_playlist->view_dispatcher, NfcPlaylistView_VariableItemList); @@ -97,8 +99,8 @@ bool nfc_playlist_nfc_remove_scene_on_event(void* context, SceneManagerEvent eve } } - stream_clean(stream); furi_string_free(line); + stream_clean(stream); stream_write_string(stream, tmp_str); furi_string_free(tmp_str); file_stream_close(stream); @@ -111,16 +113,14 @@ bool nfc_playlist_nfc_remove_scene_on_event(void* context, SceneManagerEvent eve if(selected_line == 0) { scene_manager_previous_scene(nfc_playlist->scene_manager); } else { - FuriString* tmp_str = furi_string_alloc(); - VariableItem* Line_selector = variable_item_list_get( nfc_playlist->variable_item_list, NfcPlaylistSettings_LineSelector); variable_item_set_values_count( Line_selector, nfc_playlist->settings.playlist_length); variable_item_set_current_value_index(Line_selector, selected_line - 1); - furi_string_printf(tmp_str, "%d", selected_line); - variable_item_set_current_value_text(Line_selector, furi_string_get_cstr(tmp_str)); + FuriString* tmp_str = furi_string_alloc_printf("%d", selected_line); + variable_item_set_current_value_text(Line_selector, furi_string_get_cstr(tmp_str)); furi_string_free(tmp_str); } diff --git a/nfc_playlist/scenes/nfc_playlist_scene_playlist_edit.c b/nfc_playlist/scenes/nfc_playlist_scene_playlist_edit.c index abcf29e4686..11e5882e9fb 100644 --- a/nfc_playlist/scenes/nfc_playlist_scene_playlist_edit.c +++ b/nfc_playlist/scenes/nfc_playlist_scene_playlist_edit.c @@ -19,6 +19,8 @@ void nfc_playlist_playlist_edit_scene_on_enter(void* context) { submenu_set_header(nfc_playlist->submenu, "Edit Playlist"); + bool playlist_path_empty = furi_string_empty(nfc_playlist->settings.playlist_path); + submenu_add_item( nfc_playlist->submenu, "Create Playlist", @@ -32,7 +34,7 @@ void nfc_playlist_playlist_edit_scene_on_enter(void* context) { NfcPlaylistMenuSelection_DeletePlaylist, nfc_playlist_playlist_edit_menu_callback, nfc_playlist, - furi_string_empty(nfc_playlist->settings.playlist_path), + playlist_path_empty, "No\nplaylist\nselected"); submenu_add_lockable_item( @@ -41,7 +43,7 @@ void nfc_playlist_playlist_edit_scene_on_enter(void* context) { NfcPlaylistMenuSelection_RenamePlaylist, nfc_playlist_playlist_edit_menu_callback, nfc_playlist, - furi_string_empty(nfc_playlist->settings.playlist_path), + playlist_path_empty, "No\nplaylist\nselected"); submenu_add_lockable_item( @@ -50,7 +52,7 @@ void nfc_playlist_playlist_edit_scene_on_enter(void* context) { NfcPlaylistMenuSelection_AddNfcItem, nfc_playlist_playlist_edit_menu_callback, nfc_playlist, - furi_string_empty(nfc_playlist->settings.playlist_path), + playlist_path_empty, "No\nplaylist\nselected"); submenu_add_lockable_item( @@ -59,7 +61,7 @@ void nfc_playlist_playlist_edit_scene_on_enter(void* context) { NfcPlaylistMenuSelection_RemoveNfcItem, nfc_playlist_playlist_edit_menu_callback, nfc_playlist, - furi_string_empty(nfc_playlist->settings.playlist_path), + playlist_path_empty, "No\nplaylist\nselected"); submenu_add_lockable_item( @@ -68,7 +70,7 @@ void nfc_playlist_playlist_edit_scene_on_enter(void* context) { NfcPlaylistMenuSelection_ViewPlaylistContent, nfc_playlist_playlist_edit_menu_callback, nfc_playlist, - furi_string_empty(nfc_playlist->settings.playlist_path), + playlist_path_empty, "No\nplaylist\nselected"); view_dispatcher_switch_to_view(nfc_playlist->view_dispatcher, NfcPlaylistView_Submenu); @@ -93,7 +95,7 @@ bool nfc_playlist_playlist_edit_scene_on_event(void* context, SceneManagerEvent consumed = true; break; case NfcPlaylistMenuSelection_AddNfcItem: - scene_manager_next_scene(nfc_playlist->scene_manager, NfcPlaylistScene_NfcSelect); + scene_manager_next_scene(nfc_playlist->scene_manager, NfcPlaylistScene_NfcAdd); consumed = true; break; case NfcPlaylistMenuSelection_RemoveNfcItem: diff --git a/nfc_playlist/scenes/nfc_playlist_scene_playlist_rename.c b/nfc_playlist/scenes/nfc_playlist_scene_playlist_rename.c index 06101d9b971..dad8cd84162 100644 --- a/nfc_playlist/scenes/nfc_playlist_scene_playlist_rename.c +++ b/nfc_playlist/scenes/nfc_playlist_scene_playlist_rename.c @@ -1,42 +1,65 @@ #include "../nfc_playlist.h" -void nfc_playlist_playlist_rename_menu_callback(void* context) { +int32_t nfc_playlist_playlist_rename_thread_task(void* context) { NfcPlaylist* nfc_playlist = context; - Storage* storage = furi_record_open(RECORD_STORAGE); - char const* old_file_path = (char*)furi_string_get_cstr(nfc_playlist->settings.playlist_path); - char const* old_file_name = - strchr(old_file_path, '/') != NULL ? &strrchr(old_file_path, '/')[1] : old_file_path; - - FuriString* new_file_path = furi_string_alloc_set(nfc_playlist->settings.playlist_path); - furi_string_replace(new_file_path, old_file_name, nfc_playlist->text_input_output); + FuriString* old_file_path = furi_string_alloc(); + path_extract_dirname( + furi_string_get_cstr(nfc_playlist->settings.playlist_path), old_file_path); + FuriString* new_file_path = furi_string_alloc_set(old_file_path); + path_concat( + furi_string_get_cstr(old_file_path), nfc_playlist->text_input_output, new_file_path); + furi_string_free(old_file_path); furi_string_cat_str(new_file_path, ".txt"); - if(storage_common_rename_safe(storage, old_file_path, furi_string_get_cstr(new_file_path)) == - 0) { - furi_string_move(nfc_playlist->settings.playlist_path, new_file_path); - } else { - furi_string_free(new_file_path); + Storage* storage = furi_record_open(RECORD_STORAGE); + + if(!storage_file_exists(storage, furi_string_get_cstr(new_file_path))) { + if(storage_common_rename( + storage, + furi_string_get_cstr(nfc_playlist->settings.playlist_path), + furi_string_get_cstr(new_file_path)) == FSE_OK) { + furi_string_swap(nfc_playlist->settings.playlist_path, new_file_path); + } } + furi_string_free(new_file_path); + furi_record_close(RECORD_STORAGE); - scene_manager_search_and_switch_to_previous_scene( - nfc_playlist->scene_manager, NfcPlaylistScene_MainMenu); + return 0; } -void nfc_playlist_playlist_rename_scene_on_enter(void* context) { +void nfc_playlist_playlist_rename_thread_state_callback(FuriThreadState state, void* context) { NfcPlaylist* nfc_playlist = context; + if(state == FuriThreadStateStopped) { + furi_thread_yield(); + nfc_playlist->thread = NULL; + scene_manager_search_and_switch_to_previous_scene( + nfc_playlist->scene_manager, NfcPlaylistScene_MainMenu); + } +} - char const* tmp_file_path = furi_string_get_cstr(nfc_playlist->settings.playlist_path); - char const* tmp_file_name = - strchr(tmp_file_path, '/') != NULL ? &strrchr(tmp_file_path, '/')[1] : tmp_file_path; +void nfc_playlist_playlist_rename_menu_callback(void* context) { + NfcPlaylist* nfc_playlist = context; + nfc_playlist->thread = furi_thread_alloc_ex( + "NfcPlaylistRenamer", 1024, nfc_playlist_playlist_rename_thread_task, nfc_playlist); + furi_thread_set_state_context(nfc_playlist->thread, nfc_playlist); + furi_thread_set_state_callback( + nfc_playlist->thread, nfc_playlist_playlist_rename_thread_state_callback); + furi_thread_start(nfc_playlist->thread); +} + +void nfc_playlist_playlist_rename_scene_on_enter(void* context) { + NfcPlaylist* nfc_playlist = context; - FuriString* tmp_file_name_furi = furi_string_alloc_set_str(tmp_file_name); - furi_string_replace(tmp_file_name_furi, ".txt", ""); + FuriString* tmp_file_name = furi_string_alloc(); + path_extract_filename_no_ext( + furi_string_get_cstr(nfc_playlist->settings.playlist_path), tmp_file_name); - nfc_playlist->text_input_output = strdup(furi_string_get_cstr(tmp_file_name_furi)); - furi_string_free(tmp_file_name_furi); + nfc_playlist->text_input_output = malloc(MAX_PLAYLIST_NAME_LEN + 1); + strcpy(nfc_playlist->text_input_output, furi_string_get_cstr(tmp_file_name)); + furi_string_free(tmp_file_name); text_input_set_header_text(nfc_playlist->text_input, "Enter new file name"); text_input_set_minimum_length(nfc_playlist->text_input, 1); @@ -45,7 +68,7 @@ void nfc_playlist_playlist_rename_scene_on_enter(void* context) { nfc_playlist_playlist_rename_menu_callback, nfc_playlist, nfc_playlist->text_input_output, - (50 + sizeof(nfc_playlist->text_input_output)), + MAX_PLAYLIST_NAME_LEN, false); view_dispatcher_switch_to_view(nfc_playlist->view_dispatcher, NfcPlaylistView_TextInput); diff --git a/nfc_playlist/scenes/nfc_playlist_scene_playlist_select.c b/nfc_playlist/scenes/nfc_playlist_scene_playlist_select.c index ac22e13ea45..8d514d2218e 100644 --- a/nfc_playlist/scenes/nfc_playlist_scene_playlist_select.c +++ b/nfc_playlist/scenes/nfc_playlist_scene_playlist_select.c @@ -31,7 +31,7 @@ void nfc_playlist_playlist_select_menu_callback(void* context) { void nfc_playlist_playlist_select_scene_on_enter(void* context) { NfcPlaylist* nfc_playlist = context; file_browser_configure( - nfc_playlist->file_browser, ".txt", PLAYLIST_LOCATION, true, true, &I_unknown_10px, true); + nfc_playlist->file_browser, ".txt", PLAYLIST_LOCATION, true, true, &I_Playlist_10px, true); file_browser_set_callback( nfc_playlist->file_browser, nfc_playlist_playlist_select_menu_callback, nfc_playlist); FuriString* tmp_str = furi_string_alloc_set_str(PLAYLIST_LOCATION); diff --git a/nfc_playlist/scenes/nfc_playlist_scene_settings.c b/nfc_playlist/scenes/nfc_playlist_scene_settings.c index f603d4f6b91..4022d4f7b6c 100644 --- a/nfc_playlist/scenes/nfc_playlist_scene_settings.c +++ b/nfc_playlist/scenes/nfc_playlist_scene_settings.c @@ -19,20 +19,24 @@ void nfc_playlist_settings_options_change_callback(VariableItem* item) { uint8_t current_option = variable_item_list_get_selected_item_index(nfc_playlist->variable_item_list); uint8_t option_value_index = variable_item_get_current_value_index(item); - FuriString* tmp_str = furi_string_alloc(); + switch(current_option) { - case NfcPlaylistSettings_Timeout: + case NfcPlaylistSettings_Timeout: { nfc_playlist->settings.emulate_timeout = option_value_index; - furi_string_printf( - tmp_str, "%ds", options_emulate_timeout[nfc_playlist->settings.emulate_timeout]); + FuriString* tmp_str = furi_string_alloc_printf( + "%ds", options_emulate_timeout[nfc_playlist->settings.emulate_timeout]); variable_item_set_current_value_text(item, furi_string_get_cstr(tmp_str)); + furi_string_free(tmp_str); break; - case NfcPlaylistSettings_Delay: + } + case NfcPlaylistSettings_Delay: { nfc_playlist->settings.emulate_delay = option_value_index; - furi_string_printf( - tmp_str, "%ds", options_emulate_delay[nfc_playlist->settings.emulate_delay]); + FuriString* tmp_str = furi_string_alloc_printf( + "%ds", options_emulate_delay[nfc_playlist->settings.emulate_delay]); variable_item_set_current_value_text(item, furi_string_get_cstr(tmp_str)); + furi_string_free(tmp_str); break; + } case NfcPlaylistSettings_LedIndicator: nfc_playlist->settings.emulate_led_indicator = option_value_index; variable_item_set_current_value_text( @@ -46,7 +50,6 @@ void nfc_playlist_settings_options_change_callback(VariableItem* item) { default: break; } - furi_string_free(tmp_str); } void nfc_playlist_settings_scene_on_enter(void* context) { @@ -79,6 +82,8 @@ void nfc_playlist_settings_scene_on_enter(void* context) { tmp_str, "%ds", options_emulate_delay[nfc_playlist->settings.emulate_delay]); variable_item_set_current_value_text(emulation_delay_setting, furi_string_get_cstr(tmp_str)); + furi_string_free(tmp_str); + VariableItem* emulation_led_indicator_setting = variable_item_list_add( nfc_playlist->variable_item_list, "LED Indicator", @@ -110,7 +115,6 @@ void nfc_playlist_settings_scene_on_enter(void* context) { variable_item_list_set_enter_callback( nfc_playlist->variable_item_list, nfc_playlist_settings_menu_callback, nfc_playlist); - furi_string_free(tmp_str); view_dispatcher_switch_to_view( nfc_playlist->view_dispatcher, NfcPlaylistView_VariableItemList); @@ -144,6 +148,8 @@ bool nfc_playlist_settings_scene_on_event(void* context, SceneManagerEvent event variable_item_set_current_value_text( emulation_delay_setting, furi_string_get_cstr(tmp_str)); + furi_string_free(tmp_str); + nfc_playlist->settings.emulate_led_indicator = default_emulate_led_indicator; VariableItem* emulation_led_indicator_setting = variable_item_list_get( nfc_playlist->variable_item_list, NfcPlaylistSettings_LedIndicator); @@ -161,7 +167,6 @@ bool nfc_playlist_settings_scene_on_event(void* context, SceneManagerEvent event variable_item_set_current_value_text( emulation_skip_error_setting, nfc_playlist->settings.skip_error ? "ON" : "OFF"); - furi_string_free(tmp_str); consumed = true; break; default: diff --git a/nfc_playlist/scenes/nfc_playlist_scene_view_playlist_content.c b/nfc_playlist/scenes/nfc_playlist_scene_view_playlist_content.c index 7efdd46c284..e6d9ed5a252 100644 --- a/nfc_playlist/scenes/nfc_playlist_scene_view_playlist_content.c +++ b/nfc_playlist/scenes/nfc_playlist_scene_view_playlist_content.c @@ -18,7 +18,6 @@ void nfc_playlist_view_playlist_content_scene_on_enter(void* context) { furi_string_cat_printf(tmp_str, "%s", furi_string_get_cstr(line)); } - stream_clean(stream); furi_string_free(line); file_stream_close(stream); diff --git a/nfc_rfid_detector/.catalog/changelog.md b/nfc_rfid_detector/.catalog/changelog.md index 64420cfcfed..52233336002 100644 --- a/nfc_rfid_detector/.catalog/changelog.md +++ b/nfc_rfid_detector/.catalog/changelog.md @@ -1,3 +1,5 @@ +## 1.3 + - Сhange GUI ## 1.2 - Rework application with new NFC API ## 1.1 diff --git a/nfc_rfid_detector/.catalog/gallery/nfc-rfid-both-detected.png b/nfc_rfid_detector/.catalog/gallery/nfc-rfid-both-detected.png index 3f7b2b3ace6..869cc1ed51d 100644 Binary files a/nfc_rfid_detector/.catalog/gallery/nfc-rfid-both-detected.png and b/nfc_rfid_detector/.catalog/gallery/nfc-rfid-both-detected.png differ diff --git a/nfc_rfid_detector/.catalog/gallery/nfc-rfid-nfc-detected.png b/nfc_rfid_detector/.catalog/gallery/nfc-rfid-nfc-detected.png index d0b9a4d6c2b..f116655d7dd 100644 Binary files a/nfc_rfid_detector/.catalog/gallery/nfc-rfid-nfc-detected.png and b/nfc_rfid_detector/.catalog/gallery/nfc-rfid-nfc-detected.png differ diff --git a/nfc_rfid_detector/.catalog/gallery/nfc-rfid-rfid-detected.png b/nfc_rfid_detector/.catalog/gallery/nfc-rfid-rfid-detected.png index 1fa71888af1..d5b942f630e 100644 Binary files a/nfc_rfid_detector/.catalog/gallery/nfc-rfid-rfid-detected.png and b/nfc_rfid_detector/.catalog/gallery/nfc-rfid-rfid-detected.png differ diff --git a/nfc_rfid_detector/application.fam b/nfc_rfid_detector/application.fam index 31c78eac4bc..eb85dd94113 100644 --- a/nfc_rfid_detector/application.fam +++ b/nfc_rfid_detector/application.fam @@ -7,8 +7,8 @@ App( requires=["gui"], stack_size=4 * 1024, fap_description="Identify the reader type: NFC (13 MHz) and/or RFID (125 KHz).", - fap_version="1.2", - fap_icon="nfc_rfid_detector_10px.png", + fap_version="1.3", + fap_icon="nfc_rfid_detector_icon_10px.png", fap_category="Tools", fap_icon_assets="images", fap_author="SkorP", diff --git a/nfc_rfid_detector/nfc_rfid_detector_10px.png b/nfc_rfid_detector/nfc_rfid_detector_10px.png deleted file mode 100644 index 7e875e028d5..00000000000 Binary files a/nfc_rfid_detector/nfc_rfid_detector_10px.png and /dev/null differ diff --git a/nfc_rfid_detector/nfc_rfid_detector_icon_10px.png b/nfc_rfid_detector/nfc_rfid_detector_icon_10px.png new file mode 100644 index 00000000000..3a5559439fa Binary files /dev/null and b/nfc_rfid_detector/nfc_rfid_detector_icon_10px.png differ diff --git a/nfc_rfid_detector/views/nfc_rfid_detector_view_field_presence.c b/nfc_rfid_detector/views/nfc_rfid_detector_view_field_presence.c index 1745582914d..aed8cb58d4b 100644 --- a/nfc_rfid_detector/views/nfc_rfid_detector_view_field_presence.c +++ b/nfc_rfid_detector/views/nfc_rfid_detector_view_field_presence.c @@ -75,12 +75,12 @@ void nfc_rfid_detector_view_field_presence_draw( 17, NfcRfidDetectorFieldPresenceIcons[NfcRfidDetectorTypeFieldPresenceNfc]); canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 9, 62, "13,56 MHz"); + canvas_draw_str(canvas, 9, 62, "13.56 MHz"); } if(model->rfid_field) { char str[16]; - snprintf(str, sizeof(str), "%.02f KHz", (double)model->rfid_frequency / 1000); + snprintf(str, sizeof(str), "%.02f kHz", (double)model->rfid_frequency / 1000); canvas_set_font(canvas, FontPrimary); canvas_draw_str(canvas, 76, 10, "LF RFID"); canvas_draw_icon( diff --git a/nightstand_clock/clock_app.c b/nightstand_clock/clock_app.c index c8afca64576..2cf8b5335de 100644 --- a/nightstand_clock/clock_app.c +++ b/nightstand_clock/clock_app.c @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -83,13 +84,15 @@ void handle_down() { } static void clock_input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); + PluginEvent event = {.type = EventTypeKey, .input = *input_event}; furi_message_queue_put(event_queue, &event, FuriWaitForever); } //do you are have stupid? +// idk who left that comment here, but i don't have stupid sorry void elements_progress_bar_vertical( Canvas* canvas, uint8_t x, diff --git a/nrf24batch/nrf24batch.c b/nrf24batch/nrf24batch.c index e38e65c09a4..8b350afceef 100644 --- a/nrf24batch/nrf24batch.c +++ b/nrf24batch/nrf24batch.c @@ -1092,8 +1092,9 @@ static void save_batch(void) { } static void input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); + PluginEvent event = {.type = EventTypeKey, .input = *input_event}; furi_message_queue_put(event_queue, &event, FuriWaitForever); } diff --git a/nrf24mousejacker/mousejacker.c b/nrf24mousejacker/mousejacker.c index 56a898a5288..e7c164b9a78 100644 --- a/nrf24mousejacker/mousejacker.c +++ b/nrf24mousejacker/mousejacker.c @@ -93,8 +93,8 @@ static void render_callback(Canvas* const canvas, void* ctx) { } static void input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); PluginEvent event = {.type = EventTypeKey, .input = *input_event}; furi_message_queue_put(event_queue, &event, FuriWaitForever); diff --git a/nrf24scan/nrf24scan.c b/nrf24scan/nrf24scan.c index 2309281948c..7779626a76b 100644 --- a/nrf24scan/nrf24scan.c +++ b/nrf24scan/nrf24scan.c @@ -457,8 +457,9 @@ static uint8_t load_settings_file(Stream* file_stream) { } static void input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); + PluginEvent event = {.type = EventTypeKey, .input = *input_event}; furi_message_queue_put(event_queue, &event, FuriWaitForever); } diff --git a/nrf24sniff/nrfsniff.c b/nrf24sniff/nrfsniff.c index 9f6ec803ed7..bef727a7381 100644 --- a/nrf24sniff/nrfsniff.c +++ b/nrf24sniff/nrfsniff.c @@ -129,8 +129,8 @@ static void render_callback(Canvas* const canvas, void* ctx) { } static void input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); PluginEvent event = {.type = EventTypeKey, .input = *input_event}; furi_message_queue_put(event_queue, &event, FuriWaitForever); diff --git a/paint/application.fam b/paint/application.fam index 0f6038d4e55..65306253724 100644 --- a/paint/application.fam +++ b/paint/application.fam @@ -11,6 +11,6 @@ App( fap_category="Media", fap_author="@n-o-T-I-n-s-a-n-e", fap_weburl="https://github.com/n-o-T-I-n-s-a-n-e", - fap_version="1.1", + fap_version="1.2", fap_description="A basic Paint app, Click Ok to draw dot, hold Ok to enable drawing continuously, hold Back to clear the screen", ) diff --git a/passgen/application.fam b/passgen/application.fam index 99661090695..d0826658e14 100644 --- a/passgen/application.fam +++ b/passgen/application.fam @@ -10,6 +10,6 @@ App( fap_icon="icons/passgen_icon.png", fap_icon_assets="icons", fap_author="@anakod & @henrygab", - fap_version="1.2", + fap_version="1.3", fap_description="Simple password generator", ) diff --git a/passgen/passgen.c b/passgen/passgen.c index 46aa4541e41..4a530b9bdd5 100644 --- a/passgen/passgen.c +++ b/passgen/passgen.c @@ -64,7 +64,7 @@ typedef struct { FuriMessageQueue* input_queue; ViewPort* view_port; Gui* gui; - FuriMutex** mutex; + FuriMutex* mutex; NotificationApp* notify; const char* alphabet; char password[PASSGEN_MAX_LENGTH + 1]; diff --git a/picopass/.catalog/README.md b/picopass/.catalog/README.md index 11210726d89..1df70aa5139 100644 --- a/picopass/.catalog/README.md +++ b/picopass/.catalog/README.md @@ -20,7 +20,7 @@ NOTE: If the screen says “Got std key” AND stays on 0/18, then loclass isn't 1. Download the loclass log (_sdcard/apps_data/picopass/.loclass.log_) from your Flipper Zero. 2. Use [loclass.ericbetts.dev](https://loclass.ericbetts.dev/) or a tool of your choice to calculate the key 3. Copy the key to _iclass_elite_dict_user.txt_ and place in _sdcard/apps_data/picopass/assets/_ -4. Run _Elite Dict. Attack_ from the picopass main menu +4. Run _Read_ from the picopass main menu 5. Present card to the back of the Flipper Zero. ## Failure @@ -34,9 +34,9 @@ There are some situations when the offline loclass may not find a key, such as: # NR-MAC read -Due to the nature of how secure picopass works, it is possible to emulate some public fields from a card and capture the reader's response, which can be used to authenticate. Two of the pieces involved in this are the NR and MAC. +Due to the nature of how secure picopass works, it is possible to emulate some public fields from a card and capture the reader's response, which can be used to authenticate. Two of the pieces involved in this are the NR and MAC. This allows you to get a dump of the card, except for the key, even if you don't know the key. For picopass in non-HID systems this can allow you to see what the data looks like. For iClass SE the data is encrypted (SIO), but a friend with a HID SAM can decrypt it. -These instructions are intended to be performed all at the same time. If you use the card with the reader between Card Part 1 and Card Part 2, then Card Part 2 will fail. +*These instructions are intended to be performed all at the same time. If you use the card with the reader between Card Part 1 and Card Part 2, then Card Part 2 will fail.* ## Card Part 1 @@ -44,8 +44,9 @@ These instructions are intended to be performed all at the same time. If you us 2. Run _Read_ from the picopass main menu 3. Get a "Read Failed" message 4. Select the "Menu" option -5. Select "Save Partial" +5. Select "Save Partial" (regardless if this card has been saved previously) 6. Name file something you'll remember +7. Immediately proceed to Reader Part ## Reader Part @@ -54,10 +55,18 @@ These instructions are intended to be performed all at the same time. If you us 3. Select _Emulate_ 4. Expose Flipper Zero to reader (It may work better a few inches from the reader, as opposed to physically touching) 5. Flipper will buzz and screen will say "NR-MAC Saved!" +6. Immediately proceed to Card Part 2 ## Card Part 2 1. Place card against Flipper Zero 2. Run _Read_ from the picopass main menu 3. Card will authenticate and read +4. Suggested to both "Save" the card and "Save as Seader" + +# Elite Keygen Attack + +Background: https://youtu.be/MKSXSKQHz6o?si=DEKkW60x858pUI0a&t=600 + +The keys used for early Elite systems used the VB6 (yes, as in Visual Basic) RNG to generate the keys. This attack uses the known VB6 RNG to generate the keys. This attack is only useful for early Elite systems, as later systems are keyed in some other manor. Since this can generate an insanely large number of values (and eventually loop), by default it is limited to the first 2000 keys. Please provide feedback if you would like this increased. Also, the leaked iCopyX dictionary included 700ish of these, so the first 700 are redundant to the System Elite Dictionary attack run during "Read". This attack is not useful for iClass SE systems. diff --git a/picopass/.catalog/changelog.md b/picopass/.catalog/changelog.md index b84fce83a59..4e373bb526a 100644 --- a/picopass/.catalog/changelog.md +++ b/picopass/.catalog/changelog.md @@ -1,3 +1,7 @@ +## 1.16 + - Acknowledgements page + - Elite VB6 RNG keygen attack + - Bump plugin version ## 1.15 - Add downgrade from iClass SR to iClass Legacy ## 1.14 diff --git a/picopass/acknowledgements.h b/picopass/acknowledgements.h index bc65cb76445..9f2eac90720 100644 --- a/picopass/acknowledgements.h +++ b/picopass/acknowledgements.h @@ -1,2 +1,10 @@ const char* acknowledgements_text = - "The developers of Picopass would like to humbly acknowledge the work of those who came before and made this possible.\nWe stand on the shoulders of giants.\nFlavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and Milosch Meriac for their research on iClass. Martin HS (holiman) for their work on the loclass library. Iceman and the Proxmark3 community."; + "The developers of Picopass would like to humbly acknowledge the work of those who came before and made this possible. (cont.)\ + \nWe stand on the shoulders of giants:\ + \n* Flavio D. Garcia\ + \n* Gerhard de Koning Gans\ + \n* Roel Verdult \ + \n* Milosch Meriac \ + \nfor their research on iClass.\ + \nMartin HS (holiman) for their work on the loclass library.\ + \nIceman and the Proxmark3 community."; diff --git a/picopass/application.fam b/picopass/application.fam index afc9076737f..c471069760e 100644 --- a/picopass/application.fam +++ b/picopass/application.fam @@ -14,7 +14,7 @@ App( ], stack_size=4 * 1024, fap_description="App to communicate with NFC tags using the PicoPass(iClass) format", - fap_version="1.15", + fap_version="1.16", fap_icon="125_10px.png", fap_category="NFC", fap_libs=["mbedtls"], diff --git a/picopass/config_cards/AV1.picopass b/picopass/config_cards/AV1.picopass new file mode 100755 index 00000000000..46e4e7286c4 --- /dev/null +++ b/picopass/config_cards/AV1.picopass @@ -0,0 +1,22 @@ +Filetype: Flipper Picopass device +Version: 1 +Credential: 00 00 00 00 00 00 00 00 +# Picopass blocks +Block 0: 6D C2 5B 15 FE FF 12 E0 +Block 1: 12 FF FF FF 7F 1F FF 3C +Block 2: FF FF FF FF 05 FE FF FF +Block 3: B2 45 35 54 FC 7F 41 48 +Block 4: FF FF FF FF FF FF FF FF +Block 5: FF FF FF FF FF FF FF FF +Block 6: 00 00 00 00 00 00 BF 18 +Block 7: AC 00 A8 8F A7 80 A9 01 +Block 8: FF FF FF FF FF FF FF FF +Block 9: FF FF FF FF FF FF FF FF +Block 10: FF FF FF FF FF FF FF FF +Block 11: FF FF FF FF FF FF FF FF +Block 12: FF FF FF FF FF FF FF FF +Block 13: FF FF FF FF FF FF FF FF +Block 14: FF FF FF FF FF FF FF FF +Block 15: FF FF FF FF FF FF FF FF +Block 16: FF FF FF FF FF FF FF FF +Block 17: FF FF FF FF FF FF FF FF diff --git a/picopass/config_cards/AV2.picopass b/picopass/config_cards/AV2.picopass new file mode 100755 index 00000000000..95e1d16394c --- /dev/null +++ b/picopass/config_cards/AV2.picopass @@ -0,0 +1,22 @@ +Filetype: Flipper Picopass device +Version: 1 +Credential: 00 00 00 00 00 00 00 00 +# Picopass blocks +Block 0: 6D C2 5B 15 FE FF 12 E0 +Block 1: 12 FF FF FF 7F 1F FF 3C +Block 2: FF FF FF FF 05 FE FF FF +Block 3: B2 45 35 54 FC 7F 41 48 +Block 4: FF FF FF FF FF FF FF FF +Block 5: FF FF FF FF FF FF FF FF +Block 6: 00 00 00 00 00 00 87 18 +Block 7: AC 00 A8 1F A7 80 A9 01 +Block 8: FF FF FF FF FF FF FF FF +Block 9: FF FF FF FF FF FF FF FF +Block 10: FF FF FF FF FF FF FF FF +Block 11: FF FF FF FF FF FF FF FF +Block 12: FF FF FF FF FF FF FF FF +Block 13: FF FF FF FF FF FF FF FF +Block 14: FF FF FF FF FF FF FF FF +Block 15: FF FF FF FF FF FF FF FF +Block 16: FF FF FF FF FF FF FF FF +Block 17: FF FF FF FF FF FF FF FF diff --git a/picopass/config_cards/AV3.picopass b/picopass/config_cards/AV3.picopass new file mode 100755 index 00000000000..e27fa27d2ec --- /dev/null +++ b/picopass/config_cards/AV3.picopass @@ -0,0 +1,22 @@ +Filetype: Flipper Picopass device +Version: 1 +Credential: 00 00 00 00 00 00 00 00 +# Picopass blocks +Block 0: 6D C2 5B 15 FE FF 12 E0 +Block 1: 12 FF FF FF 7F 1F FF 3C +Block 2: FF FF FF FF 05 FE FF FF +Block 3: B2 45 35 54 FC 7F 41 48 +Block 4: FF FF FF FF FF FF FF FF +Block 5: FF FF FF FF FF FF FF FF +Block 6: 00 00 00 00 00 00 BF 18 +Block 7: AC 00 A8 0F A9 03 A7 80 +Block 8: FF FF FF FF FF FF FF FF +Block 9: FF FF FF FF FF FF FF FF +Block 10: FF FF FF FF FF FF FF FF +Block 11: FF FF FF FF FF FF FF FF +Block 12: FF FF FF FF FF FF FF FF +Block 13: FF FF FF FF FF FF FF FF +Block 14: FF FF FF FF FF FF FF FF +Block 15: FF FF FF FF FF FF FF FF +Block 16: FF FF FF FF FF FF FF FF +Block 17: FF FF FF FF FF FF FF FF diff --git a/picopass/config_cards/CSN1.picopass b/picopass/config_cards/CSN1.picopass new file mode 100755 index 00000000000..19f816c172d --- /dev/null +++ b/picopass/config_cards/CSN1.picopass @@ -0,0 +1,22 @@ +Filetype: Flipper Picopass device +Version: 1 +Credential: 00 00 00 00 00 00 00 00 +# Picopass blocks +Block 0: 6D C2 5B 15 FE FF 12 E0 +Block 1: 12 FF FF FF 7F 1F FF 3C +Block 2: FF FF FF FF 05 FE FF FF +Block 3: B2 45 35 54 FC 7F 41 48 +Block 4: FF FF FF FF FF FF FF FF +Block 5: FF FF FF FF FF FF FF FF +Block 6: 00 00 00 00 00 00 BF 18 +Block 7: AC 01 A7 80 A8 9F A9 01 +Block 8: FF FF FF FF FF FF FF FF +Block 9: FF FF FF FF FF FF FF FF +Block 10: FF FF FF FF FF FF FF FF +Block 11: FF FF FF FF FF FF FF FF +Block 12: FF FF FF FF FF FF FF FF +Block 13: FF FF FF FF FF FF FF FF +Block 14: FF FF FF FF FF FF FF FF +Block 15: FF FF FF FF FF FF FF FF +Block 16: FF FF FF FF FF FF FF FF +Block 17: FF FF FF FF FF FF FF FF diff --git a/picopass/config_cards/CSN2.picopass b/picopass/config_cards/CSN2.picopass new file mode 100755 index 00000000000..7d831cc7952 --- /dev/null +++ b/picopass/config_cards/CSN2.picopass @@ -0,0 +1,22 @@ +Filetype: Flipper Picopass device +Version: 1 +Credential: 00 00 00 00 00 00 00 00 +# Picopass blocks +Block 0: 6D C2 5B 15 FE FF 12 E0 +Block 1: 12 FF FF FF 7F 1F FF 3C +Block 2: FF FF FF FF 05 FE FF FF +Block 3: B2 45 35 54 FC 7F 41 48 +Block 4: FF FF FF FF FF FF FF FF +Block 5: FF FF FF FF FF FF FF FF +Block 6: 00 00 00 00 00 00 BF 18 +Block 7: AC 02 A7 80 A8 9F A9 01 +Block 8: FF FF FF FF FF FF FF FF +Block 9: FF FF FF FF FF FF FF FF +Block 10: FF FF FF FF FF FF FF FF +Block 11: FF FF FF FF FF FF FF FF +Block 12: FF FF FF FF FF FF FF FF +Block 13: FF FF FF FF FF FF FF FF +Block 14: FF FF FF FF FF FF FF FF +Block 15: FF FF FF FF FF FF FF FF +Block 16: FF FF FF FF FF FF FF FF +Block 17: FF FF FF FF FF FF FF FF diff --git a/picopass/config_cards/CSN3.picopass b/picopass/config_cards/CSN3.picopass new file mode 100755 index 00000000000..867ec003fa4 --- /dev/null +++ b/picopass/config_cards/CSN3.picopass @@ -0,0 +1,22 @@ +Filetype: Flipper Picopass device +Version: 1 +Credential: 00 00 00 00 00 00 00 00 +# Picopass blocks +Block 0: 6D C2 5B 15 FE FF 12 E0 +Block 1: 12 FF FF FF 7F 1F FF 3C +Block 2: FF FF FF FF 05 FE FF FF +Block 3: B2 45 35 54 FC 7F 41 48 +Block 4: FF FF FF FF FF FF FF FF +Block 5: FF FF FF FF FF FF FF FF +Block 6: 00 00 00 00 00 00 BF 18 +Block 7: AC 03 A7 80 A8 9F A9 01 +Block 8: FF FF FF FF FF FF FF FF +Block 9: FF FF FF FF FF FF FF FF +Block 10: FF FF FF FF FF FF FF FF +Block 11: FF FF FF FF FF FF FF FF +Block 12: FF FF FF FF FF FF FF FF +Block 13: FF FF FF FF FF FF FF FF +Block 14: FF FF FF FF FF FF FF FF +Block 15: FF FF FF FF FF FF FF FF +Block 16: FF FF FF FF FF FF FF FF +Block 17: FF FF FF FF FF FF FF FF diff --git a/picopass/config_cards/KP1.picopass b/picopass/config_cards/KP1.picopass new file mode 100755 index 00000000000..cf2836c5caf --- /dev/null +++ b/picopass/config_cards/KP1.picopass @@ -0,0 +1,22 @@ +Filetype: Flipper Picopass device +Version: 1 +Credential: 00 00 00 00 00 00 00 00 +# Picopass blocks +Block 0: 6D C2 5B 15 FE FF 12 E0 +Block 1: 12 FF FF FF 7F 1F FF 3C +Block 2: FF FF FF FF 05 FE FF FF +Block 3: B2 45 35 54 FC 7F 41 48 +Block 4: FF FF FF FF FF FF FF FF +Block 5: FF FF FF FF FF FF FF FF +Block 6: 00 00 00 00 00 00 BF 18 +Block 7: AE 01 00 00 00 00 00 00 +Block 8: FF FF FF FF FF FF FF FF +Block 9: FF FF FF FF FF FF FF FF +Block 10: FF FF FF FF FF FF FF FF +Block 11: FF FF FF FF FF FF FF FF +Block 12: FF FF FF FF FF FF FF FF +Block 13: FF FF FF FF FF FF FF FF +Block 14: FF FF FF FF FF FF FF FF +Block 15: FF FF FF FF FF FF FF FF +Block 16: FF FF FF FF FF FF FF FF +Block 17: FF FF FF FF FF FF FF FF diff --git a/picopass/config_cards/KP2.picopass b/picopass/config_cards/KP2.picopass new file mode 100755 index 00000000000..bb8f1b5ca56 --- /dev/null +++ b/picopass/config_cards/KP2.picopass @@ -0,0 +1,22 @@ +Filetype: Flipper Picopass device +Version: 1 +Credential: 00 00 00 00 00 00 00 00 +# Picopass blocks +Block 0: 6D C2 5B 15 FE FF 12 E0 +Block 1: 12 FF FF FF 7F 1F FF 3C +Block 2: FF FF FF FF 05 FE FF FF +Block 3: B2 45 35 54 FC 7F 41 48 +Block 4: FF FF FF FF FF FF FF FF +Block 5: FF FF FF FF FF FF FF FF +Block 6: 00 00 00 00 00 00 BF 18 +Block 7: AE 0B AF FF AD 15 B3 03 +Block 8: FF FF FF FF FF FF FF FF +Block 9: FF FF FF FF FF FF FF FF +Block 10: FF FF FF FF FF FF FF FF +Block 11: FF FF FF FF FF FF FF FF +Block 12: FF FF FF FF FF FF FF FF +Block 13: FF FF FF FF FF FF FF FF +Block 14: FF FF FF FF FF FF FF FF +Block 15: FF FF FF FF FF FF FF FF +Block 16: FF FF FF FF FF FF FF FF +Block 17: FF FF FF FF FF FF FF FF diff --git a/picopass/config_cards/KP3.picopass b/picopass/config_cards/KP3.picopass new file mode 100755 index 00000000000..66fbcdc27ef --- /dev/null +++ b/picopass/config_cards/KP3.picopass @@ -0,0 +1,22 @@ +Filetype: Flipper Picopass device +Version: 1 +Credential: 00 00 00 00 00 00 00 00 +# Picopass blocks +Block 0: 6D C2 5B 15 FE FF 12 E0 +Block 1: 12 FF FF FF 7F 1F FF 3C +Block 2: FF FF FF FF 05 FE FF FF +Block 3: B2 45 35 54 FC 7F 41 48 +Block 4: FF FF FF FF FF FF FF FF +Block 5: FF FF FF FF FF FF FF FF +Block 6: 00 00 00 00 00 00 BF 18 +Block 7: AD 6D B3 03 00 00 00 00 +Block 8: FF FF FF FF FF FF FF FF +Block 9: FF FF FF FF FF FF FF FF +Block 10: FF FF FF FF FF FF FF FF +Block 11: FF FF FF FF FF FF FF FF +Block 12: FF FF FF FF FF FF FF FF +Block 13: FF FF FF FF FF FF FF FF +Block 14: FF FF FF FF FF FF FF FF +Block 15: FF FF FF FF FF FF FF FF +Block 16: FF FF FF FF FF FF FF FF +Block 17: FF FF FF FF FF FF FF FF diff --git a/picopass/config_cards/KRD.picopass b/picopass/config_cards/KRD.picopass new file mode 100755 index 00000000000..04cdab1dec8 --- /dev/null +++ b/picopass/config_cards/KRD.picopass @@ -0,0 +1,22 @@ +Filetype: Flipper Picopass device +Version: 1 +Credential: 00 00 00 00 00 00 00 00 +# Picopass blocks +Block 0: 6D C2 5B 15 FE FF 12 E0 +Block 1: 12 FF FF FF 7F 1F FF 3C +Block 2: FF FF FF FF 05 FE FF FF +Block 3: B2 45 35 54 FC 7F 41 48 +Block 4: FF FF FF FF FF FF FF FF +Block 5: FF FF FF FF FF FF FF FF +Block 6: 0C 00 00 01 00 00 BF 18 +Block 7: BF 01 FF FF FF FF FF FF +Block 8: FF FF FF FF FF FF FF FF +Block 9: FF FF FF FF FF FF FF FF +Block 10: FF FF FF FF FF FF FF FF +Block 11: FF FF FF FF FF FF FF FF +Block 12: FF FF FF FF FF FF FF FF +Block 13: FF FF FF FF FF FF FF FF +Block 14: FF FF FF FF FF FF FF FF +Block 15: FF FF FF FF FF FF FF FF +Block 16: FF FF FF FF FF FF FF FF +Block 17: FF FF FF FF FF FF FF FF diff --git a/picopass/config_cards/KRE.picopass b/picopass/config_cards/KRE.picopass new file mode 100755 index 00000000000..9c72eceb328 --- /dev/null +++ b/picopass/config_cards/KRE.picopass @@ -0,0 +1,22 @@ +Filetype: Flipper Picopass device +Version: 1 +Credential: 00 00 00 00 00 00 00 00 +# Picopass blocks +Block 0: 6D C2 5B 15 FE FF 12 E0 +Block 1: 12 FF FF FF 7F 1F FF 3C +Block 2: FF FF FF FF 05 FE FF FF +Block 3: B2 45 35 54 FC 7F 41 48 +Block 4: FF FF FF FF FF FF FF FF +Block 5: FF FF FF FF FF FF FF FF +Block 6: 0C 00 00 01 00 00 BF 18 +Block 7: BF 03 FF FF FF FF FF FF +Block 8: FF FF FF FF FF FF FF FF +Block 9: FF FF FF FF FF FF FF FF +Block 10: FF FF FF FF FF FF FF FF +Block 11: FF FF FF FF FF FF FF FF +Block 12: FF FF FF FF FF FF FF FF +Block 13: FF FF FF FF FF FF FF FF +Block 14: FF FF FF FF FF FF FF FF +Block 15: FF FF FF FF FF FF FF FF +Block 16: FF FF FF FF FF FF FF FF +Block 17: FF FF FF FF FF FF FF FF diff --git a/picopass/config_cards/RSTE.picopass b/picopass/config_cards/RSTE.picopass new file mode 100755 index 00000000000..ce41a2ec9c6 --- /dev/null +++ b/picopass/config_cards/RSTE.picopass @@ -0,0 +1,22 @@ +Filetype: Flipper Picopass device +Version: 1 +Credential: 00 00 00 00 00 00 00 00 +# Picopass blocks +Block 0: 6D C2 5B 15 FE FF 12 E0 +Block 1: 12 FF FF FF 7F 1F FF 3C +Block 2: FF FF FF FF 05 FE FF FF +Block 3: B2 45 35 54 FC 7F 41 48 +Block 4: FF FF FF FF FF FF FF FF +Block 5: FF FF FF FF FF FF FF FF +Block 6: 06 00 00 00 00 00 00 1C +Block 7: FF FF FF FF 00 FF FF FF +Block 8: FF FF FF FF FF FF FF FF +Block 9: FF FF FF FF FF FF FF FF +Block 10: FF FF FF FF FF FF FF FF +Block 11: FF FF FF FF FF FF FF FF +Block 12: FF FF FF FF FF FF FF FF +Block 13: FF FF FF FF FF FF FF FF +Block 14: FF FF FF FF FF FF FF FF +Block 15: FF FF FF FF FF FF FF FF +Block 16: FF FF FF FF FF FF FF FF +Block 17: FF FF FF FF FF FF FF FF diff --git a/picopass/config_cards/RSTR.picopass b/picopass/config_cards/RSTR.picopass new file mode 100755 index 00000000000..28cf71f75e3 --- /dev/null +++ b/picopass/config_cards/RSTR.picopass @@ -0,0 +1,22 @@ +Filetype: Flipper Picopass device +Version: 1 +Credential: 00 00 00 00 00 00 00 00 +# Picopass blocks +Block 0: 6D C2 5B 15 FE FF 12 E0 +Block 1: 12 FF FF FF 7F 1F FF 3C +Block 2: FF FF FF FF 05 FE FF FF +Block 3: B2 45 35 54 FC 7F 41 48 +Block 4: FF FF FF FF FF FF FF FF +Block 5: FF FF FF FF FF FF FF FF +Block 6: 00 00 00 00 00 00 00 1C +Block 7: 00 00 00 00 00 00 00 00 +Block 8: FF FF FF FF FF FF FF FF +Block 9: FF FF FF FF FF FF FF FF +Block 10: FF FF FF FF FF FF FF FF +Block 11: FF FF FF FF FF FF FF FF +Block 12: FF FF FF FF FF FF FF FF +Block 13: FF FF FF FF FF FF FF FF +Block 14: FF FF FF FF FF FF FF FF +Block 15: FF FF FF FF FF FF FF FF +Block 16: FF FF FF FF FF FF FF FF +Block 17: FF FF FF FF FF FF FF FF diff --git a/picopass/config_cards/readme.txt b/picopass/config_cards/readme.txt new file mode 100755 index 00000000000..e462f5a6d63 --- /dev/null +++ b/picopass/config_cards/readme.txt @@ -0,0 +1,17 @@ +# Legacy config cards + +Created by arnavoni and inspired by https://github.com/nfc-tools/nfc-iclass + +- [AV1] Audio/Visual #1 - Beep ON LED Off Flash GREEN on read +- [AV2] Audio/Visual #2 - Beep ON LED RED Host must flash GREEN +- [AV3] Audio/Visual #3 - Beep ON LED Off Host must flash RED and/or GREEN +- [KP1] Keypad Output #1 - Buffer ONE key (8 bit Dorado) +- [KP2] Keypad Output #2 - Buffer ONE to FIVE keys (standard 26 bit) +- [KP3] Keypad Output #3 - Local PIN verify +- [CSN1] Mifare CSN #1 - 32 bit reverse output +- [CSN2] Mifare CSN #2 - 16 bit output +- [CSN3] Mifare CSN #3 - 34 bit output +- [KRD] Keyroll DISABLE - Set ELITE Key and DISABLE Keyrolling +- [KRE] Keyroll ENABLE - Set ELITE Key and ENABLE Keyrolling +- [RSTR] Reset READER - Reset READER to defaults +- [RSTE] Reset ENROLLER - Reset ENROLLER to defaults diff --git a/picopass/files/iclass_elite_dict.txt b/picopass/files/iclass_elite_dict.txt index c91b37b4b52..440c92ba3ea 100644 --- a/picopass/files/iclass_elite_dict.txt +++ b/picopass/files/iclass_elite_dict.txt @@ -42,771 +42,771 @@ C1B74D7478053AE2 ## Pastebin keys (icopyx) https://pastebin.com/KWcu0ch6 -FB93B584A5064748 -0B361EDE24ED3625 -E49A2A1092A12148 -1CB2C054D0657700 +DD66EC6C67F210E7 +66EC6C67F210E785 +EC6C67F210E78530 +6C67F210E78530CB +67F210E78530CB94 +F210E78530CB941F +10E78530CB941FBD +E78530CB941FBD59 +8530CB941FBD5993 +30CB941FBD599369 +CB941FBD59936949 +941FBD59936949B4 +1FBD59936949B4C1 +BD59936949B4C15B +59936949B4C15B3F +936949B4C15B3FAE +6949B4C15B3FAE7F +49B4C15B3FAE7F61 +B4C15B3FAE7F61A8 +C15B3FAE7F61A83D +5B3FAE7F61A83DB6 +3FAE7F61A83DB655 +AE7F61A83DB6554C +7F61A83DB6554C16 +61A83DB6554C1617 +A83DB6554C1617AA +3DB6554C1617AA1B +B6554C1617AA1B7D +554C1617AA1B7DA8 +4C1617AA1B7DA8EA +1617AA1B7DA8EACC +17AA1B7DA8EACC5B +AA1B7DA8EACC5B7C +1B7DA8EACC5B7C62 +7DA8EACC5B7C62C4 +A8EACC5B7C62C491 +EACC5B7C62C491C1 +CC5B7C62C491C11B +5B7C62C491C11B39 +7C62C491C11B398C +62C491C11B398C00 +C491C11B398C000D +91C11B398C000D97 +C11B398C000D9719 +1B398C000D9719A1 +398C000D9719A190 +8C000D9719A19023 +000D9719A190237B +0D9719A190237BAE +9719A190237BAE13 +19A190237BAE13DE +A190237BAE13DEBB +90237BAE13DEBBD8 +237BAE13DEBBD810 +7BAE13DEBBD810AC +AE13DEBBD810AC40 +13DEBBD810AC40BF +DEBBD810AC40BF3F +BBD810AC40BF3FB5 +D810AC40BF3FB59F +10AC40BF3FB59F6E +AC40BF3FB59F6E0B +40BF3FB59F6E0B0C +BF3FB59F6E0B0CB4 +3FB59F6E0B0CB425 +B59F6E0B0CB42542 +9F6E0B0CB425428E +6E0B0CB425428EF2 +0B0CB425428EF25C +0CB425428EF25C10 +B425428EF25C100D +25428EF25C100DF7 +428EF25C100DF704 +8EF25C100DF7042E +F25C100DF7042EAE +100DF7042EAE6410 +0DF7042EAE641057 +F7042EAE64105790 +042EAE64105790EB +2EAE64105790EB34 +AE64105790EB34FC +64105790EB34FCAF +105790EB34FCAFA9 +5790EB34FCAFA9ED +90EB34FCAFA9ED38 +EB34FCAFA9ED3807 +34FCAFA9ED3807B7 +FCAFA9ED3807B7C1 +AFA9ED3807B7C106 +A9ED3807B7C106FC +ED3807B7C106FCFC +3807B7C106FCFCC8 +07B7C106FCFCC8B2 +B7C106FCFCC8B2F9 +C106FCFCC8B2F945 +06FCFCC8B2F9456B +FCFCC8B2F9456B8D +FCC8B2F9456B8D58 +C8B2F9456B8D5897 +B2F9456B8D58976C +F9456B8D58976CE5 +456B8D58976CE582 +6B8D58976CE582C3 +8D58976CE582C326 +58976CE582C32634 +976CE582C3263457 +6CE582C32634573C +E582C32634573C17 +82C32634573C1798 +C32634573C1798D0 +2634573C1798D026 +34573C1798D0269B +573C1798D0269B83 +3C1798D0269B83E2 +1798D0269B83E2AF +98D0269B83E2AFFA +D0269B83E2AFFAB4 +269B83E2AFFAB4A6 +9B83E2AFFAB4A6A2 +83E2AFFAB4A6A2A5 +E2AFFAB4A6A2A566 +AFFAB4A6A2A566B8 +FAB4A6A2A566B839 +B4A6A2A566B839BD +A6A2A566B839BDC7 +A2A566B839BDC7DC +A566B839BDC7DC33 +66B839BDC7DC33D5 +B839BDC7DC33D5AB +39BDC7DC33D5ABE8 +BDC7DC33D5ABE827 +C7DC33D5ABE827F9 +DC33D5ABE827F982 +33D5ABE827F982DE +D5ABE827F982DE18 +ABE827F982DE18EF +E827F982DE18EF87 +27F982DE18EF8758 +F982DE18EF875849 +82DE18EF875849BC +DE18EF875849BC3B +18EF875849BC3B29 +EF875849BC3B2953 +875849BC3B29536A +5849BC3B29536A12 +49BC3B29536A1241 +BC3B29536A124174 +3B29536A12417409 +29536A124174096C +536A124174096CD1 +6A124174096CD12A +124174096CD12AF4 +4174096CD12AF4C6 +74096CD12AF4C6B0 +096CD12AF4C6B001 +6CD12AF4C6B00155 +D12AF4C6B0015532 +2AF4C6B0015532FD +F4C6B0015532FDA9 +C6B0015532FDA9EC +B0015532FDA9EC04 +015532FDA9EC0406 +5532FDA9EC04064B +32FDA9EC04064B0C +FDA9EC04064B0CCF +A9EC04064B0CCF69 +EC04064B0CCF691D +04064B0CCF691DE6 +064B0CCF691DE690 +4B0CCF691DE69079 +0CCF691DE6907935 +CF691DE690793509 +691DE69079350928 1DE69079350928E4 -5518848B2E911037 +E69079350928E49A +9079350928E49A2A +79350928E49A2A10 +350928E49A2A1092 +0928E49A2A1092A1 +28E49A2A1092A121 +E49A2A1092A12148 +9A2A1092A12148D0 +2A1092A12148D077 +1092A12148D07735 +92A12148D0773590 +A12148D0773590AD +2148D0773590ADFA +48D0773590ADFA99 +D0773590ADFA99DB +773590ADFA99DBA4 +3590ADFA99DBA4CD +90ADFA99DBA4CD36 +ADFA99DBA4CD3601 +FA99DBA4CD36017C +99DBA4CD36017CAB +DBA4CD36017CABAB +A4CD36017CABABB4 +CD36017CABABB46D +36017CABABB46DFB +017CABABB46DFB93 +7CABABB46DFB93B5 +ABABB46DFB93B584 +ABB46DFB93B584A5 +B46DFB93B584A506 +6DFB93B584A50647 +FB93B584A5064748 +93B584A506474825 +B584A50647482562 +84A50647482562E4 +A50647482562E49E +0647482562E49EDD +47482562E49EDD4B +482562E49EDD4B30 +2562E49EDD4B30EA +62E49EDD4B30EAB0 +E49EDD4B30EAB0F0 +9EDD4B30EAB0F02B +DD4B30EAB0F02B77 +4B30EAB0F02B77CC +30EAB0F02B77CC90 +EAB0F02B77CC90AA +B0F02B77CC90AA19 +F02B77CC90AA19C7 +2B77CC90AA19C73D +77CC90AA19C73D08 +CC90AA19C73D0811 +90AA19C73D0811EE +AA19C73D0811EEE1 +19C73D0811EEE119 +C73D0811EEE11930 +3D0811EEE11930DA +0811EEE11930DA7E +11EEE11930DA7E5F +EEE11930DA7E5F3F +E11930DA7E5F3F43 +1930DA7E5F3F43BA +30DA7E5F3F43BA81 +DA7E5F3F43BA819F +7E5F3F43BA819F19 +5F3F43BA819F199A +3F43BA819F199AF8 +43BA819F199AF82D +BA819F199AF82DD1 +819F199AF82DD18E +9F199AF82DD18E0C +199AF82DD18E0C68 +9AF82DD18E0C68FD +F82DD18E0C68FDAE +2DD18E0C68FDAEFF +D18E0C68FDAEFFD6 +8E0C68FDAEFFD620 +0C68FDAEFFD62043 +68FDAEFFD6204388 +FDAEFFD6204388A3 +AEFFD6204388A3C0 +FFD6204388A3C089 D6204388A3C08982 -DCD2EB1FB841DCDF +204388A3C089828C +4388A3C089828CBD +88A3C089828CBDB3 +A3C089828CBDB3E6 +C089828CBDB3E6FB +89828CBDB3E6FBE0 +828CBDB3E6FBE030 +8CBDB3E6FBE030F7 +BDB3E6FBE030F774 +B3E6FBE030F774B7 +E6FBE030F774B72D +FBE030F774B72DBC +E030F774B72DBC2F +30F774B72DBC2FA1 +F774B72DBC2FA15B +74B72DBC2FA15BB3 +B72DBC2FA15BB307 +2DBC2FA15BB30725 +BC2FA15BB30725F2 +2FA15BB30725F2C4 +A15BB30725F2C492 +5BB30725F2C49288 +B30725F2C49288F5 +0725F2C49288F574 +25F2C49288F57492 +F2C49288F574929E +C49288F574929EB8 +9288F574929EB85B +88F574929EB85B8C +F574929EB85B8CE0 +74929EB85B8CE0A0 +929EB85B8CE0A0D8 +9EB85B8CE0A0D8B6 +B85B8CE0A0D8B6BF +5B8CE0A0D8B6BF2B +8CE0A0D8B6BF2B03 +E0A0D8B6BF2B0316 +A0D8B6BF2B031638 +D8B6BF2B03163830 +B6BF2B03163830E3 +BF2B03163830E3E9 +2B03163830E3E9A9 +03163830E3E9A967 +163830E3E9A967E1 +3830E3E9A967E142 +30E3E9A967E142E3 +E3E9A967E142E32B +E9A967E142E32B7D +A967E142E32B7DF3 +67E142E32B7DF380 +E142E32B7DF3807F +42E32B7DF3807F40 +E32B7DF3807F40B0 +2B7DF3807F40B076 +7DF3807F40B07650 +F3807F40B07650F2 +807F40B07650F272 +7F40B07650F272ED +40B07650F272EDF9 +B07650F272EDF90C +7650F272EDF90C1A +50F272EDF90C1A4E +F272EDF90C1A4E0C +72EDF90C1A4E0C70 +EDF90C1A4E0C7057 +F90C1A4E0C70579D +0C1A4E0C70579D50 +1A4E0C70579D5058 +4E0C70579D5058C9 +0C70579D5058C908 +70579D5058C90806 +579D5058C908068D +9D5058C908068D67 +5058C908068D67C0 +58C908068D67C071 +C908068D67C071D9 +08068D67C071D91E +068D67C071D91E07 +8D67C071D91E0795 +67C071D91E0795BE +C071D91E0795BEBA +71D91E0795BEBA8A +D91E0795BEBA8A3E +1E0795BEBA8A3E68 +0795BEBA8A3E680A +95BEBA8A3E680AF2 +BEBA8A3E680AF244 +BA8A3E680AF244E1 +8A3E680AF244E13F +3E680AF244E13FB6 +680AF244E13FB60E +0AF244E13FB60E84 +F244E13FB60E8496 +44E13FB60E849633 +E13FB60E84963355 +3FB60E84963355B4 +B60E84963355B437 +0E84963355B437FE +84963355B437FE2A +963355B437FE2ACD +3355B437FE2ACD5C +55B437FE2ACD5C79 +B437FE2ACD5C793B +37FE2ACD5C793B5B +FE2ACD5C793B5BB5 +2ACD5C793B5BB5A4 +CD5C793B5BB5A452 +5C793B5BB5A4528B +793B5BB5A4528B0B +3B5BB5A4528B0B36 +5BB5A4528B0B361E +B5A4528B0B361EDE +A4528B0B361EDE24 +528B0B361EDE24ED +8B0B361EDE24ED36 +0B361EDE24ED3625 +361EDE24ED3625E8 +1EDE24ED3625E822 +DE24ED3625E8225B +24ED3625E8225BA9 +ED3625E8225BA9C1 +3625E8225BA9C1A0 +25E8225BA9C1A0FD +E8225BA9C1A0FDAA +225BA9C1A0FDAA48 +5BA9C1A0FDAA48B6 +A9C1A0FDAA48B601 +C1A0FDAA48B6010B +A0FDAA48B6010B1D +FDAA48B6010B1D8B +AA48B6010B1D8BC2 +48B6010B1D8BC24B +B6010B1D8BC24B16 +010B1D8BC24B16B2 +0B1D8BC24B16B256 +1D8BC24B16B256B7 +8BC24B16B256B79D +C24B16B256B79DFE +4B16B256B79DFE12 +16B256B79DFE12DE +B256B79DFE12DE53 +56B79DFE12DE5398 +B79DFE12DE539850 +9DFE12DE53985046 +FE12DE53985046F9 +12DE53985046F94E +DE53985046F94E6F +53985046F94E6F5D +985046F94E6F5D91 +5046F94E6F5D912E 46F94E6F5D912E1C -239D50BF09D9125C -7CABABB46DFB93B5 -29536A124174096C +F94E6F5D912E1CB2 +4E6F5D912E1CB2C0 +6F5D912E1CB2C054 +5D912E1CB2C054D0 +912E1CB2C054D065 +2E1CB2C054D06577 +1CB2C054D0657700 +B2C054D06577009A +C054D06577009ADC +54D06577009ADCD2 +D06577009ADCD2EB 6577009ADCD2EB1F -199AF82DD18E0C68 77009ADCD2EB1FB8 -6A121127DD422E07 +009ADCD2EB1FB841 +9ADCD2EB1FB841DC +DCD2EB1FB841DCDF +D2EB1FB841DCDF08 +EB1FB841DCDF08E5 +1FB841DCDF08E576 +B841DCDF08E576BA +41DCDF08E576BABC +DCDF08E576BABC3D +DF08E576BABC3D54 +08E576BABC3D54B2 +E576BABC3D54B25C +76BABC3D54B25C01 +BABC3D54B25C0158 +BC3D54B25C0158F2 +3D54B25C0158F2FA +54B25C0158F2FA4E +B25C0158F2FA4E3F +5C0158F2FA4E3F0F +0158F2FA4E3F0F64 +58F2FA4E3F0F6404 F2FA4E3F0F640479 -55B437FE2ACD5C79 -FE12DE53985046F9 -E49EDD4B30EAB0F0 -A3C089828CBDB3E6 -62C491C11B398C00 +FA4E3F0F6404798F +4E3F0F6404798F9F +3F0F6404798F9F6C +0F6404798F9F6C38 +6404798F9F6C38A8 +04798F9F6C38A891 +798F9F6C38A8911F +8F9F6C38A8911FC7 +9F6C38A8911FC749 +6C38A8911FC749FE +38A8911FC749FE23 +A8911FC749FE231E +911FC749FE231E5E +1FC749FE231E5EB6 +C749FE231E5EB656 +49FE231E5EB656B3 +FE231E5EB656B350 +231E5EB656B3500C +1E5EB656B3500C10 +5EB656B3500C1092 +B656B3500C1092CC +56B3500C1092CC89 +B3500C1092CC8904 +500C1092CC8904B0 +0C1092CC8904B0C6 +1092CC8904B0C6E2 +92CC8904B0C6E267 +CC8904B0C6E2677D +8904B0C6E2677DBD +04B0C6E2677DBD28 +B0C6E2677DBD2854 +C6E2677DBD2854B8 +E2677DBD2854B840 +677DBD2854B8403F +7DBD2854B8403F70 +BD2854B8403F7087 +2854B8403F7087B1 +54B8403F7087B191 +B8403F7087B191CA +403F7087B191CAC7 +3F7087B191CAC749 +7087B191CAC74903 +87B191CAC7490304 +B191CAC7490304A1 +91CAC7490304A15C +CAC7490304A15C28 +C7490304A15C28B8 +490304A15C28B85E +0304A15C28B85EDF +04A15C28B85EDFB5 A15C28B85EDFB515 -0CBE6CC4851B3ED4 +5C28B85EDFB5157C +28B85EDFB5157C27 +B85EDFB5157C2736 +5EDFB5157C2736C9 +DFB5157C2736C901 +B5157C2736C901F3 +157C2736C901F3FF +7C2736C901F3FF24 +2736C901F3FF240F +36C901F3FF240FAD +C901F3FF240FAD64 +01F3FF240FAD647A +F3FF240FAD647AB9 +FF240FAD647AB9ED +240FAD647AB9ED2D +0FAD647AB9ED2DC9 +AD647AB9ED2DC915 +647AB9ED2DC9153F +7AB9ED2DC9153F44 +B9ED2DC9153F449B +ED2DC9153F449B92 +2DC9153F449B9226 +C9153F449B9226B1 +153F449B9226B12E +3F449B9226B12E8C +449B9226B12E8C61 +9B9226B12E8C61C8 +9226B12E8C61C8D3 +26B12E8C61C8D31E +B12E8C61C8D31E6C +2E8C61C8D31E6CA1 +8C61C8D31E6CA194 +61C8D31E6CA19438 +C8D31E6CA194384A +D31E6CA194384AC9 1E6CA194384AC919 -524556D8E2050B1F -12DE53985046F94E +6CA194384AC919F1 +A194384AC919F182 +94384AC919F18237 +384AC919F18237CC +4AC919F18237CC1E +C919F18237CC1E67 +19F18237CC1E6782 +F18237CC1E67823C +8237CC1E67823C23 +37CC1E67823C239D +CC1E67823C239D50 +1E67823C239D50BF +67823C239D50BF09 +823C239D50BF09D9 +3C239D50BF09D912 +239D50BF09D9125C +9D50BF09D9125CD1 +50BF09D9125CD1E8 +BF09D9125CD1E8EF +09D9125CD1E8EFE8 +D9125CD1E8EFE808 +125CD1E8EFE808F3 +5CD1E8EFE808F3FD +D1E8EFE808F3FD6E +E8EFE808F3FD6E9C +EFE808F3FD6E9C01 +E808F3FD6E9C01B7 +08F3FD6E9C01B7D4 +F3FD6E9C01B7D4EE +FD6E9C01B7D4EEBD +6E9C01B7D4EEBDAC +9C01B7D4EEBDACBC +01B7D4EEBDACBC28 +B7D4EEBDACBC287A +D4EEBDACBC287A74 +EEBDACBC287A74A9 +BDACBC287A74A9D1 +ACBC287A74A9D174 BC287A74A9D174E8 -BC3B29536A124174 -515B00B7D428DAA6 +287A74A9D174E863 +7A74A9D174E8639E +74A9D174E8639E59 +A9D174E8639E5992 +D174E8639E59929C +74E8639E59929C8C +E8639E59929C8C08 +639E59929C8C0863 +9E59929C8C0863D3 +59929C8C0863D32B +929C8C0863D32B98 9C8C0863D32B98A4 -8237CC1E67823C23 -F18237CC1E67823C -FA4E3F0F6404798F -E142E32B7DF3807F -ABE827F982DE18EF +8C0863D32B98A479 +0863D32B98A4793D +63D32B98A4793D9C +D32B98A4793D9C2F +2B98A4793D9C2F53 +98A4793D9C2F537F +A4793D9C2F537FA5 +793D9C2F537FA5DF +3D9C2F537FA5DF1F +9C2F537FA5DF1FC7 +2F537FA5DF1FC709 +537FA5DF1FC70945 +7FA5DF1FC709457A +A5DF1FC709457A4F +DF1FC709457A4FE3 +1FC709457A4FE39D +C709457A4FE39D01 +09457A4FE39D0151 +457A4FE39D01515B +7A4FE39D01515B00 +4FE39D01515B00B7 +E39D01515B00B7D4 +9D01515B00B7D428 +01515B00B7D428DA +515B00B7D428DAA6 +5B00B7D428DAA6C5 +00B7D428DAA6C552 +B7D428DAA6C5529F +D428DAA6C5529FC9 +28DAA6C5529FC949 +DAA6C5529FC9493D +A6C5529FC9493DBA +C5529FC9493DBA2A +529FC9493DBA2A52 +9FC9493DBA2A52E3 +C9493DBA2A52E3C6 +493DBA2A52E3C648 +3DBA2A52E3C64870 +BA2A52E3C6487061 +2A52E3C648706101 +52E3C648706101BB +E3C648706101BBEA +C648706101BBEAB5 +48706101BBEAB5FE +706101BBEAB5FE1B +6101BBEAB5FE1B0E +01BBEAB5FE1B0EC6 +BBEAB5FE1B0EC69A +EAB5FE1B0EC69A1D +B5FE1B0EC69A1DC5 +FE1B0EC69A1DC5A4 +1B0EC69A1DC5A430 +0EC69A1DC5A430FF +C69A1DC5A430FF6A +9A1DC5A430FF6A12 +1DC5A430FF6A1211 +C5A430FF6A121127 +A430FF6A121127DD +30FF6A121127DD42 +FF6A121127DD422E +6A121127DD422E07 +121127DD422E07D3 +1127DD422E07D3DF +27DD422E07D3DF18 +DD422E07D3DF1843 +422E07D3DF184370 +2E07D3DF18437050 +07D3DF184370502B +D3DF184370502B16 +DF184370502B1617 +184370502B16173C +4370502B16173C05 +70502B16173C05F1 +502B16173C05F181 +2B16173C05F18149 +16173C05F181493D +173C05F181493D66 +3C05F181493D660C +05F181493D660C2A +F181493D660C2A52 81493D660C2A5245 -3FAE7F61A83DB655 -D2EB1FB841DCDF08 -C919F18237CC1E67 -647AB9ED2DC9153F -537FA5DF1FC70945 +493D660C2A524556 +3D660C2A524556D8 +660C2A524556D8E2 +0C2A524556D8E205 +2A524556D8E2050B +524556D8E2050B1F +4556D8E2050B1F1D +56D8E2050B1F1D65 +D8E2050B1F1D65FB +E2050B1F1D65FB5D +050B1F1D65FB5D78 +0B1F1D65FB5D7852 +1F1D65FB5D785270 +1D65FB5D78527086 +65FB5D78527086A6 FB5D78527086A60C -CAC7490304A15C28 -E39D01515B00B7D4 -5B3FAE7F61A83DB6 -3C384BE84F5A6B78 -AE13DEBBD810AC40 -9F6E0B0CB425428E -912E1CB2C054D065 -C071D91E0795BEBA -4C1617AA1B7DA8EA -74096CD12AF4C6B0 -48B6010B1D8BC24B -3B29536A12417409 -240FAD647AB9ED2D -56B3500C1092CC89 -AC40BF3FB59F6E0B -C7490304A15C28B8 -8A3E680AF244E13F -AFFAB4A6A2A566B8 +5D78527086A60CBE 78527086A60CBE6C -ED2DC9153F449B92 -E6FBE030F774B72D -61A83DB6554C1617 -87B191CAC7490304 -19C73D0811EEE119 -680AF244E13FB60E -27DD422E07D3DF18 -B841DCDF08E576BA -FC22F72AC9C2E6DB -5058C908068D67C0 -5D912E1CB2C054D0 -1FBD59936949B4C1 -01515B00B7D428DA -16B256B79DFE12DE -AD647AB9ED2DC915 -30F774B72DBC2FA1 -384AC919F18237CC -0795BEBA8A3E680A -691DE69079350928 -C15B3FAE7F61A83D -823C239D50BF09D9 -AA1B7DA8EACC5B7C -1D8BC24B16B256B7 -74B72DBC2FA15BB3 -2B03163830E3E9A9 -EACC5B7C62C491C1 -1162DD6A97FAC8D2 -5046F94E6F5D912E -2DC9153F449B9226 -153F449B9226B12E -BD59936949B4C15B +527086A60CBE6CC4 +7086A60CBE6CC485 +86A60CBE6CC4851B +A60CBE6CC4851B3E +0CBE6CC4851B3ED4 BE6CC4851B3ED409 -793B5BB5A4528B0B -10AC40BF3FB59F6E -ABABB46DFB93B584 -204388A3C089828C -71D91E0795BEBA8A -2DBC2FA15BB30725 -B79DFE12DE539850 -8C0863D32B98A479 +6CC4851B3ED409B1 +C4851B3ED409B14E +851B3ED409B14E6C 1B3ED409B14E6C24 -B0C6E2677DBD2854 -C32634573C1798D0 -536A124174096CD1 +3ED409B14E6C24F2 +D409B14E6C24F217 +09B14E6C24F217AF +B14E6C24F217AFC1 +4E6C24F217AFC12C +6C24F217AFC12C7E +24F217AFC12C7E7D +F217AFC12C7E7D8F + +5518848B2E911037 +3C384BE84F5A6B78 +FC22F72AC9C2E6DB +1162DD6A97FAC8D2 B883C57781CDC832 -30E3E9A967E142E3 -660C2A524556D8E2 -04B0C6E2677DBD28 -38A8911FC749FE23 -1FB841DCDF08E576 -CB941FBD59936949 -D428DAA6C5529FC9 -482562E49EDD4B30 9D76908782D1A7FE -976CE582C3263457 -2DD18E0C68FDAEFF -B30725F2C49288F5 -9EDD4B30EAB0F02B -0647482562E49EDD -8F9F6C38A8911FC7 -B60E84963355B437 6F8D453205DB962B -0FAD647AB9ED2DC9 -94384AC919F18237 7E14BD46BAD35522 -E78530CB941FBD59 -3DBA2A52E3C64870 -9079350928E49A2A -B3E6FBE030F774B7 -BF2B03163830E3E9 -B584A50647482562 -AE7F61A83DB6554C -3D660C2A524556D8 -7E5F3F43BA819F19 -3F7087B191CAC749 -04A15C28B85EDFB5 DA7B6144B03E1BB1 -5BB5A4528B0B361E -EDF90C1A4E0C7057 -529FC9493DBA2A52 -2ACD5C793B5BB5A4 -C8B2F9456B8D5897 -83E2AFFAB4A6A2A5 -48D0773590ADFA99 -1617AA1B7DA8EACC -88A3C089828CBDB3 F5B3F854EC33DA38 -B14E6C24F217AFC1 -6F5D912E1CB2C054 -5EDFB5157C2736C9 -A6A2A566B839BDC7 6A3B86281DF16B36 -C24B16B256B79DFE -9C01B7D4EEBDACBC -C8D31E6CA194384A -0C2A524556D8E205 -C69A1DC5A430FF6A -0863D32B98A4793D -A2A566B839BDC7DC -8530CB941FBD5993 -706101BBEAB5FE1B -DEFD1FED8E326B65 -0C68FDAEFFD62043 -1D65FB5D78527086 -93B584A506474825 -59929C8C0863D32B -502B16173C05F181 -A4793D9C2F537FA5 -1A4E0C70579D5058 -EEBDACBC287A74A9 -07B7C106FCFCC8B2 -FE2ACD5C793B5BB5 -DEBBD810AC40BF3F -105790EB34FCAFA9 -AEFFD6204388A3C0 -C11B398C000D9719 -24F217AFC12C7E7D -0AE186B3AAE8271A -CD36017CABABB46D -1E0795BEBA8A3E68 -017CABABB46DFB93 -6CD12AF4C6B00155 -18EF875849BC3B29 -AFA9ED3807B7C106 -95BEBA8A3E680AF2 -225BA9C1A0FDAA48 -48706101BBEAB5FE -BF09D9125CD1E8EF -456B8D58976CE582 -99DBA4CD36017CAB -EEE11930DA7E5F3F -1E5EB656B3500C10 -86A60CBE6CC4851B -B2F9456B8D58976C -8C000D9719A19023 -1B0EC69A1DC5A430 -5849BC3B29536A12 -CC1E67823C239D50 -7DA8EACC5B7C62C4 -FCAFA9ED3807B7C1 -D9125CD1E8EFE808 -3B5BB5A4528B0B36 -EC6C67F210E78530 -5D78527086A60CBE -E8225BA9C1A0FDAA -819F199AF82DD18E -28B85EDFB5157C27 -773590ADFA99DBA4 -9A2A1092A12148D0 -124174096CD12AF4 -03163830E3E9A967 -F25C100DF7042EAE -D91E0795BEBA8A3E -B72DBC2FA15BB307 -D1E8EFE808F3FD6E -F774B72DBC2FA15B -25E8225BA9C1A0FD -7A4FE39D01515B00 -2E1CB2C054D06577 -8EF25C100DF7042E -965D6E234471D87E -FDAA48B6010B1D8B -573C1798D0269B83 -B5FE1B0EC69A1DC5 -5B8CE0A0D8B6BF2B -C6E2677DBD2854B8 -44E13FB60E849633 -5BB30725F2C49288 -9E4411D032C2507A -8E0C68FDAEFFD620 -B2C054D06577009A -DD66EC6C67F210E7 -06FCFCC8B2F9456B -72EDF90C1A4E0C70 -0E84963355B437FE -40BF3FB59F6E0B0C -7650F272EDF90C1A -2562E49EDD4B30EA -C5529FC9493DBA2A -4556D8E2050B1F1D +DEFD1FED8E326B65 +0AE186B3AAE8271A +965D6E234471D87E +9E4411D032C2507A 453FB5A1FEDA63B7 -61C8D31E6CA19438 -A5DF1FC709457A4F -24ED3625E8225BA9 -54B8403F7087B191 -F7042EAE64105790 -08F3FD6E9C01B7D4 -79350928E49A2A10 -F82DD18E0C68FDAE -9D50BF09D9125CD1 -269B83E2AFFAB4A6 -52E3C648706101BB -B191CAC7490304A1 -0F6404798F9F6C38 -828CBDB3E6FBE030 -3C05F181493D660C -9719A190237BAE13 -91CAC7490304A15C -A190237BAE13DEBB -76BABC3D54B25C01 -63D32B98A4793D9C -6C38A8911FC749FE -A4528B0B361EDE24 -E3C648706101BBEA -4B30EAB0F02B77CC -B3500C1092CC8904 -FE1B0EC69A1DC5A4 -F02B77CC90AA19C7 -422E07D3DF184370 -2FA15BB30725F2C4 -19A190237BAE13DE -7A74A9D174E8639E -BEBA8A3E680AF244 -9ADCD2EB1FB841DC -6B8D58976CE582C3 -911FC749FE231E5E -0CB425428EF25C10 -89828CBDB3E6FBE0 -163830E3E9A967E1 -58C908068D67C071 -0AF244E13FB60E84 -5B00B7D428DAA6C5 -3E680AF244E13FB6 -8CBDB3E6FBE030F7 73809262FEF07B22 -C7DC33D5ABE827F9 -1930DA7E5F3F43BA -F181493D660C2A52 -FCFCC8B2F9456B8D -B5A4528B0B361EDE -9FC9493DBA2A52E3 31FEAFF95861995F -84A50647482562E4 -3D0811EEE11930DA -ED3807B7C106FCFC -EB1FB841DCDF08E5 -493D660C2A524556 -B6010B1D8BC24B16 -A6C5529FC9493DBA -62E49EDD4B30EAB0 -A9ED3807B7C106FC 63CD88555E147AFB -ED3625E8225BA9C1 -1EDE24ED3625E822 -3FB60E84963355B4 -B256B79DFE12DE53 -3ED409B14E6C24F2 FAE6F51186CF8D27 -DC33D5ABE827F982 -BABC3D54B25C0158 -0C1A4E0C70579D50 -13DEBBD810AC40BF -639E59929C8C0863 -98A4793D9C2F537F -F982DE18EF875849 9C5A67AD8A7840AC -6404798F9F6C38A8 -7BAE13DEBBD810AC -BA2A52E3C6487061 -9AF82DD18E0C68FD 6F0897459D936AC7 AFA785A7DAB33378 -963355B437FE2ACD -E11930DA7E5F3F43 -7C2736C901F3FF24 -DEFB3722DF096419 -43D0E12B39582062 -41DCDF08E576BABC -CE670E1C4BDAEEEF -5CD1E8EFE808F3FD -9D5058C908068D67 -04798F9F6C38A891 -4E3F0F6404798F9F -A566B839BDC7DC33 -90ADFA99DBA4CD36 -FAB4A6A2A566B839 -050B1F1D65FB5D78 -4FE39D01515B00B7 -3830E3E9A967E142 -92CC8904B0C6E267 -A194384AC919F182 -A9D174E8639E5992 -EFE808F3FD6E9C01 -0B1F1D65FB5D7852 -765D0B2EB5560D87 -1127DD422E07D3DF -974CC752C4A8166E -1B398C000D9719A1 -77CC90AA19C73D08 -173C05F181493D66 -579D5058C908068D -121127DD422E07D3 -985046F94E6F5D91 -4E6C24F217AFC12C -E2AFFAB4A6A2A566 -74929EB85B8CE0A0 -1ABDD3794309EAEA -C6B0015532FDA9EC -01B7D4EEBDACBC28 -D409B14E6C24F217 -096CD12AF4C6B001 -2AF4C6B0015532FD -C901F3FF240FAD64 -A15BB30725F2C492 -30EAB0F02B77CC90 -793D9C2F537FA5DF -E13FB60E84963355 -D0269B83E2AFFAB4 -16173C05F181493D -807F40B07650F272 -554C1617AA1B7DA8 -81B3726676CB7DBB -0D9719A190237BAE -184370502B16173C -EC04064B0CCF691D -4E0C70579D5058C9 -49B4C15B3FAE7F61 -3F0F6404798F9F6C -70502B16173C05F1 -E1E1B4AE3317463C -009ADCD2EB1FB841 -493DBA2A52E3C648 -67C071D91E0795BE -E8639E59929C8C08 -0CCF691DE6907935 -58F2FA4E3F0F6404 -31773C059A90CB65 -0304A15C28B85EDF -5EA8BF8FEA56FDD6 -0DF7042EAE641057 -DFB5157C2736C901 -1950A6B44D689D4A -2A52E3C648706101 -30FF6A121127DD42 -F96E53BDBE2CEC52 -E9A967E142E32B7D -DE18EF875849BC3B -9E59929C8C0863D3 -BC3D54B25C0158F2 -428EF25C100DF704 -DCDF08E576BABC3D -2B77CC90AA19C73D -F94E6F5D912E1CB2 -9D01515B00B7D428 -F574929EB85B8CE0 -D8D4682C053F9332 -5532FDA9EC04064B -0158F2FA4E3F0F64 -125CD1E8EFE808F3 -BA819F199AF82DD1 -6A124174096CD12A -68FDAEFFD6204388 -9B9226B12E8C61C8 -B12E8C61C8D31E6C -3807B7C106FCFCC8 -7C62C491C11B398C -C9153F449B9226B1 -D31E6CA194384AC9 -7AB9ED2DC9153F44 -D8E2050B1F1D65FB -E827F982DE18EF87 -DBA4CD36017CABAB -85F114CCBA145C43 -2F537FA5DF1FC709 -F4C6B0015532FDA9 -58976CE582C32634 -D5ABE827F982DE18 -B85EDFB5157C2736 -064B0CCF691DE690 -1092CC8904B0C6E2 -C054D06577009ADC -3C1798D0269B83E2 -67823C239D50BF09 -26B12E8C61C8D31E -ADFA99DBA4CD3601 -85A6D9ABE802C474 -34FCAFA9ED3807B7 -7F40B07650F272ED -D3DF184370502B16 -DA7E5F3F43BA819F -DF184370502B1617 -BB915C51A3258C76 -6C67F210E78530CB -A967E142E32B7DF3 -E582C32634573C17 -F272EDF90C1A4E0C -237BAE13DEBBD810 -6DFB93B584A50647 -FDAEFFD6204388A3 -A50647482562E49E -01F3FF240FAD647A -0928E49A2A1092A1 -D18E0C68FDAEFFD6 -C1A0FDAA48B6010B -E576BABC3D54B25C -1798D0269B83E2AF -33D5ABE827F982DE -56B79DFE12DE5398 -6CE582C32634573C -CC90AA19C73D0811 -54D06577009ADCD2 -07D3DF184370502B -8BC24B16B256B79D -E8EFE808F3FD6E9C -24719A973EDB54F0 -0205AE53351E8E7E -30CB941FBD599369 -DD4B30EAB0F02B77 -B4A6A2A566B839BD -B7C106FCFCC8B2F9 -0725F2C49288F574 -8D58976CE582C326 -7F61A83DB6554C16 -0811EEE11930DA7E -AE64105790EB34FC -AA19C73D0811EEE1 -5C0158F2FA4E3F0F -ABB46DFB93B584A5 -2E07D3DF18437050 -34573C1798D0269B -9EB85B8CE0A0D8B6 -C491C11B398C000D -798F9F6C38A8911F -32FDA9EC04064B0C -B9ED2DC9153F449B -361EDE24ED3625E8 -A12148D0773590AD -A8911FC749FE231E -0EC69A1DC5A430FF -01BBEAB5FE1B0EC6 -A0D8B6BF2B031638 -4AC919F18237CC1E -449B9226B12E8C61 -DE53985046F94E6F -350928E49A2A1092 -DF08E576BABC3D54 -37FE2ACD5C793B5B -010B1D8BC24B16B2 -6CA194384AC919F1 -9226B12E8C61C8D3 +DEFB3722DF096419 +43D0E12B39582062 +CE670E1C4BDAEEEF +765D0B2EB5560D87 +974CC752C4A8166E +1ABDD3794309EAEA +81B3726676CB7DBB +E1E1B4AE3317463C +31773C059A90CB65 +5EA8BF8FEA56FDD6 +1950A6B44D689D4A +F96E53BDBE2CEC52 +D8D4682C053F9332 +85F114CCBA145C43 +85A6D9ABE802C474 +BB915C51A3258C76 +24719A973EDB54F0 +0205AE53351E8E7E B8F813F021E7FF16 -527086A60CBE6CC4 -67E142E32B7DF380 1DEA896C15A01330 -FA99DBA4CD36017C -36C901F3FF240FAD -8B0B361EDE24ED36 -B59F6E0B0CB42542 3D13F9F07B64D966 -40B07650F272EDF9 -C106FCFCC8B2F945 -C5A430FF6A121127 21247DA2D5A1C085 -3D54B25C0158F2FA -2148D0773590ADFA -8C61C8D31E6CA194 -1092A12148D07735 -0C70579D5058C908 -09D9125CD1E8EFE8 -D32B98A4793D9C2F -BBD810AC40BF3FB5 -BDC7DC33D5ABE827 -4388A3C089828CBD -A8EACC5B7C62C491 -C709457A4FE39D01 -04064B0CCF691DE6 -B656B3500C1092CC -2A524556D8E2050B -42E32B7DF3807F40 -3625E8225BA9C1A0 -90EB34FCAFA9ED38 -66EC6C67F210E785 -A9EC04064B0CCF69 -B4C15B3FAE7F61A8 -50F272EDF90C1A4E -B07650F272EDF90C -64105790EB34FCAF -B5157C2736C901F3 96A1D7AB6138B339 -B85B8CE0A0D8B6BF -67F210E78530CB94 -6CC4851B3ED409B1 -4370502B16173C05 -2634573C1798D026 -C908068D67C071D9 B78C814C8EABC1F4 -875849BC3B29536A -B6BF2B03163830E3 -2EAE64105790EB34 -C9493DBA2A52E3C6 -28E49A2A1092A121 -25428EF25C100DF7 -09457A4FE39D0151 -3F449B9226B12E8C -CF691DE690793509 -EAB0F02B77CC90AA -74E8639E59929C8C -8CE0A0D8B6BF2B03 -BC2FA15BB30725F2 -1B7DA8EACC5B7C62 -E32B7DF3807F40B0 -C73D0811EEE11930 -B6554C1617AA1B7D -7DF3807F40B07650 -91C11B398C000D97 7D9A947DA370382D -490304A15C28B85E -7087B191CAC74903 -F9456B8D58976CE5 -FF6A121127DD422E D81512AEB57982DD -7FA5DF1FC709457A -042EAE64105790EB -54B25C0158F2FA4E -BDACBC287A74A9D1 -D06577009ADCD2EB -F210E78530CB941F -65FB5D78527086A6 -0C1092CC8904B0C6 -2E8C61C8D31E6CA1 -3F43BA819F199AF8 -92A12148D0773590 -09B14E6C24F217AF -3C239D50BF09D912 -D174E8639E59929C 3B321CDCADC5601D -BD2854B8403F7087 -FE231E5EB656B350 -941FBD59936949B4 2666EBDD351FDB4C -9A1DC5A430FF6A12 -49BC3B29536A1241 -D810AC40BF3FB59F -157C2736C901F3FF -84963355B437FE2A -FFD6204388A3C089 -66B839BDC7DC33D5 -E030F774B72DBC2F -EAB5FE1B0EC69A1D -2736C901F3FF240F -528B0B361EDE24ED -6E0B0CB425428EF2 -70579D5058C90806 -E808F3FD6E9C01B7 -398C000D9719A190 -851B3ED409B14E6C -6949B4C15B3FAE7F -9288F574929EB85B -2A1092A12148D077 -7DBD2854B8403F70 FB75A77DB568B117 -D8B6BF2B03163830 -ACBC287A74A9D174 -B8403F7087B191CA -F3FD6E9C01B7D4EE -929C8C0863D32B98 06F3D1434297FE44 -A4CD36017CABABB4 -B7D4EEBDACBC287A -DD422E07D3DF1843 -B46DFB93B584A506 -4174096CD12AF4C6 -53985046F94E6F5D -500C1092CC8904B0 -2854B8403F7087B1 2FADA9D2C7DFD116 -0B0CB425428EF25C -2B98A4793D9C2F53 -88F574929EB85B8C -3DB6554C1617AA1B -C089828CBDB3E6FB -E2677DBD2854B840 -90237BAE13DEBBD8 -90AA19C73D0811EE -DAA6C5529FC9493D -98D0269B83E2AFFA -4B16B256B79DFE12 -9C2F537FA5DF1FC7 -E2050B1F1D65FB5D -5C28B85EDFB5157C -59936949B4C15B3F -B437FE2ACD5C793B -FCC8B2F9456B8D58 -C4851B3ED409B14E -1DC5A430FF6A1211 -43BA819F199AF82D -1FC749FE231E5EB6 -C749FE231E5EB656 -39BDC7DC33D5ABE8 -4B0CCF691DE69079 -F244E13FB60E8496 -231E5EB656B3500C -3355B437FE2ACD5C -47482562E49EDD4B -A0FDAA48B6010B1D -E69079350928E49A -82C32634573C1798 70174B4C55081B73 -F3807F40B07650F2 3EAFC735E87AA7EB -5C793B5BB5A4528B -B0F02B77CC90AA19 -5BA9C1A0FDAA48B6 -A83DB6554C1617AA -8D67C071D91E0795 -457A4FE39D01515B -BA8A3E680AF244E1 -DE24ED3625E8225B -27F982DE18EF8758 -D4EEBDACBC287A74 -D12AF4C6B0015532 -677DBD2854B8403F -015532FDA9EC0406 E9D181DCF3606E30 -F90C1A4E0C70579D 7C81AB9730375860 -82DE18EF875849BC -FD6E9C01B7D4EEBD -A60CBE6CC4851B3E -C49288F574929EB8 -08E576BABC3D54B2 -1FC709457A4FE39D -2B16173C05F18149 -56D8E2050B1F1D65 568880F8515A74CE -AA48B6010B1D8BC2 -D0773590ADFA99DB -2B7DF3807F40B076 -F217AFC12C7E7D8F -4E6F5D912E1CB2C0 -287A74A9D174E863 -B0015532FDA9EC04 3D2958F0F4014621 -FDA9EC04064B0CCF FB67D02F86DA35A2 -100DF7042EAE6410 -F3FF240FAD647AB9 -AFA785A7DAB33378 448F839FF4788375 -936949B4C15B3FAE -BDB3E6FBE030F774 -3FB59F6E0B0CB425 -7086A60CBE6CC485 -B839BDC7DC33D5AB 5066F764A834474B -5F3F43BA819F199A -BF3FB59F6E0B0CB4 -BBEAB5FE1B0EC69A -B25C0158F2FA4E3F B92B2F7E515DCAC1 -9DFE12DE53985046 6CC2EF9F295C39DB -5790EB34FCAFA9ED -8904B0C6E2677DBD -FBE030F774B72DBC -DF1FC709457A4FE3 -FF240FAD647AB9ED -F2C49288F574929E -E3E9A967E142E32B -5EB656B3500C1092 -068D67C071D91E07 -10E78530CB941FBD -5B7C62C491C11B39 -EB34FCAFA9ED3807 -25F2C49288F57492 -74A9D174E8639E59 -3590ADFA99DBA4CD -6E9C01B7D4EEBDAC -50BF09D9125CD1E8 -929EB85B8CE0A0D8 -17AA1B7DA8EACC5B -00B7D428DAA6C552 -CC8904B0C6E2677D -6C24F217AFC12C7E -E0A0D8B6BF2B0316 -05F181493D660C2A 82D6B83D9150F82C -A430FF6A121127DD -9F6C38A8911FC749 5B020E96A536B746 -C648706101BBEAB5 -0B1D8BC24B16B256 -08068D67C071D91E -000D9719A190237B -11EEE11930DA7E5F -6101BBEAB5FE1B0E -EF875849BC3B2953 -28DAA6C5529FC949 -36017CABABB46DFB -19F18237CC1E6782 -1F1D65FB5D785270 -B425428EF25C100D -B7D428DAA6C5529F -49FE231E5EB656B3 -403F7087B191CAC7 -CD5C793B5BB5A452 ECC7E9C999843102 E4148EC936302E93 -30DA7E5F3F43BA81 -37CC1E67823C239D -3D9C2F537FA5DF1F -1E67823C239D50BF -9F199AF82DD18E0C -9B83E2AFFAB4A6A2 -A9C1A0FDAA48B601 -CC5B7C62C491C11B diff --git a/picopass/picopass_elite_keygen.c b/picopass/picopass_elite_keygen.c new file mode 100644 index 00000000000..1bd84d6dbd6 --- /dev/null +++ b/picopass/picopass_elite_keygen.c @@ -0,0 +1,60 @@ +#include "picopass_elite_keygen.h" + +/* Based on https://youtu.be/MKSXSKQHz6o?si=DEKkW60x858pUI0a&t=600 */ + +#define INITIAL_SEED 0x429080 + +uint32_t seed = INITIAL_SEED; +uint8_t key_state[8]; +bool prepared = false; + +void picopass_elite_reset() { + memset(key_state, 0, sizeof(key_state)); + seed = INITIAL_SEED; + prepared = false; +} + +uint32_t picopass_elite_lcg() { + uint32_t mod = 0x1000000; // 2^24, + uint32_t a = 0xFD43FD; + uint32_t c = 0xC39EC3; + + return (a * seed + c) % mod; +} + +uint32_t picopass_elite_rng() { + seed = picopass_elite_lcg(); + return seed; +} + +uint8_t picopass_elite_nextByte() { + return (picopass_elite_rng() >> 16) & 0xFF; +} + +void picopass_elite_nextKey(uint8_t* key) { + if(prepared) { + for(size_t i = 0; i < 7; i++) { + key_state[i] = key_state[i + 1]; + } + key_state[7] = picopass_elite_nextByte(); + } else { + for(size_t i = 0; i < 8; i++) { + key_state[i] = picopass_elite_nextByte(); + } + prepared = true; + } + memcpy(key, key_state, 8); +} + +/* +int main() { + size_t limit = 700; + + for (size_t i = 0; i < limit; i++) { + nextKey(); + printKey(key); + // printf("%04lx: %08x\n", i, nextByte()); + } + return 0; +} +*/ diff --git a/picopass/picopass_elite_keygen.h b/picopass/picopass_elite_keygen.h new file mode 100644 index 00000000000..58efeb70165 --- /dev/null +++ b/picopass/picopass_elite_keygen.h @@ -0,0 +1,10 @@ +#pragma once + +#include +#include +#include +#include +#include + +void picopass_elite_nextKey(uint8_t* key); +void picopass_elite_reset(); diff --git a/picopass/plugin/.clang-format b/picopass/plugin/.clang-format new file mode 100644 index 00000000000..4b76f7fa43b --- /dev/null +++ b/picopass/plugin/.clang-format @@ -0,0 +1,191 @@ +--- +Language: Cpp +AccessModifierOffset: -4 +AlignAfterOpenBracket: AlwaysBreak +AlignArrayOfStructures: None +AlignConsecutiveMacros: None +AlignConsecutiveAssignments: None +AlignConsecutiveBitFields: None +AlignConsecutiveDeclarations: None +AlignEscapedNewlines: Left +AlignOperands: Align +AlignTrailingComments: false +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortEnumsOnASingleLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: WithoutElse +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: Yes +AttributeMacros: + - __capability +BinPackArguments: false +BinPackParameters: false +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: true +BreakBeforeBraces: Attach +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: false +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeComma +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: false +ColumnLimit: 99 +CommentPragmas: '^ IWYU pragma:' +QualifierAlignment: Leave +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +PackConstructorInitializers: BinPack +BasedOnStyle: '' +ConstructorInitializerAllOnOneLineOrOnePerLine: false +AllowAllConstructorInitializersOnNextLine: true +FixNamespaceComments: false +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '.*' + Priority: 1 + SortPriority: 0 + CaseSensitive: false + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 1 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseLabels: false +IndentCaseBlocks: false +IndentGotoLabels: true +IndentPPDirectives: None +IndentExternBlock: AfterExternBlock +IndentRequires: false +IndentWidth: 4 +IndentWrappedFunctionNames: true +InsertTrailingCommas: None +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +LambdaBodyIndentation: Signature +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 4 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 10 +PenaltyBreakBeforeFirstCallParameter: 30 +PenaltyBreakComment: 10 +PenaltyBreakFirstLessLess: 0 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakString: 10 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 100 +PenaltyReturnTypeOnItsOwnLine: 60 +PenaltyIndentedWhitespace: 0 +PointerAlignment: Left +PPIndentWidth: -1 +ReferenceAlignment: Pointer +ReflowComments: false +RemoveBracesLLVM: false +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SortIncludes: Never +SortJavaStaticImport: Before +SortUsingDeclarations: false +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: Never +SpaceBeforeParensOptions: + AfterControlStatements: false + AfterForeachMacros: false + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: false + AfterOverloadedOperator: false + BeforeNonEmptyParentheses: false +SpaceAroundPointerQualifiers: Default +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: Never +SpacesInConditionalStatement: false +SpacesInContainerLiterals: false +SpacesInCStyleCastParentheses: false +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +BitFieldColonSpacing: Both +Standard: c++03 +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 4 +UseCRLF: false +UseTab: Never +WhitespaceSensitiveMacros: + - STRINGIZE + - PP_STRINGIZE + - BOOST_PP_STRINGIZE + - NS_SWIFT_NAME + - CF_SWIFT_NAME +... + diff --git a/picopass/plugin/wiegand.c b/picopass/plugin/wiegand.c index 1a87112d06d..a362f2b59c9 100644 --- a/picopass/plugin/wiegand.c +++ b/picopass/plugin/wiegand.c @@ -26,16 +26,39 @@ static inline uint8_t evenparity32(uint32_t x) { return bit_lib_test_parity_32(x, BitLibParityEven); } -static int wiegand_C1k35s_parse(uint8_t bit_length, uint64_t bits, FuriString* description) { - if(bit_length != 35) { - return 0; +uint8_t get_bit_by_position(wiegand_message_t* data, uint8_t pos) { + if(pos >= data->Length) return false; + pos = (data->Length - pos) - + 1; // invert ordering; Indexing goes from 0 to 1. Subtract 1 for weight of bit. + uint8_t result = 0; + if(pos > 95) + result = 0; + else if(pos > 63) + result = (data->Top >> (pos - 64)) & 1; + else if(pos > 31) + result = (data->Mid >> (pos - 32)) & 1; + else + result = (data->Bot >> pos) & 1; + return result; +} + +uint64_t get_linear_field(wiegand_message_t* data, uint8_t firstBit, uint8_t length) { + uint64_t result = 0; + for(uint8_t i = 0; i < length; i++) { + result = (result << 1) | get_bit_by_position(data, firstBit + i); } + return result; +} +static int wiegand_C1k35s_parse(uint8_t bit_length, uint64_t bits, FuriString* description) { wiegand_message_t value; + value.Length = bit_length; value.Mid = bits >> 32; value.Bot = bits; wiegand_message_t* packed = &value; + if(packed->Length != 35) return false; // Wrong length? Stop here. + uint32_t cn = (packed->Bot >> 1) & 0x000FFFFF; uint32_t fc = ((packed->Mid & 1) << 11) | ((packed->Bot >> 21)); bool valid = (evenparity32((packed->Mid & 0x1) ^ (packed->Bot & 0xB6DB6DB6)) == @@ -48,6 +71,8 @@ static int wiegand_C1k35s_parse(uint8_t bit_length, uint64_t bits, FuriString* d if(valid) { furi_string_cat_printf(description, "C1k35s\nFC: %ld CN: %ld\n", fc, cn); return 1; + } else { + FURI_LOG_D(PLUGIN_APP_ID, "C1k35s invalid"); } return 0; @@ -89,6 +114,57 @@ static int wiegand_h10301_parse(uint8_t bit_length, uint64_t bits, FuriString* d furi_string_cat_printf(description, "H10301\nFC: %d CN: %d\n", fc, cn); return 1; + } else { + FURI_LOG_D(PLUGIN_APP_ID, "H10301 invalid"); + } + + return 0; +} + +static int wiegand_H10304_parse(uint8_t bit_length, uint64_t bits, FuriString* description) { + wiegand_message_t value; + value.Length = bit_length; + value.Mid = bits >> 32; + value.Bot = bits; + wiegand_message_t* packed = &value; + + if(packed->Length != 37) return false; // Wrong length? Stop here. + + uint32_t fc = get_linear_field(packed, 1, 16); + uint32_t cn = get_linear_field(packed, 17, 19); + bool valid = + (get_bit_by_position(packed, 0) == evenparity32(get_linear_field(packed, 1, 18))) && + (get_bit_by_position(packed, 36) == oddparity32(get_linear_field(packed, 18, 18))); + + if(valid) { + furi_string_cat_printf(description, "H10304\nFC: %ld CN: %ld\n", fc, cn); + return 1; + } else { + FURI_LOG_D(PLUGIN_APP_ID, "H10304 invalid"); + } + + return 0; +} + +static int wiegand_H10302_parse(uint8_t bit_length, uint64_t bits, FuriString* description) { + wiegand_message_t value; + value.Length = bit_length; + value.Mid = bits >> 32; + value.Bot = bits; + wiegand_message_t* packed = &value; + + if(packed->Length != 37) return false; // Wrong length? Stop here. + + uint64_t cn = get_linear_field(packed, 1, 35); + bool valid = + (get_bit_by_position(packed, 0) == evenparity32(get_linear_field(packed, 1, 18))) && + (get_bit_by_position(packed, 36) == oddparity32(get_linear_field(packed, 18, 18))); + + if(valid) { + furi_string_cat_printf(description, "H10302\nCN: %lld\n", cn); + return 1; + } else { + FURI_LOG_D(PLUGIN_APP_ID, "H10302 invalid"); } return 0; @@ -100,12 +176,17 @@ static int wiegand_format_count(uint8_t bit_length, uint64_t bits) { int count = 0; FuriString* ignore = furi_string_alloc(); + // NOTE: Always update the `total` and add to the wiegand_format_description function + // TODO: Make this into a function pointer array count += wiegand_h10301_parse(bit_length, bits, ignore); count += wiegand_C1k35s_parse(bit_length, bits, ignore); + count += wiegand_H10302_parse(bit_length, bits, ignore); + count += wiegand_H10304_parse(bit_length, bits, ignore); + int total = 4; furi_string_free(ignore); - FURI_LOG_I(PLUGIN_APP_ID, "count: %i", count); + FURI_LOG_I(PLUGIN_APP_ID, "count: %i/%i", count, total); return count; } @@ -115,21 +196,16 @@ static void wiegand_format_description( size_t index, FuriString* description) { FURI_LOG_I(PLUGIN_APP_ID, "description %d", index); - UNUSED(bit_length); - UNUSED(bits); - - size_t i = 0; - i += wiegand_h10301_parse(bit_length, bits, description); - if(i - 1 == index) { - return; - } - i += wiegand_C1k35s_parse(bit_length, bits, description); - if(i - 1 == index) { + // Turns out I did this wrong and trying to use the index means the results get repeated. Instead, just return the results for index == 0 + if(index != 0) { return; } - furi_string_cat_printf(description, "[%i] FC: CN:", index); + wiegand_h10301_parse(bit_length, bits, description); + wiegand_C1k35s_parse(bit_length, bits, description); + wiegand_H10302_parse(bit_length, bits, description); + wiegand_H10304_parse(bit_length, bits, description); } /* Actual implementation of app<>plugin interface */ diff --git a/picopass/protocol/picopass_poller.c b/picopass/protocol/picopass_poller.c index eafb26ed245..0e599c65838 100644 --- a/picopass/protocol/picopass_poller.c +++ b/picopass/protocol/picopass_poller.c @@ -4,6 +4,7 @@ #include "../loclass/optimized_cipher.h" #include +#include #define TAG "Picopass" @@ -88,6 +89,15 @@ NfcCommand picopass_poller_pre_auth_handler(PicopassPoller* instance) { NfcCommand command = NfcCommandContinue; PicopassError error = PicopassErrorNone; + // Print version information for app and firmware for later review in log + const Version* version = version_get(); + FURI_LOG_I( + TAG, + "Firmware origin: %s firmware version: %s app version: %s", + version_get_firmware_origin(version), + version_get_version(version), + FAP_VERSION); + do { memcpy( instance->data->card_data[PICOPASS_CSN_BLOCK_INDEX].data, diff --git a/picopass/scenes/picopass_scene_config.h b/picopass/scenes/picopass_scene_config.h index 6a529d8aa37..d8a54a74281 100644 --- a/picopass/scenes/picopass_scene_config.h +++ b/picopass/scenes/picopass_scene_config.h @@ -23,3 +23,4 @@ ADD_SCENE(picopass, nr_mac_saved, NrMacSaved) ADD_SCENE(picopass, more_info, MoreInfo) ADD_SCENE(picopass, formats, Formats) ADD_SCENE(picopass, acknowledgements, Acknowledgements) +ADD_SCENE(picopass, elite_keygen_attack, EliteKeygenAttack) diff --git a/picopass/scenes/picopass_scene_elite_keygen_attack.c b/picopass/scenes/picopass_scene_elite_keygen_attack.c new file mode 100644 index 00000000000..fd5e5f6ea72 --- /dev/null +++ b/picopass/scenes/picopass_scene_elite_keygen_attack.c @@ -0,0 +1,145 @@ +#include "../picopass_i.h" +#include +#include "../picopass_elite_keygen.h" + +#define PICOPASS_SCENE_DICT_ATTACK_KEYS_BATCH_UPDATE (10) +#define PICOPASS_SCENE_ELITE_KEYGEN_ATTACK_LIMIT (2000) + +NfcCommand picopass_elite_keygen_attack_worker_callback(PicopassPollerEvent event, void* context) { + furi_assert(context); + NfcCommand command = NfcCommandContinue; + + Picopass* picopass = context; + + if(event.type == PicopassPollerEventTypeRequestMode) { + event.data->req_mode.mode = PicopassPollerModeRead; + } else if(event.type == PicopassPollerEventTypeRequestKey) { + uint8_t key[PICOPASS_KEY_LEN] = {}; + bool is_key_provided = false; + if(picopass->dict_attack_ctx.current_key < PICOPASS_SCENE_ELITE_KEYGEN_ATTACK_LIMIT) { + picopass_elite_nextKey(key); + is_key_provided = true; + } + + memcpy(event.data->req_key.key, key, PICOPASS_KEY_LEN); + event.data->req_key.is_elite_key = true; + event.data->req_key.is_key_provided = is_key_provided; + if(is_key_provided) { + picopass->dict_attack_ctx.current_key++; + if(picopass->dict_attack_ctx.current_key % + PICOPASS_SCENE_DICT_ATTACK_KEYS_BATCH_UPDATE == + 0) { + view_dispatcher_send_custom_event( + picopass->view_dispatcher, PicopassCustomEventDictAttackUpdateView); + } + } + } else if( + event.type == PicopassPollerEventTypeSuccess || + event.type == PicopassPollerEventTypeFail || + event.type == PicopassPollerEventTypeAuthFail) { + const PicopassDeviceData* data = picopass_poller_get_data(picopass->poller); + memcpy(&picopass->dev->dev_data, data, sizeof(PicopassDeviceData)); + view_dispatcher_send_custom_event( + picopass->view_dispatcher, PicopassCustomEventPollerSuccess); + } else if(event.type == PicopassPollerEventTypeCardLost) { + picopass->dict_attack_ctx.card_detected = false; + view_dispatcher_send_custom_event( + picopass->view_dispatcher, PicopassCustomEventDictAttackUpdateView); + } else if(event.type == PicopassPollerEventTypeCardDetected) { + picopass->dict_attack_ctx.card_detected = true; + view_dispatcher_send_custom_event( + picopass->view_dispatcher, PicopassCustomEventDictAttackUpdateView); + } + + return command; +} + +static void picopass_scene_elite_keygen_attack_update_view(Picopass* instance) { + if(instance->dict_attack_ctx.card_detected) { + dict_attack_set_card_detected(instance->dict_attack); + dict_attack_set_header(instance->dict_attack, instance->dict_attack_ctx.name); + dict_attack_set_total_dict_keys( + instance->dict_attack, PICOPASS_SCENE_ELITE_KEYGEN_ATTACK_LIMIT); + dict_attack_set_current_dict_key( + instance->dict_attack, instance->dict_attack_ctx.current_key); + } else { + dict_attack_set_card_removed(instance->dict_attack); + } +} + +static void picopass_scene_elite_keygen_attack_callback(void* context) { + Picopass* instance = context; + + view_dispatcher_send_custom_event( + instance->view_dispatcher, PicopassCustomEventDictAttackSkip); +} + +void picopass_scene_elite_keygen_attack_on_enter(void* context) { + Picopass* picopass = context; + dolphin_deed(DolphinDeedNfcRead); + + // Setup dict attack context + uint32_t state = PicopassSceneEliteKeygenAttack; + + picopass->dict = keys_dict_alloc( + PICOPASS_ICLASS_STANDARD_DICT_FLIPPER_NAME, KeysDictModeOpenExisting, PICOPASS_KEY_LEN); + + dict_attack_reset(picopass->dict_attack); + picopass->dict_attack_ctx.card_detected = false; + picopass->dict_attack_ctx.total_keys = PICOPASS_SCENE_ELITE_KEYGEN_ATTACK_LIMIT; + picopass->dict_attack_ctx.current_key = 0; + picopass->dict_attack_ctx.name = "Elite Keygen Attack"; + scene_manager_set_scene_state(picopass->scene_manager, PicopassSceneEliteKeygenAttack, state); + + // Setup view + picopass_scene_elite_keygen_attack_update_view(picopass); + dict_attack_set_callback( + picopass->dict_attack, picopass_scene_elite_keygen_attack_callback, picopass); + + // Start worker + picopass->poller = picopass_poller_alloc(picopass->nfc); + picopass_poller_start( + picopass->poller, picopass_elite_keygen_attack_worker_callback, picopass); + + view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewDictAttack); + picopass_blink_start(picopass); +} + +bool picopass_scene_elite_keygen_attack_on_event(void* context, SceneManagerEvent event) { + Picopass* picopass = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == PicopassCustomEventPollerSuccess) { + scene_manager_next_scene(picopass->scene_manager, PicopassSceneReadCardSuccess); + consumed = true; + } else if(event.event == PicopassCustomEventDictAttackUpdateView) { + picopass_scene_elite_keygen_attack_update_view(picopass); + consumed = true; + } else if(event.event == PicopassCustomEventDictAttackSkip) { + scene_manager_next_scene(picopass->scene_manager, PicopassSceneReadCardSuccess); + consumed = true; + } + } + return consumed; +} + +void picopass_scene_elite_keygen_attack_on_exit(void* context) { + Picopass* picopass = context; + + if(picopass->dict) { + keys_dict_free(picopass->dict); + picopass->dict = NULL; + } + picopass->dict_attack_ctx.current_key = 0; + picopass->dict_attack_ctx.total_keys = 0; + picopass_elite_reset(); + + picopass_poller_stop(picopass->poller); + picopass_poller_free(picopass->poller); + + // Clear view + popup_reset(picopass->popup); + + picopass_blink_stop(picopass); +} diff --git a/picopass/scenes/picopass_scene_start.c b/picopass/scenes/picopass_scene_start.c index 3fed865f2c3..316576bed50 100644 --- a/picopass/scenes/picopass_scene_start.c +++ b/picopass/scenes/picopass_scene_start.c @@ -4,6 +4,7 @@ enum SubmenuIndex { SubmenuIndexSaved, SubmenuIndexLoclass, SubmenuIndexAcknowledgements, + SubmenuIndexKeygenAttack, }; void picopass_scene_start_submenu_callback(void* context, uint32_t index) { @@ -26,6 +27,12 @@ void picopass_scene_start_on_enter(void* context) { SubmenuIndexAcknowledgements, picopass_scene_start_submenu_callback, picopass); + submenu_add_item( + submenu, + "Elite Keygen Attack", + SubmenuIndexKeygenAttack, + picopass_scene_start_submenu_callback, + picopass); submenu_set_selected_item( submenu, scene_manager_get_scene_state(picopass->scene_manager, PicopassSceneStart)); @@ -60,6 +67,11 @@ bool picopass_scene_start_on_event(void* context, SceneManagerEvent event) { picopass->scene_manager, PicopassSceneStart, PicopassSceneAcknowledgements); scene_manager_next_scene(picopass->scene_manager, PicopassSceneAcknowledgements); consumed = true; + } else if(event.event == SubmenuIndexKeygenAttack) { + scene_manager_set_scene_state( + picopass->scene_manager, PicopassSceneStart, SubmenuIndexKeygenAttack); + scene_manager_next_scene(picopass->scene_manager, PicopassSceneEliteKeygenAttack); + consumed = true; } } diff --git a/pokemon_trading/.github/FUNDING.yml b/pokemon_trading/.github/FUNDING.yml index b71e52ea724..6ffcf7b7ca8 100644 --- a/pokemon_trading/.github/FUNDING.yml +++ b/pokemon_trading/.github/FUNDING.yml @@ -1,6 +1,6 @@ # These are supported funding model platforms -github: EstebanFuentealba # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +github: kbembedded # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] patreon: # open_collective: # Replace with a single Open Collective username ko_fi: # Replace with a single Ko-fi username diff --git a/pomodoro/application.fam b/pomodoro/application.fam index e1fc9dd317f..2b04dec5663 100644 --- a/pomodoro/application.fam +++ b/pomodoro/application.fam @@ -10,6 +10,6 @@ App( fap_icon="flipp_pomodoro_10.png", fap_author="@Th3Un1q3", fap_weburl="https://github.com/Th3Un1q3/flipp_pomodoro", - fap_version="1.3", + fap_version="1.4", fap_description="Boost Your Productivity with the Pomodoro Timer", ) diff --git a/pong/application.fam b/pong/application.fam index cf1604e770f..765b8c39f06 100644 --- a/pong/application.fam +++ b/pong/application.fam @@ -12,6 +12,6 @@ App( fap_category="Games", fap_author="@nmrr & @SimplyMinimal", fap_weburl="https://github.com/nmrr/flipperzero-pong", - fap_version="1.2", + fap_version="1.3", fap_description="Simple pong game", ) diff --git a/protoview/application.fam b/protoview/application.fam index 344db9cfd29..6fc5aa530f5 100644 --- a/protoview/application.fam +++ b/protoview/application.fam @@ -9,6 +9,6 @@ App( fap_icon="appicon.png", fap_category="Sub-GHz", fap_author="@antirez & (fixes by @xMasterX)", - fap_version="1.1", + fap_version="1.2", fap_description="Digital signal detection, visualization, editing and reply tool", ) diff --git a/qrcode/.github/workflows/release.yml b/qrcode/.github/workflows/release.yml index 1e30a2a43f3..bc510e382cc 100644 --- a/qrcode/.github/workflows/release.yml +++ b/qrcode/.github/workflows/release.yml @@ -6,7 +6,7 @@ on: - 'v[0-9]+.[0-9]+.[0-9]+' env: - firmware_version: '0.101.2' + firmware_version: '0.103.1' jobs: build: diff --git a/qrcode/application.fam b/qrcode/application.fam index 964cdc824f8..4cacbd3f664 100644 --- a/qrcode/application.fam +++ b/qrcode/application.fam @@ -1,7 +1,7 @@ App( appid="qrcode", name="QR Code", - fap_version=(2, 0), + fap_version=(2, 1), fap_description="Display qrcodes", fap_author="Bob Matcuk", fap_weburl="https://github.com/bmatcuk/flipperzero-qrcode", diff --git a/qrcode/qrcode_app.c b/qrcode/qrcode_app.c index 6904a0b315b..75d6271b91d 100644 --- a/qrcode/qrcode_app.c +++ b/qrcode/qrcode_app.c @@ -59,7 +59,7 @@ typedef struct { Gui* gui; ViewPort* view_port; - FuriMutex** mutex; + FuriMutex* mutex; FuriString* message; QRCode* qrcode; uint8_t min_mode; diff --git a/quac/CHANGELOG.md b/quac/CHANGELOG.md index 61fe6b11969..bff43aea8ce 100644 --- a/quac/CHANGELOG.md +++ b/quac/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.6.1 + +- Several crash fixes when Importing files and Creating groups + ## 0.6 - Basic NFC support diff --git a/quac/application.fam b/quac/application.fam index 36b06745237..0cd3d852e2b 100644 --- a/quac/application.fam +++ b/quac/application.fam @@ -8,7 +8,7 @@ App( stack_size=2 * 1024, fap_category="Tools", # Optional values - fap_version="0.6", + fap_version="0.6.1", fap_icon="images/quac.png", # 10x10 1-bit PNG fap_description="Quick Action remote control app", fap_author="Roberto De Feo", diff --git a/rc2014_coleco/coleco.c b/rc2014_coleco/coleco.c index 6b62da1b872..fdb4e9d6f24 100644 --- a/rc2014_coleco/coleco.c +++ b/rc2014_coleco/coleco.c @@ -132,8 +132,8 @@ static void render_callback(Canvas* const canvas, void* context) { } static void input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); PluginEvent event = {.type = EventTypeKey, .input = *input_event}; furi_message_queue_put(event_queue, &event, FuriWaitForever); diff --git a/reversi/application.fam b/reversi/application.fam index 75af5c99a90..e38431f85fb 100644 --- a/reversi/application.fam +++ b/reversi/application.fam @@ -13,7 +13,7 @@ App( fap_category="Games", fap_icon_assets_symbol="game_reversi", fap_author="@dimat", - fap_weburl="https://github.com/zyuhel/flipperzero-racegame", + fap_weburl="https://github.com/dimat/flipperzero-reversi", fap_version="1.3", fap_description="Reversi game, the game controls should be intuitive. Longs press on OK opens the menu to start a new game.", ) diff --git a/reversi/game_reversi.png b/reversi/game_reversi.png index 3a321471b96..75def62b925 100644 Binary files a/reversi/game_reversi.png and b/reversi/game_reversi.png differ diff --git a/rootoflife/application.fam b/rootoflife/application.fam index 105abdf583c..1443cb17075 100644 --- a/rootoflife/application.fam +++ b/rootoflife/application.fam @@ -13,6 +13,6 @@ App( fap_icon_assets_symbol="roots_of_life_game", fap_author="@Xorboo", fap_weburl="https://github.com/Xorboo/root-of-life", - fap_version="1.1", + fap_version="1.2", fap_description="A zen-puzzle game for FlipperZero, puzzle made on GlobalGameJam23 (theme: Roots)", ) diff --git a/rootoflife/roots_of_life_game.c b/rootoflife/roots_of_life_game.c index 28d0c6f8b4c..caa77be9f51 100644 --- a/rootoflife/roots_of_life_game.c +++ b/rootoflife/roots_of_life_game.c @@ -605,16 +605,16 @@ static void roots_draw_callback(Canvas* const canvas, void* ctx) { } static void roots_input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); GameEvent event = {.type = EventTypeKey, .input = *input_event}; furi_message_queue_put(event_queue, &event, FuriWaitForever); } static void roots_update_timer_callback(void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); GameEvent event = {.type = EventTypeTick}; furi_message_queue_put(event_queue, &event, 0); diff --git a/rubiks_cube_scrambler/application.fam b/rubiks_cube_scrambler/application.fam index 871c90a8020..2ee6a800dd8 100644 --- a/rubiks_cube_scrambler/application.fam +++ b/rubiks_cube_scrambler/application.fam @@ -19,6 +19,6 @@ App( fap_icon="cube.png", fap_author="@RaZeSloth", fap_weburl="https://github.com/RaZeSloth/flipperzero-rubiks-cube-scrambler", - fap_version="1.2", + fap_version="1.3", fap_description="App generates random moves to scramble a Rubik's cube.", ) diff --git a/scorched_tanks/application.fam b/scorched_tanks/application.fam index da2b8a61bd3..2a74599de4f 100644 --- a/scorched_tanks/application.fam +++ b/scorched_tanks/application.fam @@ -11,6 +11,6 @@ App( fap_category="Games", fap_author="@jasniec", fap_weburl="https://github.com/jasniec/flipper-scorched-tanks-game", - fap_version="1.2", + fap_version="1.3", fap_description="A Flipper Zero game inspired by scorched earth", ) diff --git a/scorched_tanks/scorched_tanks_game_app.c b/scorched_tanks/scorched_tanks_game_app.c index beebef9397b..cb3250cb9d0 100644 --- a/scorched_tanks/scorched_tanks_game_app.c +++ b/scorched_tanks/scorched_tanks_game_app.c @@ -351,16 +351,16 @@ static void scorched_tanks_render_callback(Canvas* const canvas, void* ctx) { } static void scorched_tanks_input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); ScorchedTanksEvent event = {.type = EventTypeKey, .input = *input_event}; furi_message_queue_put(event_queue, &event, FuriWaitForever); } static void scorched_tanks_update_timer_callback(void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); ScorchedTanksEvent event = {.type = EventTypeTick}; furi_message_queue_put(event_queue, &event, 0); diff --git a/seader/application.fam b/seader/application.fam index cc74fd5ccfc..09d04141cfd 100644 --- a/seader/application.fam +++ b/seader/application.fam @@ -20,7 +20,7 @@ App( ], fap_icon="icons/logo.png", fap_category="NFC", - fap_version="2.8", + fap_version="2.9", fap_author="bettse", # fap_extbuild=( # ExtFile( diff --git a/seader/ccid.c b/seader/ccid.c index 5d12895d255..c2595ce4078 100644 --- a/seader/ccid.c +++ b/seader/ccid.c @@ -141,7 +141,7 @@ size_t seader_ccid_process(Seader* seader, uint8_t* cmd, size_t cmd_len) { for(uint8_t i = 0; i < cmd_len; i++) { snprintf(display + (i * 2), sizeof(display), "%02x", cmd[i]); } - // FURI_LOG_D(TAG, "UART %d: %s", cmd_len, display); + FURI_LOG_D(TAG, "UART %d: %s", cmd_len, display); if(cmd_len == 2) { if(cmd[0] == CCID_MESSAGE_TYPE_RDR_to_PC_NotifySlotChange) { @@ -164,6 +164,10 @@ size_t seader_ccid_process(Seader* seader, uint8_t* cmd, size_t cmd_len) { powered[0] = false; hasSAM = false; retries = 3; + if(seader_worker->callback) { + seader_worker->callback( + SeaderWorkerEventSamMissing, seader_worker->context); + } } break; }; @@ -187,6 +191,10 @@ size_t seader_ccid_process(Seader* seader, uint8_t* cmd, size_t cmd_len) { powered[1] = false; hasSAM = false; retries = 3; + if(seader_worker->callback) { + seader_worker->callback( + SeaderWorkerEventSamMissing, seader_worker->context); + } } break; }; @@ -276,6 +284,7 @@ size_t seader_ccid_process(Seader* seader, uint8_t* cmd, size_t cmd_len) { //0306 80 00000000 0001 42fe 00 38 if(message.bStatus == 0x41 && message.bError == 0xfe) { FURI_LOG_W(TAG, "card probably upside down"); + hasSAM = false; if(seader_worker->callback) { seader_worker->callback(SeaderWorkerEventSamMissing, seader_worker->context); } diff --git a/seader/sam_api.c b/seader/sam_api.c index 56da5aa562e..25a42f0f88b 100644 --- a/seader/sam_api.c +++ b/seader/sam_api.c @@ -1,6 +1,7 @@ #include "sam_api.h" #include +#include #include #define TAG "SAMAPI" @@ -1103,6 +1104,14 @@ NfcCommand seader_worker_card_detect( } seader_send_card_detected(seader, cardDetails); + // Print version information for app and firmware for later review in log + const Version* version = version_get(); + FURI_LOG_I( + TAG, + "Firmware origin: %s firmware version: %s app version: %s", + version_get_firmware_origin(version), + version_get_version(version), + FAP_VERSION); free(cardDetails); return NfcCommandContinue; diff --git a/seader/scenes/seader_scene_sam_present.c b/seader/scenes/seader_scene_sam_present.c index f65fc07b0bf..728bb889a87 100644 --- a/seader/scenes/seader_scene_sam_present.c +++ b/seader/scenes/seader_scene_sam_present.c @@ -97,6 +97,9 @@ bool seader_scene_sam_present_on_event(void* context, SceneManagerEvent event) { consumed = true; } else if(event.event == SubmenuIndexFwVersion) { consumed = true; + } else if(event.event == SeaderWorkerEventSamMissing) { + scene_manager_next_scene(seader->scene_manager, SeaderSceneSamMissing); + consumed = true; } } else if(event.type == SceneManagerEventTypeBack) { scene_manager_stop(seader->scene_manager); diff --git a/sentry_safe/application.fam b/sentry_safe/application.fam index cb476439b6f..2fa3961bbd3 100644 --- a/sentry_safe/application.fam +++ b/sentry_safe/application.fam @@ -9,6 +9,6 @@ App( fap_icon="safe_10px.png", fap_category="GPIO", fap_author="@H4ckd4ddy & @xMasterX (ported to latest firmware)", - fap_version="1.2", + fap_version="1.3", fap_description="App exploiting vulnerability to open any Sentry Safe and Master Lock electronic safe without any pin code via UART pins.", ) diff --git a/sentry_safe/sentry_safe.c b/sentry_safe/sentry_safe.c index bb93e98d539..afbceb27139 100644 --- a/sentry_safe/sentry_safe.c +++ b/sentry_safe/sentry_safe.c @@ -46,8 +46,8 @@ static void sentry_safe_render_callback(Canvas* const canvas, void* ctx) { } static void sentry_safe_input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); Event event = {.type = EventTypeKey, .input = *input_event}; furi_message_queue_put(event_queue, &event, FuriWaitForever); diff --git a/slots/application.fam b/slots/application.fam index 2ab7af0cbf4..5c5c284e698 100644 --- a/slots/application.fam +++ b/slots/application.fam @@ -12,6 +12,6 @@ App( fap_icon_assets="assets", fap_author="@Daniel-dev-s", fap_weburl="https://github.com/Daniel-dev-s/flipperzero-slots", - fap_version="1.2", + fap_version="1.3", fap_description="Simple Slots simulator game", ) diff --git a/slots/slotmachine.c b/slots/slotmachine.c index fd89fd22784..6a376e8a361 100644 --- a/slots/slotmachine.c +++ b/slots/slotmachine.c @@ -24,7 +24,7 @@ typedef struct { Gui* gui; // container gui ViewPort* view_port; // current viewport FuriMessageQueue* input_queue; // Input Events queue - FuriMutex** model_mutex; // mutex for safe threads + FuriMutex* model_mutex; // mutex for safe threads uint16_t bet; double money, winamount; SlotColumn* columns[4]; diff --git a/snake_2/application.fam b/snake_2/application.fam index bd5a7c39233..d177f1def6f 100644 --- a/snake_2/application.fam +++ b/snake_2/application.fam @@ -11,6 +11,6 @@ App( fap_category="Games", fap_author="@Willzvul", fap_weburl="https://github.com/Willzvul/Snake_2.0", - fap_version="2.1", + fap_version="2.2", fap_description="Advanced Snake Game (Remake of original Snake)", ) diff --git a/snake_2/snake_20.c b/snake_2/snake_20.c index 827b936c1ae..4401e6ae7be 100644 --- a/snake_2/snake_20.c +++ b/snake_2/snake_20.c @@ -192,16 +192,16 @@ static void snake_game_render_callback(Canvas* const canvas, void* ctx) { } static void snake_game_input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); SnakeEvent event = {.type = EventTypeKey, .input = *input_event}; furi_message_queue_put(event_queue, &event, FuriWaitForever); } static void snake_game_update_timer_callback(void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); SnakeEvent event = {.type = EventTypeTick}; furi_message_queue_put(event_queue, &event, 0); diff --git a/solitaire/solitaire.c b/solitaire/solitaire.c index 660de8118b3..34c83decc2a 100644 --- a/solitaire/solitaire.c +++ b/solitaire/solitaire.c @@ -456,15 +456,17 @@ void init_start(GameState* game_state) { } static void input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); + AppEvent event = {.type = EventTypeKey, .input = *input_event}; furi_message_queue_put(event_queue, &event, FuriWaitForever); } static void update_timer_callback(void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); + AppEvent event = {.type = EventTypeTick}; furi_message_queue_put(event_queue, &event, 0); } diff --git a/spectrum_analyzer/application.fam b/spectrum_analyzer/application.fam index 314b0e61ddd..6c7d4638c6e 100644 --- a/spectrum_analyzer/application.fam +++ b/spectrum_analyzer/application.fam @@ -9,6 +9,6 @@ App( fap_icon="spectrum_10px.png", fap_category="Sub-GHz", fap_author="@xMasterX & @theY4Kman & @ALEEF02 (original by @jolcese)", - fap_version="1.2", + fap_version="1.3", fap_description="Displays a spectrogram chart to visually represent RF signals around you.", ) diff --git a/swd_probe/application.fam b/swd_probe/application.fam index 9a41c0702fd..eb6628fc57e 100644 --- a/swd_probe/application.fam +++ b/swd_probe/application.fam @@ -11,6 +11,6 @@ App( fap_category="GPIO/Debug", fap_icon_assets="icons", fap_author="@g3gg0 & (fixes by @xMasterX)", - fap_version="1.1", + fap_version="1.2", fap_description="ARM SWD (Single Wire Debug) Probe", ) diff --git a/swd_probe/icons/app.png b/swd_probe/icons/app.png index 6949ce78d11..5f6d42d110a 100644 Binary files a/swd_probe/icons/app.png and b/swd_probe/icons/app.png differ diff --git a/t_rex_runner/application.fam b/t_rex_runner/application.fam index b59d2b870f5..080d6337c37 100644 --- a/t_rex_runner/application.fam +++ b/t_rex_runner/application.fam @@ -12,6 +12,6 @@ App( order=36, fap_author="@Rrycbarm", fap_weburl="https://github.com/Rrycbarm/t-rex-runner", - fap_version="1.3", + fap_version="1.4", fap_description="Play the port of the Chrome browser T-Rex game on your Flipper Zero.", ) diff --git a/t_rex_runner/trexrunner.c b/t_rex_runner/trexrunner.c index 831d93a33a4..6ef1c86d4b0 100644 --- a/t_rex_runner/trexrunner.c +++ b/t_rex_runner/trexrunner.c @@ -137,8 +137,8 @@ static void timer_callback(void* ctx) { } static void input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); PluginEvent event = {.type = EventTypeKey, .input = *input_event}; furi_message_queue_put(event_queue, &event, FuriWaitForever); diff --git a/tama_p1/tama_p1.c b/tama_p1/tama_p1.c index c23bfa17b13..08a31453e5e 100644 --- a/tama_p1/tama_p1.c +++ b/tama_p1/tama_p1.c @@ -459,16 +459,16 @@ static void tama_p1_draw_callback(Canvas* const canvas, void* cb_ctx) { } static void tama_p1_input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); TamaEvent event = {.type = EventTypeInput, .input = *input_event}; furi_message_queue_put(event_queue, &event, FuriWaitForever); } static void tama_p1_update_timer_callback(void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); TamaEvent event = {.type = EventTypeTick}; furi_message_queue_put(event_queue, &event, 0); diff --git a/tanks/tanks_game.c b/tanks/tanks_game.c index d3ddafa76e7..392886d27e0 100644 --- a/tanks/tanks_game.c +++ b/tanks/tanks_game.c @@ -620,16 +620,16 @@ static void tanks_game_render_callback(Canvas* const canvas, void* ctx) { } static void tanks_game_input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); TanksEvent event = {.type = EventTypeKey, .input = *input_event}; furi_message_queue_put(event_queue, &event, FuriWaitForever); } static void tanks_game_update_timer_callback(void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); TanksEvent event = {.type = EventTypeTick}; furi_message_queue_put(event_queue, &event, 0); diff --git a/tetris/application.fam b/tetris/application.fam index f52dbc48a02..71c66feaca1 100644 --- a/tetris/application.fam +++ b/tetris/application.fam @@ -9,7 +9,7 @@ App( fap_icon="tetris_10px.png", fap_category="Games", fap_author="@xMasterX & @jeffplang & @noiob", - fap_version="1.3", + fap_version="1.4", fap_description="Tetris Game", fap_icon_assets="assets", ) diff --git a/tetris/tetris_game.c b/tetris/tetris_game.c index 105a24c822a..3fb6e01756d 100644 --- a/tetris/tetris_game.c +++ b/tetris/tetris_game.c @@ -232,8 +232,8 @@ static void tetris_game_render_callback(Canvas* const canvas, void* ctx) { } static void tetris_game_input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); TetrisEvent event = {.type = EventTypeKey, .input = *input_event}; furi_message_queue_put(event_queue, &event, FuriWaitForever); @@ -386,8 +386,8 @@ static bool tetris_game_piece_at_bottom(TetrisState* tetris_state, Piece* newPie } static void tetris_game_update_timer_callback(void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); TetrisEvent event = {.type = EventTypeTick}; furi_message_queue_put(event_queue, &event, FuriWaitForever); diff --git a/text2sam/application.fam b/text2sam/application.fam index 9842fac9206..be38d7d80ba 100644 --- a/text2sam/application.fam +++ b/text2sam/application.fam @@ -16,6 +16,6 @@ App( order=20, fap_author="@Round-Pi & (Fixes by @Willy-JL)", fap_weburl="https://github.com/Round-Pi/flipperzero-text2sam", - fap_version="1.3", + fap_version="1.4", fap_description="Convert text to speech on your Flipper Zero with SAM (Software Automatic Mouth).", ) diff --git a/text_viewer/application.fam b/text_viewer/application.fam index c186f4a3dec..69c45b9d783 100644 --- a/text_viewer/application.fam +++ b/text_viewer/application.fam @@ -13,6 +13,6 @@ App( fap_category="Tools", fap_icon_assets="icons", fap_author="@Willy-JL", # Original by @kowalski7cc & @kyhwana, new has code borrowed from archive > show - fap_version="1.5", + fap_version="1.6", fap_description="Text viewer application", ) diff --git a/tictactoe/application.fam b/tictactoe/application.fam index 8a2bfd4117e..88e77b98017 100644 --- a/tictactoe/application.fam +++ b/tictactoe/application.fam @@ -9,6 +9,6 @@ App( fap_icon="tictactoe_10px.png", fap_category="Games", fap_author="@xMasterX & @gotnull", - fap_version="1.1", + fap_version="1.2", fap_description="Tic Tac Toe game, for 2 players, play on one device", ) diff --git a/tictactoe/tictactoe_game.c b/tictactoe/tictactoe_game.c index 02dcfbdbbe8..db1be8f445e 100644 --- a/tictactoe/tictactoe_game.c +++ b/tictactoe/tictactoe_game.c @@ -289,16 +289,16 @@ static void tictactoe_draw_callback(Canvas* const canvas, void* ctx) { } static void tictactoe_input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); GameEvent event = {.type = EventTypeKey, .input = *input_event}; furi_message_queue_put(event_queue, &event, FuriWaitForever); } static void tictactoe_update_timer_callback(void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); GameEvent event = {.type = EventTypeTick}; furi_message_queue_put(event_queue, &event, 0); diff --git a/timelapse/application.fam b/timelapse/application.fam index 07b59f81526..88404b36678 100644 --- a/timelapse/application.fam +++ b/timelapse/application.fam @@ -7,7 +7,7 @@ App( requires=["gui", "input", "notification", "gpio"], stack_size=2 * 1024, order=90, - fap_version="1.1", + fap_version="1.2", fap_icon_assets="icons", fap_icon_assets_symbol="zeitraffer", fap_icon="zeitraffer.png", diff --git a/timelapse/zeitraffer.c b/timelapse/zeitraffer.c index 450b9aa94f6..8111ca6e408 100644 --- a/timelapse/zeitraffer.c +++ b/timelapse/zeitraffer.c @@ -7,8 +7,6 @@ #include "gpio_item.h" #include "zeitraffer_icons.h" -#include - #define CONFIG_FILE_PATH APP_DATA_PATH("timelapse.conf") // Часть кода покрадена из https://github.com/zmactep/flipperzero-hello-world diff --git a/timelapse/zeitraffer.png b/timelapse/zeitraffer.png index af9cf745991..0bf532872e0 100644 Binary files a/timelapse/zeitraffer.png and b/timelapse/zeitraffer.png differ diff --git a/tuning_fork/application.fam b/tuning_fork/application.fam index 1364bb6e8a8..d308b02ac82 100644 --- a/tuning_fork/application.fam +++ b/tuning_fork/application.fam @@ -13,6 +13,6 @@ App( order=20, fap_author="@besya & (Fixes by @Willy-JL)", fap_weburl="https://github.com/besya/flipperzero-tuning-fork", - fap_version="1.1", + fap_version="1.2", fap_description="Tuning fork for tuning musical instruments", ) diff --git a/tuning_fork/tuning_fork.c b/tuning_fork/tuning_fork.c index 0ad59f62807..0538bcd1fbf 100644 --- a/tuning_fork/tuning_fork.c +++ b/tuning_fork/tuning_fork.c @@ -188,8 +188,8 @@ static void render_callback(Canvas* const canvas, void* ctx) { } static void input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); PluginEvent event = {.type = EventTypeKey, .input = *input_event}; furi_message_queue_put(event_queue, &event, FuriWaitForever); diff --git a/uart_terminal/application.fam b/uart_terminal/application.fam index 6cbec8a2a51..c1264769ff1 100644 --- a/uart_terminal/application.fam +++ b/uart_terminal/application.fam @@ -10,6 +10,6 @@ App( fap_category="GPIO", fap_icon_assets="assets", fap_author="@cool4uma & @rnadyrshin & (some fixes by @xMasterX)", - fap_version="1.4", + fap_version="1.5", fap_description="Control various devices via the Flipper Zero UART interface.", ) diff --git a/uhf_rfid/icons/DolphinNice_96x59.png b/uhf_rfid/icons/DolphinNice_96x59.png deleted file mode 100644 index a299d363023..00000000000 Binary files a/uhf_rfid/icons/DolphinNice_96x59.png and /dev/null differ diff --git a/unitemp/CHANGELOG.md b/unitemp/CHANGELOG.md index 1d7fa5cf23c..8b8b9178dc6 100644 --- a/unitemp/CHANGELOG.md +++ b/unitemp/CHANGELOG.md @@ -1,4 +1,6 @@ # Unitemp changelog +## Unitemp 1.5 +- Add Cry_dolph_55x52 image (build on latest API) (Thanks jamisonderek) ## Unitemp 1.4 - Remove version value from application manifest - Small fix (Thanks for JamesDavid) diff --git a/unitemp/application.fam b/unitemp/application.fam index f46d1c77b2e..de318e970bd 100644 --- a/unitemp/application.fam +++ b/unitemp/application.fam @@ -9,7 +9,7 @@ App( stack_size=2 * 1024, order=100, fap_description="Application for reading temperature, humidity and pressure sensors like a DHT11/22, DS18B20, BMP280, HTU21 and more", - fap_version="1.4", + fap_version="1.5", fap_author="@quen0n & (fixes by @xMasterX)", fap_weburl="https://github.com/quen0n/unitemp-flipperzero", fap_category="GPIO/Sensors", diff --git a/videopoker/application.fam b/videopoker/application.fam index 85ecf7ac224..9165844dd11 100644 --- a/videopoker/application.fam +++ b/videopoker/application.fam @@ -11,6 +11,6 @@ App( fap_category="Games", fap_author="@PixlEmly", fap_weburl="https://github.com/PixlEmly", - fap_version="1.1", + fap_version="1.2", fap_description="Video poker is a casino game based on five-card draw poker", ) diff --git a/videopoker/poker.c b/videopoker/poker.c index b31deae5936..470549e72aa 100644 --- a/videopoker/poker.c +++ b/videopoker/poker.c @@ -38,7 +38,7 @@ typedef struct { } PokerPlayer_card; typedef struct { - FuriMutex** model_mutex; + FuriMutex* model_mutex; FuriMessageQueue* event_queue; ViewPort* view_port; Gui* gui; diff --git a/wav_player/application.fam b/wav_player/application.fam index 99d52cf5cd6..3ea2af01671 100644 --- a/wav_player/application.fam +++ b/wav_player/application.fam @@ -10,6 +10,6 @@ App( fap_category="Media", fap_icon_assets="images", fap_author="@DrZlo13 & (ported, fixed by @xMasterX), (improved by @LTVA1)", - fap_version="1.1", + fap_version="1.2", fap_description="Audio player for WAV files, recommended to convert files to unsigned 8-bit PCM stereo, but it may work with others too", ) diff --git a/wifi_scanner/wifi_scanner.c b/wifi_scanner/wifi_scanner.c index 3fb139da62b..12e1c06d15a 100644 --- a/wifi_scanner/wifi_scanner.c +++ b/wifi_scanner/wifi_scanner.c @@ -637,8 +637,8 @@ static void wifi_module_render_callback(Canvas* const canvas, void* ctx) { } static void wifi_module_input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); SPluginEvent event = {.m_type = EventTypeKey, .m_input = *input_event}; furi_message_queue_put(event_queue, &event, FuriWaitForever); diff --git a/wiiec/wii_anal.c b/wiiec/wii_anal.c index 272f0d59bf6..a3d643a11f5 100644 --- a/wiiec/wii_anal.c +++ b/wiiec/wii_anal.c @@ -46,8 +46,8 @@ // static void cbTimer(void* ctx) { ENTER; + furi_assert(ctx); FuriMessageQueue* queue = ctx; - furi_assert(queue); eventMsg_t message = {.id = EVID_TICK}; furi_message_queue_put(queue, &message, 0); @@ -62,9 +62,9 @@ static void cbTimer(void* ctx) { // static void cbInput(InputEvent* event, void* ctx) { ENTER; - FuriMessageQueue* queue = ctx; - furi_assert(queue); + furi_assert(ctx); furi_assert(event); + FuriMessageQueue* queue = ctx; // Put an "input" event message on the message queue eventMsg_t message = {.id = EVID_KEY, .input = *event}; diff --git a/yatzee/application.fam b/yatzee/application.fam index 96f37254052..a3dd34f2e83 100644 --- a/yatzee/application.fam +++ b/yatzee/application.fam @@ -11,6 +11,6 @@ App( fap_icon_assets="images", fap_author="@emfleak", fap_weburl="https://github.com/emfleak/flipperzero-yatzee", - fap_version="1.1", + fap_version="1.2", fap_description="Yahtzee game", ) diff --git a/zombiez/application.fam b/zombiez/application.fam index 0dd50d86756..bb851c0b8b5 100644 --- a/zombiez/application.fam +++ b/zombiez/application.fam @@ -9,6 +9,6 @@ App( fap_icon="zombie_10px.png", fap_category="Games", fap_author="@DevMilanIan & @xMasterX, (original By @Dooskington)", - fap_version="1.1", + fap_version="1.2", fap_description="Defend your walls from the zombies", ) diff --git a/zombiez/zombie_10px.png b/zombiez/zombie_10px.png index 37363ec042b..3680085f123 100644 Binary files a/zombiez/zombie_10px.png and b/zombiez/zombie_10px.png differ diff --git a/zombiez/zombiez.c b/zombiez/zombiez.c index e4fb2b4b8e7..af8ad2266d7 100644 --- a/zombiez/zombiez.c +++ b/zombiez/zombiez.c @@ -185,8 +185,9 @@ static void render_callback(Canvas* const canvas, void* ctx) { } static void input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); FuriMessageQueue* event_queue = ctx; - furi_assert(event_queue); + PluginEvent event = {.type = EventTypeKey, .input = *input_event}; furi_message_queue_put(event_queue, &event, FuriWaitForever); }