From d838c5a0c4affe54673e49f2acece29c785dbff5 Mon Sep 17 00:00:00 2001 From: YunHorn Technology Date: Wed, 28 Aug 2024 11:00:08 +0800 Subject: [PATCH 1/4] ---- start of STS-P2 ---- vl53l1x --- STM32CubeIDE/.settings/org.eclipse.core.resources.prefs | 2 ++ readme.MD | 3 +++ 2 files changed, 5 insertions(+) create mode 100644 STM32CubeIDE/.settings/org.eclipse.core.resources.prefs create mode 100644 readme.MD diff --git a/STM32CubeIDE/.settings/org.eclipse.core.resources.prefs b/STM32CubeIDE/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..99f26c0 --- /dev/null +++ b/STM32CubeIDE/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/readme.MD b/readme.MD new file mode 100644 index 0000000..e6b7910 --- /dev/null +++ b/readme.MD @@ -0,0 +1,3 @@ +--- STS P2 --- + +VL53L1X -- 2.40.1 From 9e8255599cde2817d96581feaaffead9c56d618b Mon Sep 17 00:00:00 2001 From: YunHorn Technology Date: Wed, 28 Aug 2024 11:34:24 +0800 Subject: [PATCH 2/4] --- start of STS-P2 --- readme.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index 9a8dfb1..b5cca4d 100644 --- a/readme.txt +++ b/readme.txt @@ -45,7 +45,8 @@ STS_O7 For Occupancy sensors 2024-06-26 RTM for pixel-network STS_RSS_MODE = 3 P113 switch 2024-07-30 revert back ...not good for alarm so far 2024-08-06 start focus on fall detection -2024-08-06 a... +2024-08-06 fall detection for O7, Motion detection for O6 +2024-08-28 STS-P2 ***************************************************************************** */ -- 2.40.1 From f8cef94155646e86c9e1830ad095156be68281a2 Mon Sep 17 00:00:00 2001 From: YunHorn Technology Date: Wed, 28 Aug 2024 12:10:00 +0800 Subject: [PATCH 3/4] --- prepare drivers for vl53l1x --- .project | 11 - Core/Inc/i2c.h | 51 ++ Core/Src/i2c.c | 199 ++++ Core/Src/main_5_9.c | 224 ----- Core/Src/presen-detection-temp.c | 315 ------- Core/Src/sts_lamp_bar_MAY26.c | 624 ------------- Core/Src/yunhorn_sts_presence_sensor_JULY3.c | 555 ------------ STM32CubeIDE/.project | 5 + TOF/App/Example_1_basic_ranging.c | 223 +++++ .../Example_2_tune_sensor_with_debug_data.c | 217 +++++ TOF/App/Example_3_long_ranging.c | 185 ++++ TOF/App/Example_4_ultra_low_power.c | 180 ++++ TOF/App/app_tof.c | 188 ++++ TOF/App/app_tof.h | 41 + TOF/App/app_tof_peoplecount.c | 442 +++++++++ TOF/App/app_tof_peoplecount.h | 150 ++++ TOF/Target/53l1a2_conf.h | 61 ++ TOF/Target/app_tof_pin_conf.c | 30 + TOF/Target/app_tof_pin_conf.h | 38 + .../VL53L1X_BareDriver_with_UltraLowPower.bin | Bin 54184 -> 0 bytes .../Binary/VL53L1X_UltraLowPower_Example.bin | Bin 20396 -> 0 bytes vl53lx_uld/VL53L1X_ULP_api.c | 610 +++++++++++++ vl53lx_uld/VL53L1X_ULP_api.h | 419 +++++++++ vl53lx_uld/VL53L1X_ULP_platform.c | 149 +++ vl53lx_uld/VL53L1X_ULP_platform.h | 110 +++ vl53lx_uld/VL53L1X_api.c | 850 ++++++++++++++++++ vl53lx_uld/VL53L1X_api.h | 393 ++++++++ vl53lx_uld/VL53L1X_calibration.c | 136 +++ vl53lx_uld/VL53L1X_calibration.h | 93 ++ vl53lx_uld/X-NUCLEO-53L1A1.c | 608 +++++++++++++ vl53lx_uld/X-NUCLEO-53L1A1.h | 403 +++++++++ vl53lx_uld/vl53l1_error_codes.h | 253 ++++++ vl53lx_uld/vl53l1_platform.c | 431 +++++++++ vl53lx_uld/vl53l1_platform.h | 141 +++ vl53lx_uld/vl53l1_platform_log.h | 223 +++++ vl53lx_uld/vl53l1_platform_user_config.h | 84 ++ vl53lx_uld/vl53l1_platform_user_data.h | 66 ++ vl53lx_uld/vl53l1_platform_user_defines.h | 95 ++ vl53lx_uld/vl53l1_types.h | 114 +++ 39 files changed, 7188 insertions(+), 1729 deletions(-) delete mode 100644 .project create mode 100644 Core/Inc/i2c.h create mode 100644 Core/Src/i2c.c delete mode 100644 Core/Src/main_5_9.c delete mode 100644 Core/Src/presen-detection-temp.c delete mode 100644 Core/Src/sts_lamp_bar_MAY26.c delete mode 100644 Core/Src/yunhorn_sts_presence_sensor_JULY3.c create mode 100644 TOF/App/Example_1_basic_ranging.c create mode 100644 TOF/App/Example_2_tune_sensor_with_debug_data.c create mode 100644 TOF/App/Example_3_long_ranging.c create mode 100644 TOF/App/Example_4_ultra_low_power.c create mode 100644 TOF/App/app_tof.c create mode 100644 TOF/App/app_tof.h create mode 100644 TOF/App/app_tof_peoplecount.c create mode 100644 TOF/App/app_tof_peoplecount.h create mode 100644 TOF/Target/53l1a2_conf.h create mode 100644 TOF/Target/app_tof_pin_conf.c create mode 100644 TOF/Target/app_tof_pin_conf.h delete mode 100644 VL53L1X_BareDriver_with_UltraLowPower/Binary/VL53L1X_BareDriver_with_UltraLowPower.bin delete mode 100644 VL53L1X_UltraLowPower_Example/Binary/VL53L1X_UltraLowPower_Example.bin create mode 100644 vl53lx_uld/VL53L1X_ULP_api.c create mode 100644 vl53lx_uld/VL53L1X_ULP_api.h create mode 100644 vl53lx_uld/VL53L1X_ULP_platform.c create mode 100644 vl53lx_uld/VL53L1X_ULP_platform.h create mode 100644 vl53lx_uld/VL53L1X_api.c create mode 100644 vl53lx_uld/VL53L1X_api.h create mode 100644 vl53lx_uld/VL53L1X_calibration.c create mode 100644 vl53lx_uld/VL53L1X_calibration.h create mode 100644 vl53lx_uld/X-NUCLEO-53L1A1.c create mode 100644 vl53lx_uld/X-NUCLEO-53L1A1.h create mode 100644 vl53lx_uld/vl53l1_error_codes.h create mode 100644 vl53lx_uld/vl53l1_platform.c create mode 100644 vl53lx_uld/vl53l1_platform.h create mode 100644 vl53lx_uld/vl53l1_platform_log.h create mode 100644 vl53lx_uld/vl53l1_platform_user_config.h create mode 100644 vl53lx_uld/vl53l1_platform_user_data.h create mode 100644 vl53lx_uld/vl53l1_platform_user_defines.h create mode 100644 vl53lx_uld/vl53l1_types.h diff --git a/.project b/.project deleted file mode 100644 index 0be5481..0000000 --- a/.project +++ /dev/null @@ -1,11 +0,0 @@ - - - STS_O7 - - - - - - - - diff --git a/Core/Inc/i2c.h b/Core/Inc/i2c.h new file mode 100644 index 0000000..dcdd711 --- /dev/null +++ b/Core/Inc/i2c.h @@ -0,0 +1,51 @@ +/** + ****************************************************************************** + * @file i2c.h + * @brief This file contains all the function prototypes for + * the i2c.c 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 + * + ****************************************************************************** + */ +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __I2C_H__ +#define __I2C_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + + +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +void MX_I2C2_Init(void); + +/* USER CODE BEGIN Prototypes */ + +/* USER CODE END Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif /* __I2C_H__ */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Core/Src/i2c.c b/Core/Src/i2c.c new file mode 100644 index 0000000..3ab7d85 --- /dev/null +++ b/Core/Src/i2c.c @@ -0,0 +1,199 @@ +/** + ****************************************************************************** + * @file i2c.c + * @author Yunhorn (r) Technology Limited Application Team + * @brief This file provides code for the configuration + * of the I2C instances. + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 Yunhorn Technology Limited. + * Copyright (c) 2023 Shenzhen Yunhorn Technology Co., Ltd. + * + * 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 + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "i2c.h" +#include "main.h" +/* USER CODE BEGIN 0 */ +I2C_HandleTypeDef hi2c2; +DMA_HandleTypeDef hdma_i2c2_rx; +DMA_HandleTypeDef hdma_i2c2_tx; +/* USER CODE END 0 */ + +/* I2C2 init function */ +/** + * @brief I2C2 Initialization Function + * @param None + * @retval None + */ +void MX_I2C2_Init(void) +{ + + /* USER CODE BEGIN I2C2_Init 0 */ + + /* USER CODE END I2C2_Init 0 */ + + /* USER CODE BEGIN I2C2_Init 1 */ + + /* USER CODE END I2C2_Init 1 */ + hi2c2.Instance = I2C2; + //hi2c2.Init.Timing = 0x20303E5D; //0x2010091A = 400K Fast Mode, 0x20303E5D, 100K Standard mode, 0x20000209 Fast Mode Plus, 1Mbps + hi2c2.Init.Timing = I2C2_STANDARD_100K; //2024-07-12 UPDATE + hi2c2.Init.OwnAddress1 = 0; + hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; + hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; + hi2c2.Init.OwnAddress2 = 0; + hi2c2.Init.OwnAddress2Masks = I2C_OA2_NOMASK; + hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; + hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; + if (HAL_I2C_Init(&hi2c2) != HAL_OK) + { + Error_Handler(); + } + + /** Configure Analogue filter + */ + if (HAL_I2CEx_ConfigAnalogFilter(&hi2c2, I2C_ANALOGFILTER_ENABLE) != HAL_OK) + { + Error_Handler(); + } + /** Configure Digital filter + */ + if (HAL_I2CEx_ConfigDigitalFilter(&hi2c2, 0) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN I2C2_Init 2 */ + + /* USER CODE END I2C2_Init 2 */ + +} + +void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle) +{ + + GPIO_InitTypeDef GPIO_InitStruct = {0}; + RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; + if(i2cHandle->Instance==I2C2) + { + /* USER CODE BEGIN I2C2_MspInit 0 */ + + /* USER CODE END I2C2_MspInit 0 */ + + /** Initializes the peripherals clocks + */ + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2C2; + PeriphClkInitStruct.I2c2ClockSelection = RCC_I2C2CLKSOURCE_PCLK1; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) + { + Error_Handler(); + } + + + __HAL_RCC_GPIOA_CLK_ENABLE(); + /**I2C2 GPIO Configuration + PA12 ------> I2C2_SCL + PA11 ------> I2C2_SDA + */ + GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_11; + GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; + GPIO_InitStruct.Pull = GPIO_NOPULL; //GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF4_I2C2; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* I2C2 clock enable */ + __HAL_RCC_I2C2_CLK_ENABLE(); + + /* I2C2 DMA Init */ + /* I2C2_RX Init */ + hdma_i2c2_rx.Instance = DMA1_Channel4; + hdma_i2c2_rx.Init.Request = DMA_REQUEST_I2C2_RX; + hdma_i2c2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_i2c2_rx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_i2c2_rx.Init.MemInc = DMA_MINC_ENABLE; + hdma_i2c2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_i2c2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_i2c2_rx.Init.Mode = DMA_NORMAL; + hdma_i2c2_rx.Init.Priority = DMA_PRIORITY_LOW; + if (HAL_DMA_Init(&hdma_i2c2_rx) != HAL_OK) + { + Error_Handler(); + } +#ifdef STM32WL55xx + if (HAL_DMA_ConfigChannelAttributes(&hdma_i2c2_rx, DMA_CHANNEL_NPRIV) != HAL_OK) + { + Error_Handler(); + } +#endif + __HAL_LINKDMA(i2cHandle,hdmarx,hdma_i2c2_rx); + + /* I2C2_TX Init */ + hdma_i2c2_tx.Instance = DMA1_Channel5; + hdma_i2c2_tx.Init.Request = DMA_REQUEST_I2C2_TX; + hdma_i2c2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_i2c2_tx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_i2c2_tx.Init.MemInc = DMA_MINC_ENABLE; + hdma_i2c2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + hdma_i2c2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + hdma_i2c2_tx.Init.Mode = DMA_NORMAL; + hdma_i2c2_tx.Init.Priority = DMA_PRIORITY_LOW; + if (HAL_DMA_Init(&hdma_i2c2_tx) != HAL_OK) + { + Error_Handler(); + } +#ifdef STM32WL55xx + if (HAL_DMA_ConfigChannelAttributes(&hdma_i2c2_tx, DMA_CHANNEL_NPRIV) != HAL_OK) + { + Error_Handler(); + } +#endif + __HAL_LINKDMA(i2cHandle,hdmatx,hdma_i2c2_tx); + + /* USER CODE BEGIN I2C2_MspInit 1 */ + + /* USER CODE END I2C2_MspInit 1 */ + } +} + +void HAL_I2C_MspDeInit(I2C_HandleTypeDef* i2cHandle) +{ + + if(i2cHandle->Instance==I2C2) + { + /* USER CODE BEGIN I2C2_MspDeInit 0 */ + + /* USER CODE END I2C2_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_I2C2_CLK_DISABLE(); + + /**I2C2 GPIO Configuration + PA12 ------> I2C2_SCL + PA11 ------> I2C2_SDA + */ + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_12); + + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11); + + /* I2C2 DMA DeInit */ + HAL_DMA_DeInit(i2cHandle->hdmarx); + HAL_DMA_DeInit(i2cHandle->hdmatx); + + /* USER CODE BEGIN I2C2_MspDeInit 1 */ + + /* USER CODE END I2C2_MspDeInit 1 */ + } +} + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Core/Src/main_5_9.c b/Core/Src/main_5_9.c deleted file mode 100644 index 60e07d4..0000000 --- a/Core/Src/main_5_9.c +++ /dev/null @@ -1,224 +0,0 @@ -/* USER CODE BEGIN Header */ -/** - ****************************************************************************** - * @file: main.c * - * @author Yunhorn (r) Technology Limited Application Team * - * @brief Yunhorn (r) SmarToilets (r) Product configuration file. * - ****************************************************************************** - * @attention - * - * Copyright (c) 2023 Yunhorn Technology Limited. - * Copyright (c) 2023 Shenzhen Yunhorn Technology Co., Ltd. - * 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. - * - ****************************************************************************** - */ -/* USER CODE END Header */ -/* Includes ------------------------------------------------------------------*/ -#include "main.h" -#include "app_lorawan.h" -#include "gpio.h" -#include "usart.h" -/* Private includes ----------------------------------------------------------*/ -/* USER CODE BEGIN Includes */ -#include "yunhorn_sts_sensors.h" -#include "sts_cmox_hmac_sha.h" -#include "spi.h" -#include "dma.h" -#include "tim.h" -#include "sts_lamp_bar.h" -#include "sys_app.h" - -#include "acc_hal_integration.h" -#include "example_bring_up.h" -#include "example_multiple_service_usage.h" -#include "example_detector_distance.h" -#include "example_detector_presence.h" -#include "example_detector_distance_recorded.h" -#include "example_service_sparse.h" -#include "ref_app_wave_to_exit.h" -#include "ref_app_smart_presence.h" -#include "ref_app_tank_level.h" -#include "ref_app_parking.h" -#include "acc_detector_presence.h" -/* USER CODE END Includes */ - -/* Private typedef -----------------------------------------------------------*/ -/* USER CODE BEGIN PTD */ - -/* USER CODE END PTD */ - -/* Private define ------------------------------------------------------------*/ -/* USER CODE BEGIN PD */ -/* USER CODE END PD */ - -/* Private macro -------------------------------------------------------------*/ -/* USER CODE BEGIN PM */ - -/* USER CODE END PM */ - -/* Private variables ---------------------------------------------------------*/ - -/* USER CODE BEGIN PV */ - -/* USER CODE END PV */ - -/* Private function prototypes -----------------------------------------------*/ -void SystemClock_Config(void); -/* USER CODE BEGIN PFP */ - -/* USER CODE END PFP */ - -/* Private user code ---------------------------------------------------------*/ -/* USER CODE BEGIN 0 */ - -/* USER CODE END 0 */ - -/** - * @brief The application entry point. - * @retval int - */ -int main(void) -{ - /* USER CODE BEGIN 1 */ - - /* USER CODE END 1 */ - - /* MCU Configuration--------------------------------------------------------*/ - - /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ - HAL_Init(); - - /* USER CODE BEGIN Init */ - - /* USER CODE END Init */ - - /* Configure the system clock */ - SystemClock_Config(); - - /* USER CODE BEGIN SysInit */ - MX_GPIO_Init(); - MX_DMA_Init(); - MX_USART2_UART_Init(); - MX_TIM1_Init(); - MX_SPI1_Init(); - /* USER CODE END SysInit */ - - /* Initialize all configured peripherals */ - - MX_LoRaWAN_Init(); - /* USER CODE BEGIN 2 */ - - STS_Lamp_Bar_Self_Test_Simple(); - - - - - - /* USER CODE END 2 */ - - /* Infinite loop */ - /* USER CODE BEGIN WHILE */ - - while (1) - { - /* USER CODE END WHILE */ - - MX_LoRaWAN_Process(); - - - /* USER CODE BEGIN 3 */ - } - /* USER CODE END 3 */ -} - -/** - * @brief System Clock Configuration - * @retval None - */ -void SystemClock_Config(void) -{ - RCC_OscInitTypeDef RCC_OscInitStruct = {0}; - RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; - - /** Configure LSE Drive Capability - */ - HAL_PWR_EnableBkUpAccess(); - __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW); - - /** Configure the main internal regulator output voltage - */ - __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); - - /** Initializes the CPU, AHB and APB buses clocks - */ - RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE|RCC_OSCILLATORTYPE_MSI; - RCC_OscInitStruct.LSEState = RCC_LSE_ON; - RCC_OscInitStruct.MSIState = RCC_MSI_ON; - RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT; - RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_11; - RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; - if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) - { - Error_Handler(); - } - - /** Configure the SYSCLKSource, HCLK, PCLK1 and PCLK2 clocks dividers - */ - RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK3|RCC_CLOCKTYPE_HCLK - |RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1 - |RCC_CLOCKTYPE_PCLK2; - RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI; - RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; - RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; - RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; - RCC_ClkInitStruct.AHBCLK3Divider = RCC_SYSCLK_DIV1; - - if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) - { - Error_Handler(); - } -} - -/* USER CODE BEGIN 4 */ - -/* USER CODE END 4 */ - -/** - * @brief This function is executed in case of error occurrence. - * @retval None - */ -void Error_Handler(void) -{ - /* USER CODE BEGIN Error_Handler_Debug */ - /* User can add his own implementation to report the HAL error return state */ - __disable_irq(); - while (1) - { - } - /* USER CODE END Error_Handler_Debug */ -} - -#ifdef USE_FULL_ASSERT -/** - * @brief Reports the name of the source file and the source line number - * where the assert_param error has occurred. - * @param file: pointer to the source file name - * @param line: assert_param error line source number - * @retval None - */ -void assert_failed(uint8_t *file, uint32_t line) -{ - /* USER CODE BEGIN 6 */ - /* User can add his own implementation to report the file name and line number, - ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ - while (1) - { - } - /* USER CODE END 6 */ -} -#endif /* USE_FULL_ASSERT */ diff --git a/Core/Src/presen-detection-temp.c b/Core/Src/presen-detection-temp.c deleted file mode 100644 index 972f3c3..0000000 --- a/Core/Src/presen-detection-temp.c +++ /dev/null @@ -1,315 +0,0 @@ - -int sts_presence_rss_fall_rise_detection(void) -{ - const acc_hal_t *hal = acc_hal_integration_get_implementation(); - - if (!acc_rss_activate(hal)) - { - APP_LOG(TS_OFF, VLEVEL_H,"Failed to activate RSS\n"); - return EXIT_FAILURE; - } - - acc_rss_override_sensor_id_check_at_creation(true); - - acc_detector_presence_configuration_t presence_configuration = acc_detector_presence_configuration_create(); - if (presence_configuration == NULL) - { - APP_LOG(TS_OFF, VLEVEL_H,"Failed to create configuration\n"); - acc_rss_deactivate(); - return EXIT_FAILURE; - } - - switch (sts_rss_config_updated_flag) - { - case STS_RSS_CONFIG_DEFAULT: - set_default_configuration(presence_configuration); - break; - case STS_RSS_CONFIG_SIMPLE: - sts_rss_set_current_configuration_simple(presence_configuration); - APP_LOG(TS_OFF, VLEVEL_L,"\r\n##### YUNHORN STS *** Simple *** cfg applied\n"); - - break; - case STS_RSS_CONFIG_FULL: - sts_rss_set_current_configuration_full(presence_configuration); - APP_LOG(TS_OFF, VLEVEL_L,"\r\n######### YUNHORN STS *** FULL *** cfg applied\n"); - break; - default: - break; - } - sts_rss_config_updated_flag = STS_RSS_CONFIG_DEFAULT; //update finished, set to 0 - - acc_detector_presence_handle_t handle = acc_detector_presence_create(presence_configuration); - if (handle == NULL) - { - APP_LOG(TS_OFF, VLEVEL_H,"Failed to create detector\n"); - acc_detector_presence_configuration_destroy(&presence_configuration); - acc_detector_presence_destroy(&handle); - acc_rss_deactivate(); - return EXIT_FAILURE; - } - -// ******** First Half detection of fall down and rise up - if (!acc_detector_presence_activate(handle)) - { - APP_LOG(TS_OFF, VLEVEL_H, "Failed to activate detector \n"); - return false; - } - - bool success = true; - const int iterations = (DEFAULT_UPDATE_RATE_PRESENCE+1); - acc_detector_presence_result_t result; - uint8_t average_result = 0; - float average_distance =0.0f; - float average_score =0.0f; - for (int i = 0; i < (iterations/2); i++) - { - success = acc_detector_presence_get_next(handle, &result); - if (!success) - { - APP_LOG(TS_OFF, VLEVEL_H,"acc_detector_presence_get_next() failed\n"); - break; - } - - print_result(result); - //if (!result.data_saturated) - { - if (result.presence_detected) - { - average_result++; - average_distance += result.presence_distance; - average_score += result.presence_score; - } - - if (sts_presence_fall_detection == 1) - { - sts_motion_dataset[motion_count].presence_distance = result.presence_distance; - sts_motion_dataset[motion_count].presence_score = result.presence_score; - - if (motion_count ++ == DEFAULT_MOTION_DATASET_LEN) - { - STS_YunhornCheckStandardDeviation(); - motion_count = 0; - } - } - } - - acc_integration_sleep_ms(1000 / DEFAULT_UPDATE_RATE_PRESENCE); // DEFAULT_UPDATE_RATE); - } - - acc_detector_presence_deactivate(handle); - APP_LOG(TS_OFF, VLEVEL_L,"First Half Presence Detection, Motion Count = %u \r\n", (int)motion_count); - -// ******** Second Half detection of fall down and rise up - - set_default_fall_rise_configuration(presence_configuration); - - if (!acc_detector_presence_reconfigure(&handle, presence_configuration)) - { - APP_LOG(TS_OFF, VLEVEL_M,"Failed to reconfigure detector\n"); - acc_detector_presence_configuration_destroy(&presence_configuration); - acc_detector_presence_destroy(&handle); - acc_rss_deactivate(); - return EXIT_FAILURE; - } - - - if (!acc_detector_presence_activate(handle)) - { - APP_LOG(TS_OFF, VLEVEL_H, "Failed to activate detector \n"); - return false; - } - acc_detector_presence_configuration_destroy(&presence_configuration); - - for (int i = 0; i < (iterations/2); i++) - { - success = acc_detector_presence_get_next(handle, &result); - if (!success) - { - APP_LOG(TS_OFF, VLEVEL_H,"acc_detector_presence_get_next() failed\n"); - break; - } - - print_result(result); - //if (!result.data_saturated) - { - if (result.presence_detected) - { - average_result++; - average_distance += result.presence_distance; - average_score += result.presence_score; - } - - if (sts_presence_fall_detection == 1) - { - sts_motion_dataset[motion_count].presence_distance = result.presence_distance; - sts_motion_dataset[motion_count].presence_score = result.presence_score; - - if (motion_count ++ == DEFAULT_MOTION_DATASET_LEN) - { - STS_YunhornCheckStandardDeviation(); - motion_count = 0; - } - } - } - - acc_integration_sleep_ms(1000 / DEFAULT_UPDATE_RATE_PRESENCE); // DEFAULT_UPDATE_RATE); - } - - APP_LOG(TS_OFF, VLEVEL_L,"Second Half, Fall Rise Detection, Motion Count = %u \r\n", (int)motion_count); - - sts_rss_result = (average_result > 3)? 1: 0; - average_distance = (1000.0f*average_distance)/average_result; // in meters - average_score = (1000.0f*average_score)/average_result; - sts_presence_rss_distance = average_distance; - sts_presence_rss_score = average_score; - if (average_score !=0) //if (sts_rss_result) - { - APP_LOG(TS_OFF, VLEVEL_H,"\r\n######## Motion: %u Distance=%u mm, Score=%u Average_result=%u out of %u \r\n", - (uint8_t)sts_rss_result,(int) average_distance, (int)(average_score), (int)average_result, (int)iterations); - } - - - bool deactivated = acc_detector_presence_deactivate(handle); - - acc_detector_presence_destroy(&handle); - - acc_rss_deactivate(); - - if (deactivated && success) - { - //APP_LOG(TS_OFF, VLEVEL_M,"Application finished OK\n"); - return EXIT_SUCCESS; - } - - return EXIT_FAILURE; - -} - - - - -int sts_presence_rss_presence_detection(void) -{ - const acc_hal_t *hal = acc_hal_integration_get_implementation(); - - if (!acc_rss_activate(hal)) - { - APP_LOG(TS_OFF, VLEVEL_H,"Failed to activate RSS\n"); - return EXIT_FAILURE; - } - - acc_rss_override_sensor_id_check_at_creation(true); - - acc_detector_presence_configuration_t presence_configuration = acc_detector_presence_configuration_create(); - if (presence_configuration == NULL) - { - APP_LOG(TS_OFF, VLEVEL_H,"Failed to create configuration\n"); - acc_rss_deactivate(); - return EXIT_FAILURE; - } - - switch (sts_rss_config_updated_flag) - { - case STS_RSS_CONFIG_DEFAULT: - set_default_configuration(presence_configuration); - break; - case STS_RSS_CONFIG_SIMPLE: - sts_rss_set_current_configuration_simple(presence_configuration); - APP_LOG(TS_OFF, VLEVEL_L,"\r\n##### YUNHORN STS *** Simple *** cfg applied\n"); - - break; - case STS_RSS_CONFIG_FULL: - sts_rss_set_current_configuration_full(presence_configuration); - APP_LOG(TS_OFF, VLEVEL_L,"\r\n######### YUNHORN STS *** FULL *** cfg applied\n"); - break; - default: - break; - } - sts_rss_config_updated_flag = STS_RSS_CONFIG_DEFAULT; //update finished, set to 0 - - acc_detector_presence_handle_t handle = acc_detector_presence_create(presence_configuration); - if (handle == NULL) - { - APP_LOG(TS_OFF, VLEVEL_H,"Failed to create detector\n"); - acc_detector_presence_configuration_destroy(&presence_configuration); - acc_detector_presence_destroy(&handle); - acc_rss_deactivate(); - return EXIT_FAILURE; - } - - acc_detector_presence_configuration_destroy(&presence_configuration); - - if (!acc_detector_presence_activate(handle)) - { - APP_LOG(TS_OFF, VLEVEL_H,"Failed to activate detector\n"); - acc_detector_presence_destroy(&handle); - acc_rss_deactivate(); - return EXIT_FAILURE; - } - - bool success = true; - const int iterations = DEFAULT_UPDATE_RATE_PRESENCE; - acc_detector_presence_result_t result; - uint8_t average_result = 0; - float average_distance =0.0f; - float average_score =0.0f; - for (int i = 0; i < iterations; i++) - { - success = acc_detector_presence_get_next(handle, &result); - if (!success) - { - APP_LOG(TS_OFF, VLEVEL_H,"acc_detector_presence_get_next() failed\n"); - break; - } - - print_result(result); - //if (!result.data_saturated) - { - if (result.presence_detected) - { - average_result++; - average_distance += result.presence_distance; - average_score += result.presence_score; - } - - if (sts_presence_fall_detection == 1) - { - sts_motion_dataset[motion_count].presence_distance = result.presence_distance; - sts_motion_dataset[motion_count].presence_score = result.presence_score; - - if (motion_count ++ == DEFAULT_MOTION_DATASET_LEN) - { - STS_YunhornCheckStandardDeviation(); - motion_count = 0; - } - } - } - - acc_integration_sleep_ms(1000 / DEFAULT_UPDATE_RATE_PRESENCE); // DEFAULT_UPDATE_RATE); - } - - sts_rss_result = (average_result > 3)? 1: 0; - average_distance = (1000.0f*average_distance)/average_result; // in meters - average_score = (1000.0f*average_score)/average_result; - sts_presence_rss_distance = average_distance; - sts_presence_rss_score = average_score; - if (average_score !=0) //if (sts_rss_result) - { - APP_LOG(TS_OFF, VLEVEL_H,"\r\n######## Motion: %u Distance=%u mm, Score=%u Average_result=%u out of %u \r\n", - (uint8_t)sts_rss_result,(int) average_distance, (int)(average_score), (int)average_result, (int)iterations); - } - - bool deactivated = acc_detector_presence_deactivate(handle); - - acc_detector_presence_destroy(&handle); - - acc_rss_deactivate(); - - if (deactivated && success) - { - //APP_LOG(TS_OFF, VLEVEL_M,"Application finished OK\n"); - return EXIT_SUCCESS; - } - - return EXIT_FAILURE; -} diff --git a/Core/Src/sts_lamp_bar_MAY26.c b/Core/Src/sts_lamp_bar_MAY26.c deleted file mode 100644 index c3e9b58..0000000 --- a/Core/Src/sts_lamp_bar_MAY26.c +++ /dev/null @@ -1,624 +0,0 @@ -/* USER CODE BEGIN Header */ -/** - ****************************************************************************** - * @file yunhorn_sts_lamp_bar.c * - * @author Yunhorn (r) Technology Limited Application Team * - * @brief Yunhorn (r) SmarToilets (r) Product configuration file. * - ****************************************************************************** - * @attention - * - * Copyright (c) 2022 Yunhorn Technology Limited. - * Copyright (c) 2022 Shenzhen Yunhorn Technology Co., Ltd. - * 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. - * - ****************************************************************************** - */ -/* USER CODE END Header */ -#include "main.h" -#include "dma.h" -#include "tim.h" -#include "string.h" -#include "sys_app.h" -#include "stm32_systime.h" -#include "sts_lamp_bar.h" -#include "ref_app_smart_presence.h" -#include "yunhorn_sts_sensors.h" - -#define ONE_PULSE (36) -#define ZERO_PULSE (20) - -#define LED_DATA_LEN (24) -#define WS2812B_DATA_LEN (LED_DATA_LEN * (STS_LAMP_BAR_LED_NUM+4)) -#define DEFAULT_LUMINANCE_LEVEL (20) -#define RESET_PULSE (10) //(80) TO FIX DARK_COLOR AND SM2 - - -typedef struct ws2812b_e { - uint16_t head[3]; - uint16_t GRB[24*STS_LAMP_BAR_LED_NUM]; - uint16_t tail; -} WS2812B_FrameTypeDef; - -volatile WS2812B_FrameTypeDef rgb_buf = { - .head[0] = 0, - .head[1] = 0, - .head[2] = 0, - .tail = 0 -}; - -uint8_t color_rgb[8][3] = { //STS_COLOR R G B MAPPING TABLE - {0,0,0},{0,1,0},{1,0,0},{0,0,1},{1,1,0},{1,0,1},{0,1,1},{1,1,1} -}; -volatile uint8_t sts_service_mask; -volatile uint8_t sts_work_mode = STS_DUAL_MODE; -volatile uint8_t sts_reed_hall_ext_int = 0; -volatile uint8_t sts_status_color = STS_DARK; -volatile uint8_t sts_lamp_bar_color = STS_GREEN; //puColor -volatile uint8_t sts_cloud_netcolor = STS_GREEN; //netColor -volatile uint8_t sts_occupancy_status; -volatile uint8_t sts_reed_hall_changed_flag = 1; -volatile uint8_t sts_reed_hall_result =0; -volatile uint8_t sts_tof_result_changed_flag = 0; -volatile uint8_t sts_water_leakage_result=0; -volatile uint8_t sts_water_leakage_changed_flag=0; - -volatile uint8_t sts_rss_result_changed_flag = 0; -volatile uint8_t sts_rss_result = STS_RESULT_NO_MOTION; -volatile uint8_t sts_rss_2nd_result = STS_RESULT_NO_MOTION; //2nd RSS sensor status -volatile uint8_t sts_tof_result = STS_RESULT_NO_MOTION; -volatile uint8_t last_sts_rss_result; -volatile uint8_t last_sts_reed_hall_result = 2; //Initial state, not 0, not 1 -volatile uint8_t last_lamp_bar_color; -extern volatile uint8_t sts_presence_fall_detection; -extern volatile float sts_presence_rss_distance; -extern volatile uint8_t sensor_data_ready; -extern SysTime_t mems_event_time; -extern volatile uint32_t event_start_time, event_stop_time; -uint8_t luminance_level = DEFAULT_LUMINANCE_LEVEL; - - -void STS_YunhornSTSEventP1_Process(void) -{ - STS_Lamp_Bar_Refresh(); - if ((sts_work_mode == STS_WIRED_MODE) || (sts_work_mode == STS_REEDSWITCH_MODE) || (sts_work_mode == STS_DUAL_MODE)) - { - STS_Reed_Hall_Presence_Detection(); - - if (sts_reed_hall_result == last_sts_reed_hall_result) { - sts_reed_hall_changed_flag = 0; - } else { - sts_reed_hall_changed_flag = 1; - STS_Combined_Status_Processing(); - } - - last_sts_reed_hall_result = sts_reed_hall_result; - } - -} - -void STS_YunhornSTSEventP2_Process(void) -{ - STS_Lamp_Bar_Refresh(); - if ((sts_work_mode >= STS_RSS_MODE) && (sts_work_mode <= STS_TOF_RSS_MODE)) - { - STS_RSS_Smart_Presence_Detection(); - STS_Reed_Hall_Presence_Detection(); - - if (sts_rss_result == last_sts_rss_result) { - sts_rss_result_changed_flag =0; - } else { - sts_rss_result_changed_flag =1; - last_sts_rss_result = sts_rss_result; - } - - if (sts_reed_hall_result == last_sts_reed_hall_result) - { - sts_reed_hall_changed_flag = 0; - - } else - { - sts_reed_hall_changed_flag = 1; - } - if (sts_service_mask > 0 ) { - sts_rss_result_changed_flag =0; - sts_reed_hall_changed_flag = 0; - } - - STS_Combined_Status_Processing(); - - last_sts_rss_result = sts_rss_result; - last_sts_reed_hall_result = sts_reed_hall_result; - } - -} - -void STS_Reed_Hall_Presence_Detection(void) -{ -// HAL_Delay(50); // BOUNCING ELIMIATION - - if (STS_Reed_Hall_State == STS_Status_Door_Open) - { - sts_reed_hall_result = STS_Status_Door_Open; - - } else if (STS_Reed_Hall_State == STS_Status_Door_Close) - { - sts_reed_hall_result = STS_Status_Door_Close; - - } - - //sts_reed_hall_result = ((STS_Reed_Hall_State)&STS_Status_Door_Open); - -// HAL_Delay(20); // BOUNCING ELIMIATION - - sts_reed_hall_changed_flag = 0; - - sts_reed_hall_ext_int = 0; - -} - -void STS_RSS_Smart_Presence_Detection(void) -{ - STS_Lamp_Bar_Refresh(); - - //sts_presence_rss_presence_detection(); - - sts_presence_rss_fall_rise_detection(); - -// if (sts_presence_fall_detection) { -// STS_YunhornSTSFallDetection(); -// } - -} - -/* - * STS P3 process, Lamp Bar Scoller - */ -void STS_YunhornSTSEventP3_Process(void) -{ - STS_Lamp_Bar_Refresh(); - if (STS_Reed_Hall_State == STS_Status_Door_Open) - { - sts_lamp_bar_color =STS_GREEN; - } - else - { - sts_lamp_bar_color =STS_RED; - } - STS_Lamp_Bar_Scoller(sts_lamp_bar_color, luminance_level); -} - -/* - * STS P4 Process, STS_CAP_Sensor_Detection Process - * STS_CAP_SWITCH(ON) Boost Voltage to 5V, then hold for 1000 ms - * HAL_Delay(1000) (ms) - * STS_CAP_Read_Data() Read STS_CAP_DATA state - * STS_CAP_SWITCH(OFF) Switch Off Boosted Voltage - */ -void STS_YunhornSTSEventP4_Process(void) -{ - - APP_LOG(TS_OFF, VLEVEL_L, "\r\n P4 Testing Process\r\n"); - -} - -/* - * STS P5 Process, Detection ToF distance (VL53L0X) - * - */ - -void STS_YunhornSTSEventP5_Process(void) -{ - APP_LOG(TS_OFF, VLEVEL_L, "\r\n P5 Testing Process\r\n"); -} - -/* - * STS P6 Process, Detection ToF IN-OUT PEOPLE COUNT (VL53L3X) - * - */ - -void STS_YunhornSTSEventP6_Process(void) -{ - APP_LOG(TS_OFF, VLEVEL_L, "\r\n P6 Testing Process\r\n"); -} - - -/* - * STS P7 Process, Detection IAQ Sensors - * air quality and odor level sensors - */ - -void STS_YunhornSTSEventP7_Process(void) -{ - APP_LOG(TS_OFF, VLEVEL_L, "\r\n P7 Testing Process\r\n"); -} - - -/* - * STS P8 Process, Detection xxx Sensors - * xxx sensors - */ - -void STS_YunhornSTSEventP8_Process(void) -{ - APP_LOG(TS_OFF, VLEVEL_L, "\r\n P8 Testing Process\r\n"); -} - - -void STS_Lamp_Bar_Set_Dark(void) -{ - for (uint8_t i=0; i< STS_LAMP_BAR_LED_NUM; i++) - { - STS_WS2812B_Set_RGB(0x00,0x00,0x00,i); - } - //STS_WS2812B_Refresh(); -} - -void STS_WS2812B_Refresh(void) -{ - HAL_TIM_PWM_Start_DMA(&STS_LAMP_BAR_HTIM, STS_LAMP_BAR_TIM_CHANNEL, (uint32_t *)&rgb_buf, (RESET_PULSE+WS2812B_DATA_LEN+1)); - - //HAL_TIM_PWM_Start_IT(&STS_LAMP_BAR_HTIM, STS_LAMP_BAR_TIM_CHANNEL); -} - -void STS_Lamp_Bar_Init(void) -{ - if (sts_service_mask == STS_SERVICE_MASK_L0) - { - STS_Lamp_Bar_Set_STS_RGB_Color(STS_GREEN, luminance_level); - //STS_WS2812B_Refresh(); - HAL_Delay(200); - STS_Lamp_Bar_Set_STS_RGB_Color(STS_RED, luminance_level); - //STS_WS2812B_Refresh(); - HAL_Delay(200); - STS_Lamp_Bar_Set_STS_RGB_Color(STS_BLUE, luminance_level); - //STS_WS2812B_Refresh(); - HAL_Delay(200); - } -} - -//marquee scoller -void STS_Lamp_Bar_Scoller(uint8_t color, uint8_t luminance_level) -{ - STS_Lamp_Bar_Set_Dark(); - - for(uint8_t i = 0; i<(STS_LAMP_BAR_LED_NUM+1); i++) - { - //if (sts_service_mask < STS_SERVICE_MASK_L1) - // STS_WS2812B_Refresh(); - HAL_Delay(60); - if (i < STS_LAMP_BAR_LED_NUM) { - STS_WS2812B_Set_RGB(color_rgb[color][0]*luminance_level,color_rgb[color][1]*luminance_level, color_rgb[color][2]*luminance_level, i); - } - } - HAL_Delay(10); - - //if (sts_service_mask == STS_SERVICE_MASK_L0) { - // STS_WS2812B_Refresh(); - //} - -} - - -void STS_WS2812B_Set_RGB(uint8_t R, uint8_t G, uint8_t B, uint8_t idx) -{ - if (idx < STS_LAMP_BAR_LED_NUM) - { - for (uint8_t j = 0; j < 8; j ++) - { - rgb_buf.GRB[idx*24+j] = (G&(0X80)>>j)? ONE_PULSE : ZERO_PULSE; - rgb_buf.GRB[idx*24+8+j] = (R&(0X80)>>j)? ONE_PULSE : ZERO_PULSE; - rgb_buf.GRB[idx*24+16+j] = (B&(0X80)>>j)? ONE_PULSE : ZERO_PULSE; - } - } - // CHANGED AT 2023-05-10 - if (sts_service_mask == STS_SERVICE_MASK_L0) { - STS_WS2812B_Refresh(); - } -} - -void STS_Lamp_Bar_Set_RGB_Color(uint8_t red, uint8_t green, uint8_t blue ) -{ - HAL_Delay(1); - for(uint8_t i = 0; i < STS_LAMP_BAR_LED_NUM; i++) - { - for (uint8_t j = 0; j < 8; j ++) - { - rgb_buf.GRB[i*24+j] = (green&(0x80)>>j)? ONE_PULSE : ZERO_PULSE; - rgb_buf.GRB[i*24+8+j] = (red&(0x80)>>j)? ONE_PULSE : ZERO_PULSE; - rgb_buf.GRB[i*24+16+j] = (blue&(0x80)>>j)? ONE_PULSE : ZERO_PULSE; - } - } - if (sts_service_mask == STS_SERVICE_MASK_L0) { - STS_WS2812B_Refresh(); - } - -} - - -void STS_Lamp_Bar_Refresh(void) -{ - STS_Lamp_Bar_Set_STS_RGB_Color(sts_lamp_bar_color, luminance_level); -} -void STS_Lamp_Bar_Set_STS_RGB_Color(uint8_t sts_lamp_color, uint8_t luminance_level) -{ - uint8_t lum = luminance_level; - - STS_Lamp_Bar_Set_RGB_Color(0x0, 0x0, 0x0); - switch (sts_lamp_color) - { - case STS_DARK: - STS_Lamp_Bar_Set_RGB_Color(0x0, 0x0, 0x0); - break; - case STS_GREEN: - STS_Lamp_Bar_Set_RGB_Color(0x0, lum, 0x0); - break; - case STS_RED: - STS_Lamp_Bar_Set_RGB_Color(lum, 0x0, 0x0); - break; - case STS_BLUE: - STS_Lamp_Bar_Set_RGB_Color(0x0, 0x0, lum); - break; - case STS_YELLOW: - STS_Lamp_Bar_Set_RGB_Color(lum, lum, 0x0); - break; - case STS_PINK: - STS_Lamp_Bar_Set_RGB_Color(lum, 0x0, lum); - break; - case STS_CYAN: - STS_Lamp_Bar_Set_RGB_Color(0x0, lum, lum); - break; - case STS_WHITE: - STS_Lamp_Bar_Set_RGB_Color(lum, lum, lum); - break; - case STS_RED_BLUE: - STS_Lamp_Bar_Set_RGB_Color(lum, 0x0, 0x0); - HAL_Delay(300); - STS_Lamp_Bar_Set_RGB_Color(0x0, 0x0, lum); - HAL_Delay(300); - break; - } -} - -void STS_Reed_Hall_Working(void) -{ - -} -void STS_Combined_Status_Processing(void) -{ - mems_event_time = SysTimeGetMcuTime(); - - if ((sts_rss_result == STS_RESULT_MOTION) || (sts_reed_hall_result == STS_Status_Door_Close) || (sts_tof_result == STS_RESULT_PRESENCE)) - { - - if (event_start_time == 0) { - - event_start_time = mems_event_time.Seconds; - event_stop_time = 0; - - APP_LOG(TS_OFF, VLEVEL_L, "\r\n Event Started at %6u Seconds \r\n", event_start_time); - } - - - } else if ((sts_rss_result != STS_RESULT_MOTION) || (sts_reed_hall_result != STS_Status_Door_Close) || (sts_tof_result != STS_RESULT_PRESENCE)) - { - if (event_stop_time ==0) - { - event_stop_time = mems_event_time.Seconds; - - event_start_time = 0; - - APP_LOG(TS_OFF, VLEVEL_L, "\r\n Event Stop at %6u Seconds \r\n", event_stop_time); - } - } - - switch (sts_work_mode) - { - case STS_NETWORK_MODE: - sts_status_color = sts_cloud_netcolor; - break; - case STS_WIRED_MODE: // NO LAMP BAR FOR THOSE WATER LEAKAGE SENSOR OR SOAP CAPACITY SENSORS - sts_status_color = STS_DARK; - sts_water_leakage_result = (sts_reed_hall_result == STS_Status_Door_Open )?STS_RESULT_WATER_LEAKAGE_YES:STS_RESULT_WATER_LEAKAGE_NO; - sts_water_leakage_changed_flag = 1; - break; - case STS_REEDSWITCH_MODE: - - sts_status_color = (sts_reed_hall_result == STS_Status_Door_Open )? STS_GREEN: STS_RED; - - break; - case STS_RSS_MODE: - if (sts_rss_result == STS_RESULT_NO_MOTION){ - sts_status_color = STS_GREEN; - } else if ((sts_rss_result == STS_RESULT_MOTION)) - { - sts_status_color = STS_RED; - } - break; - case STS_DUAL_MODE: - if ((sts_rss_result == STS_RESULT_NO_MOTION) && (sts_reed_hall_result == STS_Status_Door_Open )) - { - sts_status_color = STS_GREEN; - - } else if ((sts_rss_result == STS_RESULT_MOTION) || (sts_reed_hall_result == STS_Status_Door_Close )) - { - sts_status_color = STS_RED; - } - break; - case STS_REMOTE_REED_RSS_MODE: - if ((sts_rss_result == STS_RESULT_NO_MOTION) && (sts_reed_hall_result == STS_Status_Door_Open )) - { - sts_status_color = STS_GREEN; - - } else if ((sts_rss_result == STS_RESULT_MOTION) || (sts_reed_hall_result == STS_Status_Door_Close )) - { - sts_status_color = STS_RED; - } - break; - case STS_DUAL_RSS_MODE: - if ((sts_rss_result == STS_RESULT_NO_MOTION) && (sts_rss_2nd_result == STS_RESULT_NO_MOTION)) - { - sts_status_color = STS_GREEN; - } else if ((sts_rss_result == STS_RESULT_MOTION) || (sts_rss_2nd_result == STS_RESULT_MOTION)) - { - sts_status_color = STS_RED; - } - - break; - case STS_TOF_RSS_MODE: - if ((sts_rss_result == STS_RESULT_NO_MOTION) && (sts_tof_result == STS_RESULT_NO_PRESENCE)){ - sts_status_color = STS_GREEN; - - } else if ((sts_rss_result == STS_RESULT_MOTION) || (sts_tof_result == STS_RESULT_PRESENCE)) - { - sts_status_color = STS_RED; - } - - break; -// TO-DO LIST *********************************************************** - case STS_TOF_DISTANCE_MODE: - if ((sts_tof_result == STS_RESULT_NO_PRESENCE)) { - sts_status_color = STS_GREEN; - } else if ((sts_tof_result == STS_RESULT_PRESENCE)) { - sts_status_color = STS_RED; - } - break; - case STS_TOF_PRESENCE_MODE: - if ((sts_tof_result == STS_RESULT_NO_PRESENCE)) { - sts_status_color = STS_GREEN; - } else if ((sts_tof_result == STS_RESULT_PRESENCE)) { - sts_status_color = STS_RED; - } - break; - case STS_TOF_IN_OUT_MODE: - if ((sts_tof_result == STS_RESULT_NO_PRESENCE)) { - sts_status_color = STS_GREEN; - } else if ((sts_tof_result == STS_RESULT_PRESENCE)) { - sts_status_color = STS_RED; - } - break; -// TO-DO LIST *********************************************************** - default: - break; - } - - - if (sts_status_color == STS_RED_BLUE) - { - STS_Lamp_Bar_Set_STS_RGB_Color(sts_lamp_bar_color, luminance_level); - } - if ((sts_work_mode == STS_WIRED_MODE) || (sts_service_mask > STS_SERVICE_MASK_L0)) - { - sts_status_color = STS_DARK; - sts_lamp_bar_color = STS_DARK; - last_lamp_bar_color = STS_DARK; - STS_Lamp_Bar_Set_Dark(); - } - else - { - - //if ((last_lamp_bar_color != sts_status_color)) - { - sts_lamp_bar_color = ((sts_service_mask == STS_SERVICE_MASK_L0)? sts_status_color:STS_DARK); - - STS_Lamp_Bar_Set_STS_RGB_Color(sts_lamp_bar_color, luminance_level); - - if ((sts_service_mask == STS_SERVICE_MASK_L0) || (sts_lamp_bar_color == STS_DARK)) - { - // STS_WS2812B_Refresh(); - } - - last_lamp_bar_color = sts_lamp_bar_color; - } - } - - if ((sts_rss_result_changed_flag)|| (sts_reed_hall_changed_flag) || (sts_tof_result_changed_flag) || (sts_water_leakage_changed_flag)) - { - sensor_data_ready = 1; - STS_PRESENCE_SENSOR_Prepare_Send_Data(); - sts_rss_result_changed_flag =0; - sts_reed_hall_changed_flag =0; - sts_tof_result_changed_flag =0; - sts_water_leakage_changed_flag=0; - } -} - -void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) -{ - __HAL_TIM_SetCompare(&STS_LAMP_BAR_HTIM, STS_LAMP_BAR_TIM_CHANNEL,0); - HAL_TIM_PWM_Stop_DMA(&STS_LAMP_BAR_HTIM,STS_LAMP_BAR_TIM_CHANNEL); - -} - -void STS_Lamp_Bar_Self_Test_Simple(void) -{ - uint8_t color=0, luminance_level=10; - APP_LOG(TS_OFF, VLEVEL_M, "\r\n [#1] RGB Space Lumianance Level Testing Start\r\n"); - for (color=STS_GREEN; color <= STS_RED_BLUE; color++) - { - luminance_level = 10; - do { - STS_Lamp_Bar_Set_STS_RGB_Color(color, luminance_level); - HAL_Delay(10); - luminance_level += 20; - } while (luminance_level < 99); - //STS_Lamp_Bar_Set_Dark(); - } - APP_LOG(TS_OFF, VLEVEL_M, "\r\n [#1] RGB Space Lumianance Level Testing Finished\r\n"); -} -void STS_Lamp_Bar_Self_Test(void) -{ - uint8_t color=0, luminance_level=10; - - APP_LOG(TS_OFF, VLEVEL_M, "\r\n YunHorn STS Indicative Lamp Self Test\r\n"); - - STS_Lamp_Bar_Self_Test_Simple(); - - APP_LOG(TS_OFF, VLEVEL_H, "\r\n [#2] Scoller Testing\r\n"); - for (color = STS_GREEN; color <= STS_RED_BLUE; color++) - { - STS_Lamp_Bar_Scoller(color, luminance_level); - } - STS_Lamp_Bar_Set_Dark(); - - APP_LOG(TS_OFF, VLEVEL_M, "\r\n [##] YunHorn STS Indicative Lamp Self Test Finished\r\n"); - if ((sts_work_mode == STS_WIRED_MODE) ) - { - STS_Lamp_Bar_Set_Dark(); - } else - { - STS_Lamp_Bar_Set_STS_RGB_Color(STS_GREEN, luminance_level); - } - - -} -void sts_rgb_unit_test(void) -{ - - APP_LOG(TS_OFF, VLEVEL_L, "\r\n STS Lamp Bar Init...\r\n"); - - STS_Lamp_Bar_Set_Dark(); - - STS_Lamp_Bar_Full_Color_Gradient(); - - STS_Lamp_Bar_Self_Test(); - - do { - for (uint8_t i=0; i<9; i++) - { - APP_LOG(TS_OFF, VLEVEL_L, "\r\n STS Lamp Bar color = %d...\r\n", i); - - STS_Lamp_Bar_Set_STS_RGB_Color(i, luminance_level); - STS_Combined_Status_Processing(); - HAL_Delay(6000); - STS_Lamp_Bar_Set_Dark(); - } - } while(1); - - - -} - diff --git a/Core/Src/yunhorn_sts_presence_sensor_JULY3.c b/Core/Src/yunhorn_sts_presence_sensor_JULY3.c deleted file mode 100644 index eaedba4..0000000 --- a/Core/Src/yunhorn_sts_presence_sensor_JULY3.c +++ /dev/null @@ -1,555 +0,0 @@ -/* USER CODE BEGIN Header */ -/** - ****************************************************************************** - * @file yunhorn_sts_presence_sensor.c * - * @author Yunhorn (r) Technology Limited Application Team * - * @brief Yunhorn (r) SmarToilets (r) Product configuration file. * - ****************************************************************************** - * @attention - * - * Copyright (c) 2022 Yunhorn Technology Limited. - * Copyright (c) 2022 Shenzhen Yunhorn Technology Co., Ltd. - * 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. - * - ****************************************************************************** - */ -/* USER CODE END Header */ - -/* Includes ------------------------------------------------------------------*/ -#include "stdint.h" -#include "platform.h" -#include "sys_conf.h" -#include "sys_app.h" -#include "stdio.h" -#include "stm32_systime.h" -#include "adc_if.h" -#include "gpio.h" -#include "LmHandler.h" -#include "lora_app.h" -#include "yunhorn_sts_prd_conf.h" -#include "yunhorn_sts_sensors.h" -#include "sts_cmox_hmac_sha.h" -/* USER CODE BEGIN Includes */ -#if (defined(YUNHORN_STS_O6_ENABLED) && defined(USE_ACCONEER_A111)) -//#include "yunhorn_sts_rss_sensor.h" -extern volatile uint8_t sts_ac_code[20]; -volatile uint32_t rfac_timer; -extern volatile uint8_t sensor_data_ready; -volatile STS_OO_SensorStatusDataTypeDef sts_o6_sensorData; -volatile STS_PRESENCE_SENSOR_Event_Status_t sts_o6_event_status; -volatile float sts_distance_rss_distance; -extern volatile float sts_presence_rss_distance, sts_presence_rss_score; -volatile uint8_t sts_rss_config_updated_flag = 0; -extern volatile uint8_t mems_int1_detected, link_wakeup, link_sleep; -volatile uint32_t event_start_time, event_stop_time; -extern volatile STS_OO_RSS_SensorTuneDataTypeDef sts_presence_rss_config; -extern volatile sts_cfg_nvm_t sts_cfg_nvm; -extern volatile uint8_t sts_fall_detection_acc_threshold, sts_fall_detection_depth_threshold, sts_occupancy_overtime_threshold; -extern volatile uint8_t sts_reed_hall_result, sts_rss_result, sts_rss_2nd_result,sts_tof_result, sts_status_color, sts_lamp_bar_color, sts_work_mode, sts_service_mask; -extern volatile distance_measure_cfg_t distance_cfg; -extern uint8_t sts_fall_rising_detected_result; -extern volatile uint16_t sts_fall_rising_pattern_factor1; -extern volatile uint16_t sts_roc_acc_standard_variance; -extern uint8_t luminance_level; -SysTime_t mems_event_time; - -#endif - -/* USER CODE END Includes */ - -/* External variables ---------------------------------------------------------*/ -/* USER CODE BEGIN EV */ - -/* USER CODE END EV */ - -/* Private typedef -----------------------------------------------------------*/ -/* USER CODE BEGIN PTD */ - -/* USER CODE END PTD */ - -/* Private define ------------------------------------------------------------*/ - -/* USER CODE BEGIN PD */ - -/* USER CODE END PD */ - -/* Private macro -------------------------------------------------------------*/ -/* USER CODE BEGIN PM */ - -/* USER CODE END PM */ - -/* Private variables ---------------------------------------------------------*/ - -/* USER CODE BEGIN PV */ - -/* USER CODE END PV */ - -/* Private function prototypes -----------------------------------------------*/ -/* USER CODE BEGIN PFP */ -#if (defined(YUNHORN_STS_O6_ENABLED) && defined(USE_ACCONEER_A111)) - -#endif - -/* USER CODE END PFP */ - -/* Exported functions --------------------------------------------------------*/ - -void STS_YunhornAuthenticationCode_Process(void) -{ - if (sts_ac_code[0] == 0x00) { - APP_LOG(TS_OFF,VLEVEL_H, "Initial AC CODE blank... \r\n"); - return; - } - - sts_service_mask = (sts_hmac_verify()!= 0)? STS_SERVICE_MASK_L2:STS_SERVICE_MASK_L0; - - if (sts_service_mask == STS_SERVICE_MASK_L2) { - sts_ac_code[0] = 0x0; - } - APP_LOG(TS_OFF, VLEVEL_H, "STS_SERVICE_MASK:%d \r\n",sts_service_mask); -} - -void STS_YunhornSTSEventRFAC_Process(void) -{ - if (sts_ac_code[0] ==0x0) - { - if ((rfac_timer >= STS_BURN_IN_RFAC) && (rfac_timer < (STS_BURN_IN_RFAC +3))) - { - APP_LOG(TS_OFF, VLEVEL_H, "\r\n -------------------RFAC Process\r\n"); - STS_SENSOR_Upload_Message(YUNHORN_STS_O6_USER_APP_CTRL_REPLY_PORT, 4, "RFAC"); - } - if ((rfac_timer > (STS_BURN_IN_RFAC + 2))) - { - APP_LOG(TS_OFF, VLEVEL_H, "\r\n -------------------Verify RFAC Success or Not\r\n"); - sts_service_mask = (sts_hmac_verify()!= 0)? STS_SERVICE_MASK_L2:STS_SERVICE_MASK_L0; - if (sts_service_mask == STS_SERVICE_MASK_L2) { - sts_ac_code[0] = 0x0; - } - } - } - -} - -void STS_FallDetection_LampBarProcess(void) -{ - uint8_t buf[32]={0x0}; - uint8_t i=0; - switch (sts_fall_rising_detected_result) - { - case STS_PRESENCE_LAYDOWN: - - break; - case STS_PRESENCE_FALL: - sts_lamp_bar_color = STS_BLUE; //STS_RED_BLUE; - sts_status_color = STS_BLUE; //STS_RED_BLUE; - sts_rss_result = STS_RESULT_MOTION; - STS_Lamp_Bar_Set_STS_RGB_Color(sts_lamp_bar_color, luminance_level); - - buf[i++] = (uint8_t)sts_lamp_bar_color; - buf[i++] = (uint8_t)sts_work_mode; - buf[i++] = (uint8_t)sts_fall_rising_detected_result; - - buf[i++] = (uint8_t)(sts_fall_rising_pattern_factor1/10 + 0x30)&0xFF; - buf[i++] = (uint8_t)(sts_fall_rising_pattern_factor1%10 + 0x30)&0xFF; - buf[i++] = (uint8_t)(sts_roc_acc_standard_variance/10 + 0x30)&0xFF; - buf[i++] = (uint8_t)(sts_roc_acc_standard_variance%10 + 0x30)&0xFF; - break; - - case STS_PRESENCE_RISING: - sts_lamp_bar_color = STS_RED; // normal occupancy status - sts_status_color = STS_RED; // normal occupancy status - sts_rss_result = STS_RESULT_MOTION; - STS_Lamp_Bar_Set_STS_RGB_Color(sts_lamp_bar_color, luminance_level); - buf[i++] = (uint8_t)sts_lamp_bar_color; - buf[i++] = (uint8_t)sts_work_mode; - buf[i++] = (uint8_t)sts_fall_rising_detected_result; - - // TESTING ONLY TO BE REMOVED - buf[i++] = (uint8_t)(sts_fall_rising_pattern_factor1/10 + 0x30)&0xFF; - buf[i++] = (uint8_t)(sts_fall_rising_pattern_factor1%10 + 0x30)&0xFF; - buf[i++] = (uint8_t)(sts_roc_acc_standard_variance/10 + 0x30)&0xFF; - buf[i++] = (uint8_t)(sts_roc_acc_standard_variance%10 + 0x30)&0xFF; - break; - - default: - break; - } - - APP_LOG(TS_OFF, VLEVEL_L, "\r\n <<<<<<<<<<<<<< Fall Rise state=%d, send buf size = %d \r\n", - sts_fall_rising_detected_result, i ) - - STS_SENSOR_Upload_Message((LORAWAN_USER_APP_PORT+2), i, (char*)buf); - - sts_fall_rising_detected_result = STS_PRESENCE_NONE; - -} - -void STS_YunhornSTSFallDetection(void) -{ - //APP_LOG(TS_OFF, VLEVEL_M, "\r\n YUNHORN STS FALL DETECTION \r\n"); - - //STS_YunhornCheckStandardDeviation(); - -} - -void STS_PRESENCE_SENSOR_NVM_CFG(void) -{ - sts_presence_rss_config.default_start_m = (float)((float)sts_cfg_nvm.p[RSS_CFG_START_M]*0.1f); - sts_presence_rss_config.default_length_m = (float)((float)sts_cfg_nvm.p[RSS_CFG_LENGTH_M]*0.1f); - sts_presence_rss_config.default_threshold = (float)((float)sts_cfg_nvm.p[RSS_CFG_THRESHOLD]*0.1f); - sts_presence_rss_config.default_receiver_gain = (float)((float)sts_cfg_nvm.p[RSS_CFG_RECEIVER_GAIN]*0.01f); - - sts_presence_rss_config.default_zone_length_m = DEFAULT_ZONE_LENGTH; - sts_presence_rss_config.default_profile = (float)(sts_cfg_nvm.p[RSS_CFG_PROFILE]); - sts_presence_rss_config.default_update_rate_tracking = (float)(sts_cfg_nvm.p[RSS_CFG_RATE_TRACKING]); - sts_presence_rss_config.default_update_rate_presence = (float)(sts_cfg_nvm.p[RSS_CFG_RATE_PRESENCE]); - sts_presence_rss_config.default_hwaas = (float)(sts_cfg_nvm.p[RSS_CFG_HWAAS]); - - sts_presence_rss_config.default_nbr_removed_pc = (float)(sts_cfg_nvm.p[RSS_CFG_NBR_REMOVED_PC]); - -//filter parameter - sts_presence_rss_config.default_inter_frame_deviation_time_const = (float)(sts_cfg_nvm.p[RSS_CFG_ITE_DEVIATION]*0.1f); - sts_presence_rss_config.default_inter_frame_fast_cutoff = (float)(sts_cfg_nvm.p[RSS_CFG_ITE_FAST_CUTOFF]); - sts_presence_rss_config.default_inter_frame_slow_cutoff = (float)(sts_cfg_nvm.p[RSS_CFG_ITE_SLOW_CUTOFF]*0.01f); - sts_presence_rss_config.default_intra_frame_time_const = (float)(sts_cfg_nvm.p[RSS_CFG_ITR_TIME]); - sts_presence_rss_config.default_intra_frame_weight = (float)(sts_cfg_nvm.p[RSS_CFG_ITR_WEIGHT]*0.1f); - sts_presence_rss_config.default_output_time_const = (float)(sts_cfg_nvm.p[RSS_CFG_OUTPUT_TIME]*0.1f); -//filter parameter - - sts_presence_rss_config.default_downsampling_factor = (float)(sts_cfg_nvm.p[RSS_CFG_DOWNSAMPLING_FACTOR]); - sts_presence_rss_config.default_power_save_mode = (float)(sts_cfg_nvm.p[RSS_CFG_POWER_MODE]); - - sts_rss_config_updated_flag = STS_RSS_CONFIG_FULL; //set to 2 for FULL config effect in next detection -} - -void STS_PRESENCE_SENSOR_NVM_CFG_SIMPLE(void) -{ - sts_presence_rss_config.default_start_m = (float)(sts_cfg_nvm.p[RSS_CFG_START_M]*0.1f); - sts_presence_rss_config.default_length_m = (float)(sts_cfg_nvm.p[RSS_CFG_LENGTH_M]*0.1f); - sts_presence_rss_config.default_threshold = (float)(sts_cfg_nvm.p[RSS_CFG_THRESHOLD]*0.1f); - sts_presence_rss_config.default_receiver_gain = (float)(sts_cfg_nvm.p[RSS_CFG_RECEIVER_GAIN]*0.01f); - - sts_rss_config_updated_flag = STS_RSS_CONFIG_SIMPLE; //set to 1 for simple config effect in next detection -} - -void STS_PRESENCE_SENSOR_Init_Send_Data(void) -{ - sts_o6_sensorData.lamp_bar_color = STS_GREEN; - sts_o6_sensorData.workmode = STS_DUAL_MODE; - - sts_o6_sensorData.state_sensor1_on_off = 0x0; - sts_o6_sensorData.state_sensor2_on_off = 0x0; - sts_o6_sensorData.state_sensor3_on_off = 0x0; - sts_o6_sensorData.state_sensor4_on_off = 0x0; - sts_o6_sensorData.rss_presence_distance = 0x0; - sts_o6_sensorData.rss_presence_score = 0x0; - sts_o6_sensorData.fall_state = STS_PRESENCE_NONE; - sts_o6_sensorData.fall_speed = 0x0; - sts_o6_sensorData.fall_gravity = 0x0; - sts_o6_sensorData.event_start_time = 0x0; - sts_o6_sensorData.event_stop_time = 0x0; - sts_o6_sensorData.overtime = 0x0; - - sts_o6_sensorData.battery_Pct = 99; // 99% as init value - sts_o6_sensorData.dutycycletimelevel = 1; - sensor_data_ready = 0; -} -void STS_PRESENCE_SENSOR_Prepare_Send_Data(void) -{ - sts_o6_sensorData.lamp_bar_color = sts_lamp_bar_color; - sts_o6_sensorData.workmode = sts_work_mode; - sts_o6_sensorData.state_sensor1_on_off = ((STS_Reed_Hall_State == STS_Status_Door_Open)? 0U:1U); - sts_o6_sensorData.state_sensor2_on_off = sts_rss_result; - sts_o6_sensorData.state_sensor3_on_off = sts_tof_result; - sts_o6_sensorData.state_sensor4_on_off = sts_rss_2nd_result; - if (sts_rss_result == STS_RESULT_MOTION) - { - sts_o6_sensorData.rss_presence_distance = (uint16_t)(sts_presence_rss_distance)&0xFFFF; - sts_o6_sensorData.rss_presence_score = (uint16_t)(sts_presence_rss_score)&0xFFFF; - } else { - sts_o6_sensorData.rss_presence_distance = 0x0; - sts_o6_sensorData.rss_presence_score = 0x0; - } - sts_o6_sensorData.fall_state = sts_fall_rising_detected_result; - if (sts_fall_rising_detected_result != STS_PRESENCE_NONE) - { - sts_o6_sensorData.fall_speed = (uint8_t)sts_fall_rising_pattern_factor1; - sts_o6_sensorData.fall_gravity = (uint8_t)sts_roc_acc_standard_variance; - } - - sts_o6_sensorData.overtime = (event_stop_time - event_start_time)> (sts_occupancy_overtime_threshold*60)? 1:0; - sts_o6_sensorData.event_start_time = event_start_time; - sts_o6_sensorData.event_stop_time = event_stop_time; -} - -void STS_PRESENCE_SENSOR_Read(STS_OO_SensorStatusDataTypeDef *o6_data) -{ - o6_data->lamp_bar_color = (uint8_t)sts_o6_sensorData.lamp_bar_color; - o6_data->workmode = (uint8_t)sts_o6_sensorData.workmode; - - o6_data->state_sensor1_on_off = (uint8_t)sts_o6_sensorData.state_sensor1_on_off; - o6_data->state_sensor2_on_off = (uint8_t)sts_o6_sensorData.state_sensor2_on_off; - o6_data->state_sensor3_on_off = (uint8_t)sts_o6_sensorData.state_sensor3_on_off; - o6_data->state_sensor4_on_off = (uint8_t)sts_o6_sensorData.state_sensor4_on_off; - o6_data->rss_presence_distance = (uint16_t)sts_o6_sensorData.rss_presence_distance; - o6_data->rss_presence_score = (uint16_t)sts_o6_sensorData.rss_presence_score; - o6_data->event_start_time = (uint32_t)sts_o6_sensorData.event_start_time; - o6_data->event_stop_time = (uint32_t)sts_o6_sensorData.event_stop_time; - o6_data->overtime = (uint8_t)sts_o6_sensorData.overtime; - - o6_data->battery_Pct = (uint8_t)sts_o6_sensorData.battery_Pct; - o6_data->dutycycletimelevel = (uint8_t)sts_o6_sensorData.dutycycletimelevel; - -} - -void STS_PRESENCE_SENSOR_GetValue(void) -{ - -} - -void STS_PRESENCE_SENSOR_WakeUp_Process_Sampling(void) -{ - if ((sensor_data_ready ==0)) { - STS_PRESENCE_SENSOR_GetValue(); - } -} - -void STS_PRESENCE_SENSOR_After_Wake_Up() -{ - -} - -/** - * @brief Initializes the motion sensors - * @param Instance Motion sensor instance - * @param Functions Motion sensor functions. Could be : - * - MOTION_ACCELERO for instance - * @retval BSP status - */ -void STS_PRESENCE_SENSOR_Init(void) -{ - APP_LOG(TS_ON, VLEVEL_M, "##### YunHorn SmarToilets(r) Presence Sensor Started\r\n"); - - sts_o6_sensorData.workmode = (uint8_t)STS_DUAL_MODE; - sts_o6_sensorData.lamp_bar_color = (uint8_t)STS_GREEN; - sts_o6_sensorData.battery_Pct = 99; - sts_o6_sensorData.dutycycletimelevel = 1; - sts_o6_sensorData.event_start_time = 0; - sts_o6_sensorData.event_stop_time = 0; - - STS_SENSOR_Power_ON(0); - STS_PRESENCE_SENSOR_REEDSWITCH_HALL_Init(); - STS_PRESENCE_SENSOR_TOF_Init(); - STS_PRESENCE_SENSOR_RSS_Init(); - - mems_int1_detected=0; -} - -void STS_PRESENCE_SENSOR_TOF_Init(void) -{ - APP_LOG(TS_ON, VLEVEL_H, "##### YunHorn SmarToilets(r) MEMS TOF Initializing \r\n"); - -} -void STS_PRESENCE_SENSOR_REEDSWITCH_HALL_Init(void) -{ - - APP_LOG(TS_ON, VLEVEL_H, "##### YunHorn SmarToilets(r) REED SWITCH HALL ELEMENT Initializing \r\n"); - -} -void STS_PRESENCE_SENSOR_RSS_Init(void) -{ - APP_LOG(TS_ON, VLEVEL_H, "##### YunHorn SmarToilets(r) MEMS RSS Initializing \r\n"); - - STS_SENSOR_Power_ON(0); - - STS_PRESENCE_SENSOR_NVM_CFG(); - - sts_rss_config_updated_flag = STS_RSS_CONFIG_DEFAULT; - - mems_int1_detected=0; - -} - -void STS_MOTION_SENSOR_ACT_INACT_DURATION_Init() -{ - -} - -void STS_PRESENCE_SENSOR_Get_Event_Status(STS_PRESENCE_SENSOR_Event_Status_t *Status) -{ - uint8_t int_source=0; - SysTime_t mems_event_time; - //int_source = ADXL345_GetRegisterValue(ADXL345_REG_INT_SOURCE); - - if (int_source & 0x10) { - mems_event_time = SysTimeGetMcuTime(); - Status->WakeUpStatus = 1U; - event_start_time = mems_event_time.Seconds; - } - else { - Status->WakeUpStatus =0U; - } - - if (int_source & 0x08) { - mems_event_time = SysTimeGetMcuTime(); - Status->SleepStatus = 1U; - event_stop_time = mems_event_time.Seconds; - } - else { - Status->SleepStatus = 0U; - - } - - -} - - -void STS_PRESENCE_SENSOR_Distance_Measure_Process(void) -{ - uint8_t exit_status = EXIT_SUCCESS, i=0; - - APP_LOG(TS_OFF, VLEVEL_H, "\r\n ****start_m=%u length_m=%u profile=%u hwaas=%u \r\n", - (unsigned int)(distance_cfg.start_m*1000),(unsigned int)(distance_cfg.length_m*1000), - (unsigned int)(distance_cfg.acc_profile),(unsigned int)(distance_cfg.hwaas)); - do - { - exit_status = sts_distance_rss_detector_distance(); - HAL_Delay(100); - i++; - } while ((exit_status == EXIT_FAILURE) && (i < 1)); - -} - -void STS_PRESENCE_SENSOR_Function_Test_Process(uint8_t *self_test_result, uint8_t count) -{ - uint8_t bring_up_result[20]; - STS_SENSOR_Power_ON(0); - HAL_Init(); - MX_GPIO_Init(); - HAL_Delay(150); //wait for sensor ready - - for (uint8_t i=0;i < count; i++) //while(1) - { - STS_Lamp_Bar_Self_Test_Simple(); - - sts_presence_rss_bring_up_test(bring_up_result); - - HAL_Delay(5000); - - STS_PRESENCE_SENSOR_Distance_Measure_Process(); - - } - - memcpy(self_test_result,bring_up_result, 10); - mems_int1_detected=0; -} - - -void STS_PRESENCE_SENSOR_Enable_Wake_Up_Detection() -{ - -} - -void STS_PRESENCE_SENSOR_Disable_Wake_Up_Detection(void) -{ - -} - -uint8_t STS_SENSOR_MEMS_Get_ID(uint8_t *devID) -{ - uint8_t scanned_id[2] = {0x0,0x0}; - -#ifdef YUNHORN_STS_O6_ENABLED - if (hal_test_spi_read_chipid(scanned_id)) - { - devID[0] = scanned_id[0]; - devID[1] = scanned_id[1]; - return true; - } - else - { - return false; - } -#endif - -} -/* -uint16_t STS_RSS_A111_GetDeviceIDValue(void) -{ - uint16_t devid=0; - if (STS_SENSOR_MEMS_Get_ID(&devid)) - { - return (uint16_t)devid; - } else return 0; -} -*/ -void STS_SENSOR_Power_ON(uint8_t cnt) -{ - switch (cnt) { - case 0: - case 1: - case 2: -#ifdef YUNHORN_STS_M7_ENABLED - HAL_GPIO_WritePin(MEMS_POWER_GPIO_Port, MEMS_POWER_Pin, GPIO_PIN_SET); -#endif -#ifdef YUNHORN_STS_O6_ENABLED - HAL_GPIO_WritePin(MEMS_POWER_GPIO_Port, MEMS_POWER_Pin, GPIO_PIN_SET); -#endif - break; - default: - break; - } - -} -void STS_SENSOR_Power_OFF(uint8_t cnt) -{ - switch (cnt) { - case 0: - case 1: - case 2: -#ifdef YUNHORN_STS_M7_ENABLED - HAL_GPIO_WritePin(MEMS_POWER_GPIO_Port, MEMS_POWER_Pin, GPIO_PIN_RESET); -#endif -#ifdef YUNHORN_STS_O6_ENABLED - HAL_GPIO_WritePin(MEMS_POWER_GPIO_Port, MEMS_POWER_Pin, GPIO_PIN_RESET); -#endif - break; - default: - break; - } -} - -void STS_SENSOR_MEMS_Reset(uint8_t cnt) -{ - switch (cnt) { - case 0: - case 1: - case 2: -#ifdef YUNHORN_STS_M7_ENABLED - HAL_GPIO_WritePin(MEMS_RESET_GPIO_Port, MEMS_RESET_Pin, GPIO_PIN_SET); -#endif -#ifdef YUNHORN_STS_O6_ENABLED - HAL_GPIO_WritePin(MEMS_RESET_GPIO_Port, MEMS_RESET_Pin, GPIO_PIN_RESET); - HAL_Delay(100); - HAL_GPIO_WritePin(MEMS_RESET_GPIO_Port, MEMS_RESET_Pin, GPIO_PIN_SET); -#endif - break; - default: - break; - } - -} - - -/* USER CODE BEGIN EF */ - -/* USER CODE END EF */ - -/* Private Functions Definition -----------------------------------------------*/ -/* USER CODE BEGIN PrFD */ - -/* USER CODE END PrFD */ diff --git a/STM32CubeIDE/.project b/STM32CubeIDE/.project index d8cf060..20b6e4f 100644 --- a/STM32CubeIDE/.project +++ b/STM32CubeIDE/.project @@ -447,6 +447,11 @@ 1 copy_PARENT/Core/Src/gpio.c + + Application/User/Core/i2c.c + 1 + copy_PARENT/Core/Src/i2c.c + Application/User/Core/main.c 1 diff --git a/TOF/App/Example_1_basic_ranging.c b/TOF/App/Example_1_basic_ranging.c new file mode 100644 index 0000000..b8b19e2 --- /dev/null +++ b/TOF/App/Example_1_basic_ranging.c @@ -0,0 +1,223 @@ +/* + Copyright (c) 2021, STMicroelectronics - All Rights Reserved + + This file : part of VL53L1X ULP and : dual licensed, + either 'STMicroelectronics + Proprietary license' + or 'BSD 3-clause "New" or "Revised" License' , at your option. + +******************************************************************************* + + 'STMicroelectronics Proprietary license' + +******************************************************************************* + + License terms: STMicroelectronics Proprietary in accordance with licensing + terms at www.st.com/sla0081 + + STMicroelectronics confidential + Reproduction and Communication of this document : strictly prohibited unless + specifically authorized in writing by STMicroelectronics. + + +******************************************************************************* + + Alternatively, VL53L1X ULP may be distributed under the terms of + 'BSD 3-clause "New" or "Revised" License', in which case the following + provisions apply instead of the ones mentioned above : + +******************************************************************************* + + License terms: BSD 3-clause "New" or "Revised" License. + + 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. +******************************************************************************* +*/ + +/****************************************/ +/* VL53L1X Low Power basic ranging */ +/****************************************/ + +/* +* This example shows how to use the VL53L1X Ultra Low Power driver in a very +* simple example. It initializes the VL53L1X driver, configure the sensor and +* starts a ranging to capture 200 frames. +*/ + +#include +#include +#include +#include "sys_app.h" + +#include "VL53L1X_ULP_api.h" +extern uint8_t ToF_EventDetected; +/* +uint8_t IsInterruptDetected(uint16_t dev) +{ + // To be filled with customer HW. This function should + // return 1 when an interrupt is raised by the ToF on GPIO1 pin (pin7) + if (ToF_EventDetected ) + { + APP_LOG(TS_OFF, VLEVEL_L,"############### TOF EVENT DETECTED \r\n"); + ToF_EventDetected =0; + return 1; + } else { + return 0; + } +} +*/ +int Example_1_basic_ranging(void) +{ /* + int sts_vl53lx_ranging(uint8_t vl_model, uint8_t range_mode, + uint16_t distance_threshold_mm, uint16_t inter_measurement_ms, uint16_t macro_timing, + uint16_t roi_width, uint16_t sigma_mm, uint16_t signal_kcps, uint16_t i_ambient_kcps); + */ + + /*********************************/ + /* VL53L1X ranging variables */ + /*********************************/ + + uint8_t status, loop; + uint8_t dev; + uint16_t sensor_id; + + uint8_t measurement_status; + uint16_t estimated_distance_mm, signal_kcps, sigma_mm, ambient_kcps; + + /*********************************/ + /* Customer platform */ + /*********************************/ + + /* Default VL53L1X Ultra Low Power I2C address */ + dev = 0x52; + + /* (Optional) Change I2C address */ + // status = VL53L1X_ULP_SetI2CAddress(dev, 0x52); //0x20 + + // dev = 0x20; + + + /*********************************/ + /* Power on sensor and init */ + /*********************************/ + + /* (Optional) Check if there is a VL53L1X sensor connected */ + status = VL53L1X_ULP_GetSensorId(dev, &sensor_id); + APP_LOG(TS_OFF,VLEVEL_L,"VL53L1X address =%X\r\n",sensor_id ); + if(status || (sensor_id != 0xEACC)) + { + APP_LOG(TS_OFF,VLEVEL_L,"VL53L1X not detected at requested address\n"); + return status; + } + + /* (Mandatory) Init VL53L1X sensor */ + status = VL53L1X_ULP_SensorInit(dev); + if(status) + { + APP_LOG(TS_OFF,VLEVEL_L,"VL53L1X ultra low power Loading failed\n"); + //HAL_Delay(100); + return status; + } + + APP_LOG(TS_OFF,VLEVEL_L,"VL53L1X ultra low power ready ! \r\n"); + + /*********************************/ + /* Sensor configuration */ + /*********************************/ + + /* (Optional) Program sensor to raise an interrupt ONLY below 300mm */ + status = VL53L1X_ULP_SetInterruptConfiguration(dev, 800, 1); //i_distance_threshold_mm + + /* (Optional) Program a 10Hz ranging frequency */ + status = VL53L1X_ULP_SetInterMeasurementInMs(dev, 100); // range_interval_ms + + { + /* Increase the macro timing. This is equivalent as increasing the integration time */ + status = VL53L1X_ULP_SetMacroTiming(dev, 100); // micro_timing_ms + + /* Enable all the SPADS */ + status = VL53L1X_ULP_SetROI(dev, 16); // SPADS { 1 -- 16 } + + + // STS---001 for ultra low power + /* Reduce the macro timing to minimum. This is equivalent as reducing the integration time */ + //status = VL53L1X_ULP_SetMacroTiming(dev, 1); + /* Reduce at maximum the SPADS */ + //status = VL53L1X_ULP_SetROI(dev, 4); + + + // STS ---002 for short distance + /* Example for robust and short distance measurements. Max distance reduced + * but very low number of false-positives */ + status |= VL53L1X_ULP_SetSigmaThreshold(dev, 30); + status |= VL53L1X_ULP_SetSignalThreshold(dev, 2000); + + // STS --- 003 for long range + /* Relax some limits. Be careful, it can create false-positives !*/ + //status |= VL53L1X_ULP_SetSigmaThreshold(dev, 60); + //status |= VL53L1X_ULP_SetSignalThreshold(dev, 1200); + } + + + /*********************************/ + /* Ranging loop */ + /*********************************/ + + status = VL53L1X_ULP_StartRanging(dev); + if(status) + { + APP_LOG(TS_OFF,VLEVEL_L,"VL53L1X_ULP_StartRanging failed with status %u\n", status); + return status; + } + + APP_LOG(TS_OFF,VLEVEL_L,"Ranging started. Put your hand close to the sensor to generate an interrupt...\n"); + + loop = 0; + while(loop < 20) + { + /* Use this external function to detect when a hardware interrupt is + * generated on PIN 7 (GPIO1). It means that a new measurement is ready. + */ + + //if(IsInterruptDetected(dev)) + { + /* (Mandatory) Clear HW interrupt to restart measurements */ + VL53L1X_ULP_ClearInterrupt(dev); + + /* Dump debug data */ + status = VL53L1X_ULP_DumpDebugData(dev, &measurement_status, + &estimated_distance_mm, &sigma_mm, &signal_kcps, &ambient_kcps); + + APP_LOG(TS_OFF,VLEVEL_L,"Target detected! Interrupt raised by sensor, Distance =%d mm \r\n", estimated_distance_mm ); + + loop++; + } + } + + status = VL53L1X_ULP_StopRanging(dev); + APP_LOG(TS_OFF,VLEVEL_L,"End of VL53L1X ultra low power demo\n"); + return status; +} diff --git a/TOF/App/Example_2_tune_sensor_with_debug_data.c b/TOF/App/Example_2_tune_sensor_with_debug_data.c new file mode 100644 index 0000000..e8b5b25 --- /dev/null +++ b/TOF/App/Example_2_tune_sensor_with_debug_data.c @@ -0,0 +1,217 @@ +/* + Copyright (c) 2021, STMicroelectronics - All Rights Reserved + + This file : part of VL53L1X ULP and : dual licensed, + either 'STMicroelectronics + Proprietary license' + or 'BSD 3-clause "New" or "Revised" License' , at your option. + +******************************************************************************* + + 'STMicroelectronics Proprietary license' + +******************************************************************************* + + License terms: STMicroelectronics Proprietary in accordance with licensing + terms at www.st.com/sla0081 + + STMicroelectronics confidential + Reproduction and Communication of this document : strictly prohibited unless + specifically authorized in writing by STMicroelectronics. + + +******************************************************************************* + + Alternatively, VL53L1X ULP may be distributed under the terms of + 'BSD 3-clause "New" or "Revised" License', in which case the following + provisions apply instead of the ones mentioned above : + +******************************************************************************* + + License terms: BSD 3-clause "New" or "Revised" License. + + 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. +******************************************************************************* +*/ + +/****************************************/ +/* VL53L1X Low Power tune sensor */ +/****************************************/ + +/* +* This example shows how to tune the VL53L1X Low power for a specific +* application, playing with sigma and signal threshold. +* It initializes the VL53L1X driver, configure the sensor and +* starts a ranging to capture 200 frames. +*/ + +#include +#include +#include + +#include "../../STM32CubeIDE/Drivers/BSP/vl53l1x_uld/VL53L1X_ULP_api.h" + +uint8_t IsInterruptDetected(uint16_t dev) +{ + // To be filled with customer HW. This function should + // return 1 when an interrupt is raised by the ToF on GPIO1 pin (pin7) +} + +uint8_t Example_2_tune_sensor_with_debug_data(void) +{ + + /*********************************/ + /* VL53L1X ranging variables */ + /*********************************/ + + uint8_t status, loop; + uint8_t dev; + uint16_t sensor_id; + + uint8_t measurement_status; + uint16_t estimated_distance_mm, signal_kcps, sigma_mm, ambient_kcps; + + + /*********************************/ + /* Customer platform */ + /*********************************/ + + /* Default VL53L1X Ultra Low Power I2C address */ + dev = 0x52; + + /* (Optional) Change I2C address */ + // status = VL53L1X_ULP_SetI2CAddress(dev, 0x20); + // dev = 0x20; + + + /*********************************/ + /* Power on sensor and init */ + /*********************************/ + + /* (Optional) Check if there is a VL53L1X sensor connected */ + status = VL53L1X_ULP_GetSensorId(dev, &sensor_id); + if(status || (sensor_id != 0xEACC)) + { + printf("VL53L1X not detected at requested address\n"); + return status; + } + + /* (Mandatory) Init VL53L1X sensor */ + status = VL53L1X_ULP_SensorInit(dev); + if(status) + { + printf("VL53L1X ultra low power Loading failed\n"); + return status; + } + + printf("VL53L1X ultra low power ready !\n"); + + /*********************************/ + /* Sensor tuning */ + /*********************************/ + + /* Here we will change some settings to tune the sensor valid measurements. + * The sensor can output 2 thresholds used to define a valid distance : + * - Sigma threshold. This is the estimated standard deviation of the + * measurement. A low value means that the accuracy is good. Reducing + * this threshold reduces the max ranging distance, but it reduces the + * number of false-positives. + * + * - Signal threshold. This is the quantity of photons measured by the + * sensor. A high value means that the accuracy is good. Increasing + * this threshold reduces the max ranging distance, but it reduces the + * number of false-positives. + */ + + /* Example for robust and short distance measurements. Max distance reduced + * but very low number of false-positives */ + status |= VL53L1X_ULP_SetSigmaThreshold(dev, 30); + status |= VL53L1X_ULP_SetSignalThreshold(dev, 2000); + + + /* Example for longer distance measurements. Max distance increased + * but false-positives may appear */ + // status |= VL53L1X_ULP_SetSigmaThreshold(dev, 60); + // status |= VL53L1X_ULP_SetSignalThreshold(dev, 1200); + + + /*********************************/ + /* Sensor configuration */ + /*********************************/ + + /* (Optional) Program sensor to output interrupt when a new measurement is + * ready, even if the distance is not valid */ + status = VL53L1X_ULP_SetInterruptConfiguration(dev, 0, 0); + + /* (Optional) Program a 10Hz ranging frequency */ + status = VL53L1X_ULP_SetInterMeasurementInMs(dev, 100); + + + /*********************************/ + /* Ranging loop */ + /*********************************/ + + status = VL53L1X_ULP_StartRanging(dev); + if(status) + { + printf("VL53L1X_ULP_StartRanging failed with status %u\n", status); + return status; + } + + printf("Ranging started. Put your hand close to the sensor to generate an interrupt...\n"); + + loop = 0; + while(loop < 200) + { + /* Use this external function to detect when a hardware interrupt is + * generated on PIN 7 (GPIO1). It means that a new measurement is ready. + */ + + if(IsInterruptDetected(dev)) + { + /* (Mandatory) Clear HW interrupt to restart measurements */ + VL53L1X_ULP_ClearInterrupt(dev); + + /* Dump debug data */ + status = VL53L1X_ULP_DumpDebugData(dev, &measurement_status, + &estimated_distance_mm, &sigma_mm, &signal_kcps, &ambient_kcps); + + /* Print debug data. Measurement status 0 means that a valid target + * has been detected */ + printf("DEBUG DATA : Status = %2u, Estimated distance = %4u mm, Signal = %6u kcps, Sigma = %3u mm\n", + measurement_status, + estimated_distance_mm, + signal_kcps, + sigma_mm); + + loop++; + } + } + + status = VL53L1X_ULP_StopRanging(dev); + printf("End of VL53L1X ultra low power demo\n"); + return status; +} diff --git a/TOF/App/Example_3_long_ranging.c b/TOF/App/Example_3_long_ranging.c new file mode 100644 index 0000000..571f941 --- /dev/null +++ b/TOF/App/Example_3_long_ranging.c @@ -0,0 +1,185 @@ +/* + Copyright (c) 2021, STMicroelectronics - All Rights Reserved + + This file : part of VL53L1X ULP and : dual licensed, + either 'STMicroelectronics + Proprietary license' + or 'BSD 3-clause "New" or "Revised" License' , at your option. + +******************************************************************************* + + 'STMicroelectronics Proprietary license' + +******************************************************************************* + + License terms: STMicroelectronics Proprietary in accordance with licensing + terms at www.st.com/sla0081 + + STMicroelectronics confidential + Reproduction and Communication of this document : strictly prohibited unless + specifically authorized in writing by STMicroelectronics. + + +******************************************************************************* + + Alternatively, VL53L1X ULP may be distributed under the terms of + 'BSD 3-clause "New" or "Revised" License', in which case the following + provisions apply instead of the ones mentioned above : + +******************************************************************************* + + License terms: BSD 3-clause "New" or "Revised" License. + + 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. +******************************************************************************* +*/ + +/****************************************/ +/* VL53L1X Low Power basic ranging */ +/****************************************/ + +/* +* This example shows how to use the VL53L1X Ultra Low Power driver for +* detecting a user at long distance (>60cm). Please note that the proposed +* configuration also increase the power consumption. +* The example initializes the VL53L1X driver, configure the sensor and +* starts a ranging to capture 200 frames. +*/ + +#include +#include +#include + +#include "../../STM32CubeIDE/Drivers/BSP/vl53l1x_uld/VL53L1X_ULP_api.h" + +uint8_t IsInterruptDetected(uint16_t dev) +{ + // To be filled with customer HW. This function should + // return 1 when an interrupt is raised by the ToF on GPIO1 pin (pin7) +} + +uint8_t Example_3_long_ranging(void) +{ + + /*********************************/ + /* VL53L1X ranging variables */ + /*********************************/ + + uint8_t status, loop; + uint8_t dev; + uint16_t sensor_id; + + + /*********************************/ + /* Customer platform */ + /*********************************/ + + /* Default VL53L1X Ultra Low Power I2C address */ + dev = 0x52; + + /* (Optional) Change I2C address */ + // status = VL53L1X_ULP_SetI2CAddress(dev, 0x20); + // dev = 0x20; + + + /*********************************/ + /* Power on sensor and init */ + /*********************************/ + + /* (Optional) Check if there is a VL53L1X sensor connected */ + status = VL53L1X_ULP_GetSensorId(dev, &sensor_id); + if(status || (sensor_id != 0xEACC)) + { + printf("VL53L1X not detected at requested address\n"); + return status; + } + + /* (Mandatory) Init VL53L1X sensor */ + status = VL53L1X_ULP_SensorInit(dev); + if(status) + { + printf("VL53L1X ultra low power Loading failed\n"); + return status; + } + + printf("VL53L1X ultra low power ready !\n"); + + /*********************************/ + /* Sensor configuration */ + /*********************************/ + + /* (Optional) Program sensor to raise an interrupt ONLY below 600mm */ + status = VL53L1X_ULP_SetInterruptConfiguration(dev, 600, 1); + + /* (Optional) Program a 10Hz ranging frequency */ + status = VL53L1X_ULP_SetInterMeasurementInMs(dev, 100); + + /* Increase the macro timing. This is equivalent as increasing the integration time */ + status = VL53L1X_ULP_SetMacroTiming(dev, 100); + + /* Enable all the SPADS */ + status = VL53L1X_ULP_SetROI(dev, 16); + + /* Relax some limits. Be careful, it can create false-positives !*/ + status |= VL53L1X_ULP_SetSigmaThreshold(dev, 60); + status |= VL53L1X_ULP_SetSignalThreshold(dev, 1200); + + + /*********************************/ + /* Ranging loop */ + /*********************************/ + + status = VL53L1X_ULP_StartRanging(dev); + if(status) + { + printf("VL53L1X_ULP_StartRanging failed with status %u\n", status); + return status; + } + + printf("Ranging started. Put your hand close to the sensor to generate an interrupt...\n"); + + loop = 0; + while(loop < 200) + { + /* Use this external function to detect when a hardware interrupt is + * generated on PIN 7 (GPIO1). It means that a new measurement is ready. + */ + + if(IsInterruptDetected(dev)) + { + /* (Mandatory) Clear HW interrupt to restart measurements */ + VL53L1X_ULP_ClearInterrupt(dev); + + printf("Target detected! Interrupt raised by sensor\n"); + + loop++; + } + } + + status = VL53L1X_ULP_StopRanging(dev); + printf("End of VL53L1X ultra low power demo\n"); + return status; +} diff --git a/TOF/App/Example_4_ultra_low_power.c b/TOF/App/Example_4_ultra_low_power.c new file mode 100644 index 0000000..436b602 --- /dev/null +++ b/TOF/App/Example_4_ultra_low_power.c @@ -0,0 +1,180 @@ +/* + Copyright (c) 2021, STMicroelectronics - All Rights Reserved + + This file : part of VL53L1X ULP and : dual licensed, + either 'STMicroelectronics + Proprietary license' + or 'BSD 3-clause "New" or "Revised" License' , at your option. + +******************************************************************************* + + 'STMicroelectronics Proprietary license' + +******************************************************************************* + + License terms: STMicroelectronics Proprietary in accordance with licensing + terms at www.st.com/sla0081 + + STMicroelectronics confidential + Reproduction and Communication of this document : strictly prohibited unless + specifically authorized in writing by STMicroelectronics. + + +******************************************************************************* + + Alternatively, VL53L1X ULP may be distributed under the terms of + 'BSD 3-clause "New" or "Revised" License', in which case the following + provisions apply instead of the ones mentioned above : + +******************************************************************************* + + License terms: BSD 3-clause "New" or "Revised" License. + + 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. +******************************************************************************* +*/ + +/****************************************/ +/* VL53L1X Low Power basic ranging */ +/****************************************/ + +/* +* This example shows how to use the VL53L1X Ultra Low Power driver with the +* lowest possible power consumption. +* The example initializes the VL53L1X driver, configure the sensor and +* starts a ranging to capture 200 frames. +*/ + +#include +#include +#include + +#include "../../STM32CubeIDE/Drivers/BSP/vl53l1x_uld/VL53L1X_ULP_api.h" + +uint8_t IsInterruptDetected(uint16_t dev) +{ + // To be filled with customer HW. This function should + // return 1 when an interrupt is raised by the ToF on GPIO1 pin (pin7) +} + +uint8_t Example_4_ultra_low_power(void) +{ + + /*********************************/ + /* VL53L1X ranging variables */ + /*********************************/ + + uint8_t status, loop; + uint8_t dev; + uint16_t sensor_id; + + + /*********************************/ + /* Customer platform */ + /*********************************/ + + /* Default VL53L1X Ultra Low Power I2C address */ + dev = 0x52; + + /* (Optional) Change I2C address */ + // status = VL53L1X_ULP_SetI2CAddress(dev, 0x20); + // dev = 0x20; + + + /*********************************/ + /* Power on sensor and init */ + /*********************************/ + + /* (Optional) Check if there is a VL53L1X sensor connected */ + status = VL53L1X_ULP_GetSensorId(dev, &sensor_id); + if(status || (sensor_id != 0xEACC)) + { + printf("VL53L1X not detected at requested address\n"); + return status; + } + + /* (Mandatory) Init VL53L1X sensor */ + status = VL53L1X_ULP_SensorInit(dev); + if(status) + { + printf("VL53L1X ultra low power Loading failed\n"); + return status; + } + + printf("VL53L1X ultra low power ready !\n"); + + /*********************************/ + /* Sensor configuration */ + /*********************************/ + + /* (Optional) Program sensor to raise an interrupt ONLY below 300mm */ + status = VL53L1X_ULP_SetInterruptConfiguration(dev, 300, 1); + + /* (Optional) Program a 10Hz ranging frequency */ + status = VL53L1X_ULP_SetInterMeasurementInMs(dev, 100); + + /* Reduce the macro timing to minimum. This is equivalent as reducing the integration time */ + status = VL53L1X_ULP_SetMacroTiming(dev, 1); + + /* Reduce at maximum the SPADS */ + status = VL53L1X_ULP_SetROI(dev, 4); + + + /*********************************/ + /* Ranging loop */ + /*********************************/ + + status = VL53L1X_ULP_StartRanging(dev); + if(status) + { + printf("VL53L1X_ULP_StartRanging failed with status %u\n", status); + return status; + } + + printf("Ranging started. Put your hand close to the sensor to generate an interrupt...\n"); + + loop = 0; + while(loop < 200) + { + /* Use this external function to detect when a hardware interrupt is + * generated on PIN 7 (GPIO1). It means that a new measurement is ready. + */ + + if(IsInterruptDetected(dev)) + { + /* (Mandatory) Clear HW interrupt to restart measurements */ + VL53L1X_ULP_ClearInterrupt(dev); + + printf("Target detected! Interrupt raised by sensor\n"); + + loop++; + } + } + + status = VL53L1X_ULP_StopRanging(dev); + printf("End of VL53L1X ultra low power demo\n"); + return status; +} diff --git a/TOF/App/app_tof.c b/TOF/App/app_tof.c new file mode 100644 index 0000000..2ebb44e --- /dev/null +++ b/TOF/App/app_tof.c @@ -0,0 +1,188 @@ +/** + ****************************************************************************** + * @file : app_tof.c + * @author : IMG SW Application Team + * @brief : This file provides code for the configuration + * of the STMicroelectronics.X-CUBE-TOF1.3.2.0 instances. + ****************************************************************************** + * + * @attention + * + * Copyright (c) 2022 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. + * + ****************************************************************************** + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "app_tof.h" +#include "main.h" +#include + +#include "53l1a2_ranging_sensor.h" +#include "stm32wlxx_nucleo.h" + +/* Private typedef -----------------------------------------------------------*/ + +/* Private define ------------------------------------------------------------*/ +#define TIMING_BUDGET (30U) /* 16 ms < TimingBudget < 500 ms */ +#define POLLING_PERIOD (250U) /* refresh rate for polling mode (milliseconds, shall be consistent with TimingBudget value) */ + +/* Private variables ---------------------------------------------------------*/ +static RANGING_SENSOR_Capabilities_t Cap; +static RANGING_SENSOR_ProfileConfig_t Profile; +static int32_t status = 0; +static volatile uint8_t PushButtonDetected = 0; +volatile uint8_t ToF_EventDetected = 0; + +/* Private function prototypes -----------------------------------------------*/ +static void MX_53L1A2_SimpleRanging_Init(void); +static void MX_53L1A2_SimpleRanging_Process(void); +static void print_result(RANGING_SENSOR_Result_t *Result); +static int32_t decimal_part(float_t x); + +void MX_TOF_Init(void) +{ + /* USER CODE BEGIN SV */ + + /* USER CODE END SV */ + + /* USER CODE BEGIN TOF_Init_PreTreatment */ + + /* USER CODE END TOF_Init_PreTreatment */ + + /* Initialize the peripherals and the TOF components */ + + MX_53L1A2_SimpleRanging_Init(); + + /* USER CODE BEGIN TOF_Init_PostTreatment */ + + /* USER CODE END TOF_Init_PostTreatment */ +} + +/* + * LM background task + */ +void MX_TOF_Process(void) +{ + /* USER CODE BEGIN TOF_Process_PreTreatment */ + + /* USER CODE END TOF_Process_PreTreatment */ + + MX_53L1A2_SimpleRanging_Process(); + + /* USER CODE BEGIN TOF_Process_PostTreatment */ + + /* USER CODE END TOF_Process_PostTreatment */ +} + +static void MX_53L1A2_SimpleRanging_Init(void) +{ + /* Initialize Virtual COM Port */ + BSP_COM_Init(COM1); + + /* Initialize button */ + BSP_PB_Init(BUTTON_KEY, BUTTON_MODE_EXTI); + + printf("53L1A2 Simple Ranging demo application\n"); + status = VL53L1A2_RANGING_SENSOR_Init(VL53L1A2_DEV_CENTER); + + if (status != BSP_ERROR_NONE) + { + printf("VL53L1A2_RANGING_SENSOR_Init failed\n"); + while(1); + } +} + +static void MX_53L1A2_SimpleRanging_Process(void) +{ + uint32_t Id; + + RANGING_SENSOR_Result_t Result; + + VL53L1A2_RANGING_SENSOR_ReadID(VL53L1A2_DEV_CENTER, &Id); + VL53L1A2_RANGING_SENSOR_GetCapabilities(VL53L1A2_DEV_CENTER, &Cap); + + Profile.RangingProfile = RS_MULTI_TARGET_MEDIUM_RANGE; + Profile.TimingBudget = TIMING_BUDGET; /* 16 ms < TimingBudget < 500 ms */ + Profile.Frequency = 0; /* Induces intermeasurement period, set to ZERO for normal ranging */ + Profile.EnableAmbient = 1; /* Enable: 1, Disable: 0 */ + Profile.EnableSignal = 1; /* Enable: 1, Disable: 0 */ + + /* set the profile if different from default one */ + VL53L1A2_RANGING_SENSOR_ConfigProfile(VL53L1A2_DEV_CENTER, &Profile); + + status = VL53L1A2_RANGING_SENSOR_Start(VL53L1A2_DEV_CENTER, RS_MODE_BLOCKING_CONTINUOUS); + + if (status != BSP_ERROR_NONE) + { + printf("VL53L1A2_RANGING_SENSOR_Start failed\n"); + while(1); + } + + while (1) + { + /* polling mode */ + status = VL53L1A2_RANGING_SENSOR_GetDistance(VL53L1A2_DEV_CENTER, &Result); + + if (status == BSP_ERROR_NONE) + { + print_result(&Result); + } + + HAL_Delay(POLLING_PERIOD); + } +} + +static void print_result(RANGING_SENSOR_Result_t *Result) +{ + uint8_t i, j; + + for (i = 0; i < RANGING_SENSOR_MAX_NB_ZONES; i++) + { + printf("\nTargets = %lu", (unsigned long)Result->ZoneResult[i].NumberOfTargets); + + for (j = 0; j < Result->ZoneResult[i].NumberOfTargets; j++) + { + printf("\n |---> "); + + printf("Status = %ld, Distance = %5ld mm ", + (long)Result->ZoneResult[i].Status[j], + (long)Result->ZoneResult[i].Distance[j]); + + if (Profile.EnableAmbient) + printf(", Ambient = %ld.%02ld kcps/spad", + (long)Result->ZoneResult[i].Ambient[j], + (long)decimal_part(Result->ZoneResult[i].Ambient[j])); + + if (Profile.EnableSignal) + printf(", Signal = %ld.%02ld kcps/spad", + (long)Result->ZoneResult[i].Signal[j], + (long)decimal_part(Result->ZoneResult[i].Signal[j])); + } + } + printf ("\n"); +} + +static int32_t decimal_part(float_t x) +{ + int32_t int_part = (int32_t) x; + return (int32_t)((x - int_part) * 100); +} + +void BSP_PB_Callback(Button_TypeDef Button) +{ + PushButtonDetected = 1; +} + +#ifdef __cplusplus +} +#endif diff --git a/TOF/App/app_tof.h b/TOF/App/app_tof.h new file mode 100644 index 0000000..328c4ff --- /dev/null +++ b/TOF/App/app_tof.h @@ -0,0 +1,41 @@ +/** + ****************************************************************************** + * @file : app_tof.h + * @author : IMG SW Application Team + * @brief : This file provides code for the configuration + * of the STMicroelectronics.X-CUBE-TOF1.3.2.0 instances. + ****************************************************************************** + * + * @attention + * + * Copyright (c) 2022 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 __APP_TOF_H +#define __APP_TOF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ + +/* Exported defines ----------------------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +void MX_TOF_Init(void); +void MX_TOF_Process(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __APP_TOF_H */ diff --git a/TOF/App/app_tof_peoplecount.c b/TOF/App/app_tof_peoplecount.c new file mode 100644 index 0000000..39bb543 --- /dev/null +++ b/TOF/App/app_tof_peoplecount.c @@ -0,0 +1,442 @@ + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" +#include "sys_app.h" +/* USER CODE BEGIN Includes */ +#include "app_tof_peoplecount.h" +#include "VL53L1X_API.h" +#include "VL53l1X_calibration.h" +#include "X-NUCLEO-53L1A1.h" +#include "app_tof.h" +/* USER CODE END Includes */ +/* Private variables ---------------------------------------------------------*/ +/* USER CODE BEGIN PV */ +/* Private variables ---------------------------------------------------------*/ +extern I2C_HandleTypeDef hi2c2; +volatile sts_people_count_sensor_data_t sts_people_count_sensor_data={0,0,0,2,'M',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + +volatile sts_ppc_cfg_type_t ppc_cfg[3] = { + {DOOR_JAM_2000, 8, 2000,0,1600,8,33,DISTANCE_MODE_SHORT,175,247}, + {DOOR_JAM_2000, 8, 2000,0,1600,8,33,DISTANCE_MODE_SHORT,175,247}, + {DOOR_JAM_2400, 10, 2400,0,1600,8,33,DISTANCE_MODE_LONG,175,231}, +}; +volatile sts_zone_center_by_rows_of_spads_t zone_center[3]={ + {4, 151, 247}, + {6, 159, 239}, + {8, 175, 231}, +}; +volatile uint8_t sts_distance_mode = DISTANCE_MODE_LONG; +volatile uint8_t sts_people_count_number_changed = 0; +uint16_t dev=0x52; +int status = 0; +volatile int IntCount; +#define isInterrupt 1 /* If isInterrupt = 1 then device working in interrupt mode, else device working in polling mode */ +/* USER CODE END PV */ +static int PplCounter; +static int center[2] = {FRONT_ZONE_CENTER,BACK_ZONE_CENTER}; //{ppc_cfg[sts_distance_mode].front_zone_center, ppc_cfg[sts_distance_mode].back_zone_center}; /* these are the spad center of the 2 4*16 zones */ +static int Zone = 0; +static int PathTrack[] = {0,0,0,0}; +static int PathTrackFillingSize = 1; // init this to 1 as we start from state where nobody is any of the zones +static int LeftPreviousStatus = NOBODY; +static int RightPreviousStatus = NOBODY; +static int PeopleCount = 0; +static uint16_t Distances[2][DISTANCES_ARRAY_SIZE]; +static uint8_t DistancesTableSize[2] = {0,0}; + +/* Private function prototypes -----------------------------------------------*/ +/* USER CODE BEGIN PFP */ +/* Private function prototypes -----------------------------------------------*/ + +/* USER CODE END PFP */ +//void sts_tof_vl53lx_peoplecount(void); +//int sts_tof_vl53lx_peoplecount_subprocess(void); +/* USER CODE BEGIN 0 */ + +#define VL53L1X_INT_Pin (GPIO_PIN_3) // WL55JC GPIO_PIN_10, F401xE ==>(GPIO_PIN_4) +#if 0 +void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) +{ + if (GPIO_Pin==VL53L1X_INT_Pin) + { + IntCount++; + } +} +#endif +/* USER CODE END 0 */ + +int ProcessPeopleCountingData(int16_t Distance, uint8_t zone, uint8_t RangeStatus) { + + uint16_t MinDistance; + uint8_t i; + +#ifdef TRACE_PPC +#define TIMES_WITH_NO_EVENT 10// was 40 + static uint32_t trace_count = TIMES_WITH_NO_EVENT; // replace by 0 if you want to trace the first TIMES_WITH_NO_EVENT values +#endif + + int CurrentZoneStatus = NOBODY; + int AllZonesCurrentStatus = 0; + int AnEventHasOccured = 0; + + // Add just picked distance to the table of the corresponding zone + if (DistancesTableSize[zone] < ppc_cfg[sts_distance_mode].distance_array_size) { + Distances[zone][DistancesTableSize[zone]] = Distance; + DistancesTableSize[zone] ++; + } + else { + for (i=1; i= 2) { + for (i=1; i if next is 0 : check if exit + PathTrack[PathTrackFillingSize-1] = AllZonesCurrentStatus; + } + +#if 1 +#ifdef TRACE_PPC + if (AnEventHasOccured) { + for (int j=0; jWalk_In_People_Count = sts_people_count_sensor_data.Walk_In_People_Count; + sts_p2_sensor_data->Walk_Out_People_Count = sts_people_count_sensor_data.Walk_Out_People_Count; + sts_p2_sensor_data->Walk_Around_People_Count = sts_people_count_sensor_data.Walk_Around_People_Count; + sts_p2_sensor_data->Count_Period = sts_people_count_sensor_data.Count_Period; + sts_p2_sensor_data->Count_Period_Unit = sts_people_count_sensor_data.Count_Period_Unit; + + // Sum Day counting + // if not end of day --- + sts_people_count_sensor_data.Sum_Day_Walk_In_People_Count += sts_people_count_sensor_data.Walk_In_People_Count; + sts_people_count_sensor_data.Sum_Day_Walk_Out_People_Count += sts_people_count_sensor_data.Walk_Out_People_Count; + sts_people_count_sensor_data.Sum_Day_Walk_Around_People_Count += sts_people_count_sensor_data.Walk_Around_People_Count; + + sts_p2_sensor_data->Sum_Day_Walk_In_People_Count = sts_people_count_sensor_data.Sum_Day_Walk_In_People_Count; + sts_p2_sensor_data->Sum_Day_Walk_Out_People_Count = sts_people_count_sensor_data.Sum_Day_Walk_Out_People_Count; + sts_p2_sensor_data->Sum_Day_Walk_Around_People_Count = sts_people_count_sensor_data.Sum_Day_Walk_Around_People_Count; + + + // else reset day counter +#if 0 + sts_people_count_sensor_data.Sum_Day_Walk_In_People_Count = 0; + sts_people_count_sensor_data.Sum_Day_Walk_Out_People_Count = 0; + sts_people_count_sensor_data.Sum_Day_Walk_Around_People_Count = 0; +#endif + + // Sum Week counting + // if not end of week --- + sts_people_count_sensor_data.Sum_Week_Walk_In_People_Count += sts_people_count_sensor_data.Sum_Day_Walk_In_People_Count; + sts_people_count_sensor_data.Sum_Week_Walk_Out_People_Count += sts_people_count_sensor_data.Sum_Day_Walk_Out_People_Count; + sts_people_count_sensor_data.Sum_Week_Walk_Around_People_Count += sts_people_count_sensor_data.Sum_Day_Walk_Around_People_Count; + // else reset week counter +#if 0 + sts_people_count_sensor_data.Sum_Week_Walk_In_People_Count = 0; + sts_people_count_sensor_data.Sum_Week_Walk_Out_People_Count = 0; + sts_people_count_sensor_data.Sum_Week_Walk_Around_People_Count = 0; +#endif + + // Sum Month counting + // if not end of month --- + sts_people_count_sensor_data.Sum_Month_Walk_In_People_Count += sts_people_count_sensor_data.Sum_Day_Walk_In_People_Count; + sts_people_count_sensor_data.Sum_Month_Walk_Out_People_Count += sts_people_count_sensor_data.Sum_Day_Walk_Out_People_Count; + sts_people_count_sensor_data.Sum_Month_Walk_Around_People_Count += sts_people_count_sensor_data.Sum_Day_Walk_Around_People_Count; + // else reset month counter +#if 0 + sts_people_count_sensor_data.Sum_Month_Walk_In_People_Count = 0; + sts_people_count_sensor_data.Sum_Month_Walk_Out_People_Count = 0; + sts_people_count_sensor_data.Sum_Month_Walk_Around_People_Count = 0; +#endif + + // Sum Year counting + // if not end of year --- + sts_people_count_sensor_data.Sum_Year_Walk_In_People_Count += sts_people_count_sensor_data.Sum_Day_Walk_In_People_Count; + sts_people_count_sensor_data.Sum_Year_Walk_Out_People_Count += sts_people_count_sensor_data.Sum_Day_Walk_Out_People_Count; + sts_people_count_sensor_data.Sum_Year_Walk_Around_People_Count += sts_people_count_sensor_data.Sum_Day_Walk_Around_People_Count; + // else reset year counter +#if 0 + sts_people_count_sensor_data.Sum_Year_Walk_In_People_Count = 0; + sts_people_count_sensor_data.Sum_Year_Walk_Out_People_Count = 0; + sts_people_count_sensor_data.Sum_Year_Walk_Around_People_Count = 0; +#endif + + // Sum LifeCycle counting + sts_people_count_sensor_data.Sum_LifeCycle_Walk_In_People_Count += sts_people_count_sensor_data.Sum_Day_Walk_In_People_Count; + sts_people_count_sensor_data.Sum_LifeCycle_Walk_Out_People_Count += sts_people_count_sensor_data.Sum_Day_Walk_Out_People_Count; + sts_people_count_sensor_data.Sum_LifeCycle_Walk_Around_People_Count += sts_people_count_sensor_data.Sum_Day_Walk_Around_People_Count; + + //reset counter of counting period + sts_people_count_sensor_data.Walk_In_People_Count = 0; + sts_people_count_sensor_data.Walk_Out_People_Count = 0; + sts_people_count_sensor_data.Walk_Around_People_Count = 0; + + // reset counter at end of day TODO XXX + // reset counter at end of week TODO XXX + // reset counter at end of month TODO XXX + // reset counter at end of year TODO XXX + // reset counter at end of year TODO XXX + + // write to NVM store TODO XXX + +} + +void STS_TOF_VL53LX_PeopleCounting_Process_Init(void) +{ + APP_LOG(TS_OFF, VLEVEL_M,"############### TOF VL53LX_ PEOPLE COUNTING PROCESS INITIALIZATION\r\n"); + sts_tof_vl53lx_peoplecount_init(); + +} + +void STS_TOF_VL53LX_PeopleCounting_Process_Start(void* context) +{ + + //APP_LOG(TS_OFF, VLEVEL_M,"############### TOF VL53LX_ PEOPLE COUNTING SUB-PROCESS \r\n"); + { + status = sts_tof_vl53lx_peoplecount_start(); + //APP_LOG(TS_OFF, VLEVEL_M,"############### SUB-PROCESS running .... \r\n"); + } + +} + +int sts_tof_vl53lx_peoplecount_init(void) +{ + //int8_t error; + uint8_t byteData, sensorState=0; + uint16_t wordData; + + /* int PplCounter = 0;*/ + + /* MCU Configuration----------------------------------------------------------*/ + + /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ + + + /* Configure the system clock */ + + + /* Initialize all configured peripherals */ + APP_LOG(TS_OFF, VLEVEL_L,"XNUCLEO53L1A1_Init Start .......... \r\n"); + status = XNUCLEO53L1A1_Init(); + APP_LOG(TS_OFF, VLEVEL_L,"XNUCLEO53L1A1_Init Status : %X\n", status); + + + status = XNUCLEO53L1A1_ResetId(XNUCLEO53L1A1_DEV_CENTER, 0); // Reset ToF sensor + HAL_Delay(2); + status = XNUCLEO53L1A1_ResetId(XNUCLEO53L1A1_DEV_CENTER, 1); // Reset ToF sensor + + + // Those basic I2C read functions can be used to check your own I2C functions */ + status = VL53L1_RdByte(dev, 0x010F, &byteData); + APP_LOG(TS_OFF, VLEVEL_L,"VL53L1X Model_ID: %X\n", byteData); + status = VL53L1_RdByte(dev, 0x0110, &byteData); + APP_LOG(TS_OFF, VLEVEL_L,"VL53L1X Module_Type: %X\n", byteData); + status = VL53L1_RdWord(dev, 0x010F, &wordData); + APP_LOG(TS_OFF, VLEVEL_L,"VL53L1X: %X\n", wordData); + while (sensorState == 0) { + status = VL53L1X_BootState(dev, &sensorState); + HAL_Delay(2); + } + APP_LOG(TS_OFF, VLEVEL_L,"Chip booted\n"); + + /* Initialize and configure the device according to people counting need */ + status = VL53L1X_SensorInit(dev); + status += VL53L1X_SetDistanceMode(dev, ppc_cfg[sts_distance_mode].distance_mode); /* 1=short, 2=long, DISTANCE_MODE */ + status += VL53L1X_SetTimingBudgetInMs(dev, ppc_cfg[sts_distance_mode].timing_budget); /* TIMING_BUDGET, in ms possible values [15, 20, 50, 100, 200, 500] */ + status += VL53L1X_SetInterMeasurementInMs(dev, ppc_cfg[sts_distance_mode].timing_budget); + status += VL53L1X_SetROI(dev, ppc_cfg[sts_distance_mode].rows_of_SPADS, 16); /* minimum ROI 4,4 */ + center[0]=ppc_cfg[sts_distance_mode].front_zone_center; + center[1]=ppc_cfg[sts_distance_mode].back_zone_center; + if (status != 0) { + APP_LOG(TS_OFF, VLEVEL_L,"Initialization or configuration of the device\n"); + return (-1); + } + APP_LOG(TS_OFF, VLEVEL_L,"Start counting people with profile : %s...\n", PROFILE_STRING); + status = VL53L1X_StartRanging(dev); /* This function has to be called to enable the ranging */ + + if (status != 0) { + APP_LOG(TS_OFF, VLEVEL_L,"Error in start ranging\n"); + return (-1); + } + return 0; +} +int sts_tof_vl53lx_peoplecount_start(void) +{ + //uint8_t byteData, sensorState=0; + //uint16_t wordData; + uint16_t Distance, Signal; + uint8_t RangeStatus; + uint8_t dataReady; + //char DisplayStr[5]; + + /* read and display data */ + + while (dataReady == 0) { + status = VL53L1X_CheckForDataReady(dev, &dataReady); + HAL_Delay(1); + } + dataReady = 0; + status += VL53L1X_GetRangeStatus(dev, &RangeStatus); + status += VL53L1X_GetDistance(dev, &Distance); + status += VL53L1X_GetSignalPerSpad(dev, &Signal); + status += VL53L1X_ClearInterrupt(dev); /* clear interrupt has to be called to enable next interrupt*/ + if (status != 0) { + APP_LOG(TS_OFF, VLEVEL_L,"Error in operating the device\n"); + return (-1); + } + //HAL_Delay(WAIT_BEFORE_PROGRAMMING_OTHER_ZONE_CENTER); // 10, 8, 7, 6 tested OK + status = VL53L1X_SetROICenter(dev, center[Zone]); + if (status != 0) { + APP_LOG(TS_OFF, VLEVEL_L,"Error in chaning the center of the ROI\n"); + return (-1); + } + // check the status of the ranging. In case of error, lets assume the distance is the max of the use case + // Value RangeStatus string Comment + // 0 VL53L1_RANGESTATUS_RANGE_VALID Ranging measurement is valid + // 1 VL53L1_RANGESTATUS_SIGMA_FAIL Raised if sigma estimator check is above the internal defined threshold + // 2 VL53L1_RANGESTATUS_SIGNAL_FAIL Raised if signal value is below the internal defined threshold + // 4 VL53L1_RANGESTATUS_OUTOFBOUNDS_ FAIL Raised when phase is out of bounds + // 5 VL53L1_RANGESTATUS_HARDWARE_FAIL Raised in case of HW or VCSEL failure + // 7 VL53L1_RANGESTATUS_WRAP_TARGET_ FAIL Wrapped target, not matching phases + // 8 VL53L1_RANGESTATUS_PROCESSING_ FAIL Internal algorithm underflow or overflow + // 14 VL53L1_RANGESTATUS_RANGE_INVALID The reported range is invalid + if ((RangeStatus == 0) || (RangeStatus == 4) || (RangeStatus == 7)) { + if (Distance <= ppc_cfg[sts_distance_mode].min_distance) //MIN_DISTANCE) // wraparound case see the explanation at the constants definition place + Distance = ppc_cfg[sts_distance_mode].max_distance + ppc_cfg[sts_distance_mode].min_distance; //MAX_DISTANCE + MIN_DISTANCE; + } + else // severe error cases + Distance = ppc_cfg[sts_distance_mode].max_distance; //MAX_DISTANCE; + // inject the new ranged distance in the people counting algorithm + PplCounter = ProcessPeopleCountingData(Distance, Zone, RangeStatus); + //printf("\PplCounter =%d \n\r", PplCounter); + //sprintf(DisplayStr, "%4d", PplCounter); // only use for special EVK with display + //XNUCLEO53L1A1_SetDisplayString(DisplayStr); + //APP_LOG(TS_OFF, VLEVEL_H,"%d,%d,%d\n", Zone, Distance, Signal); + Zone++; + Zone = Zone%2; + + return 0; +} diff --git a/TOF/App/app_tof_peoplecount.h b/TOF/App/app_tof_peoplecount.h new file mode 100644 index 0000000..7ddf790 --- /dev/null +++ b/TOF/App/app_tof_peoplecount.h @@ -0,0 +1,150 @@ +/** + ****************************************************************************** + * @file : app_tof_peoplecount.h + * @author : IMG SW Application Team + * @brief : This file provides code for the configuration + * of the STMicroelectronics.X-CUBE-TOF1.3.2.0 instances. + ****************************************************************************** + * + * @attention + * + * Copyright (c) 2022 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 __APP_TOF_PEOPLECOUNT_H +#define __APP_TOF_PEOPLECOUNT_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ + +/* Exported defines ----------------------------------------------------------*/ + + + // People Counting defines + #define NOBODY 0 + #define SOMEONE 1 + #define LEFT 0 + #define RIGHT 1 + + #define DOOR_JAM_2000 0 + #define DOOR_JAM_2400 1 + #define DOOR_JAM_3000 2 + #define ON_SIDE 3 + + + + // define here the profile for your case. + #define PPC_PROFILE DOOR_JAM_2400 + + #define TRACE_PPC 1 + +// time budget in ms 20,33,50,100,200,500 +#define tbms_20 20 +#define tbms_33 33 +#define tbms_50 50 +#define tbms_100 100 +#define tbms_200 200 +#define tbms_500 500 + + //PPC_PROFILE DOOR_JAM_2400 + #if PPC_PROFILE == DOOR_JAM_2400 + #define PROFILE_STRING "DOOR_JAM_2400" + #define DISTANCES_ARRAY_SIZE 10 // nb of samples + #define MAX_DISTANCE 2400 // mm was 2400 + #define MIN_DISTANCE 0 // mm + #define DIST_THRESHOLD 1600 // mm + #define ROWS_OF_SPADS 8 // 8x16 SPADs ROI + #define TIMING_BUDGET 33 //33 // was 20 ms, I found 33 ms has better succes rate with lower reflectance target + #define DISTANCE_MODE DISTANCE_MODE_LONG + #endif + + #if ROWS_OF_SPADS == 4 + #define FRONT_ZONE_CENTER 151 + #define BACK_ZONE_CENTER 247 + #elif ROWS_OF_SPADS == 6 + #define FRONT_ZONE_CENTER 159 + #define BACK_ZONE_CENTER 239 + #elif ROWS_OF_SPADS == 8 + #define FRONT_ZONE_CENTER 175 // was 167, see UM2555 on st.com, centre = 175 has better return signal rate for the ROI #1 + #define BACK_ZONE_CENTER 231 + #endif + +/* Exported functions --------------------------------------------------------*/ + enum distance_mode { + DISTANCE_MODE_SIDE=0, + DISTANCE_MODE_SHORT, + DISTANCE_MODE_LONG, + }; + + typedef struct STS_ZONE_CENTRE_BY_ROWS_OF_SPADS + { + uint8_t rows_of_spads; + uint8_t front_zone_center; + uint8_t back_zone_center; + } sts_zone_center_by_rows_of_spads_t; + typedef struct STS_PPC_CFG_Type { + uint8_t profile_name; + uint8_t distance_array_size; + uint16_t max_distance; + uint16_t min_distance; + uint16_t dist_threshold; + uint8_t rows_of_SPADS; /* minimum ROI 4,4 */ + uint16_t timing_budget; /* TIMING_BUDGET, in ms possible values [15, 20, 33, 50, 100, 200, 500] */ + uint8_t distance_mode; /* 1=short, 2=long, DISTANCE_MODE */ + uint8_t front_zone_center; + uint8_t back_zone_center; + } sts_ppc_cfg_type_t; + + typedef struct STS_People_Count_Sensor_Data_Type { + uint16_t Walk_In_People_Count; + uint16_t Walk_Out_People_Count; + uint16_t Walk_Around_People_Count; + uint8_t Count_Period; + uint8_t Count_Period_Unit; + + uint16_t Sum_Day_Walk_In_People_Count; + uint16_t Sum_Day_Walk_Out_People_Count; + uint16_t Sum_Day_Walk_Around_People_Count; + + uint16_t Sum_Week_Walk_In_People_Count; + uint16_t Sum_Week_Walk_Out_People_Count; + uint16_t Sum_Week_Walk_Around_People_Count; + + uint16_t Sum_Month_Walk_In_People_Count; + uint16_t Sum_Month_Walk_Out_People_Count; + uint16_t Sum_Month_Walk_Around_People_Count; + + uint16_t Sum_Year_Walk_In_People_Count; + uint16_t Sum_Year_Walk_Out_People_Count; + uint16_t Sum_Year_Walk_Around_People_Count; + + uint32_t Sum_LifeCycle_Walk_In_People_Count; + uint32_t Sum_LifeCycle_Walk_Out_People_Count; + uint32_t Sum_LifeCycle_Walk_Around_People_Count; + + } sts_people_count_sensor_data_t; + +void STS_TOF_VL53LX_PeopleCounting_Process_Init(void); +void STS_TOF_VL53LX_PeopleCounting_Process_Start(void*); +int sts_tof_vl53lx_peoplecount_init(void); +int sts_tof_vl53lx_peoplecount_start(void); +//int sts_tof_vl53lx_peoplecount(void); +int ProcessPeopleCountingData(int16_t Distance, uint8_t zone, uint8_t RangeStatus); +void STS_people_count_sensor_Read(sts_people_count_sensor_data_t *sts_p2_sensor_data); + +#ifdef __cplusplus +} +#endif + +#endif /* __APP_TOF_PEOPLECOUNT_H */ diff --git a/TOF/Target/53l1a2_conf.h b/TOF/Target/53l1a2_conf.h new file mode 100644 index 0000000..9467008 --- /dev/null +++ b/TOF/Target/53l1a2_conf.h @@ -0,0 +1,61 @@ + +/** + ****************************************************************************** + * @file 53l1a2_conf.h + * @author IMG SW Application Team + * @brief This file contains definitions for the ToF components bus interfaces + * when using the X-NUCLEO-53L1A2 expansion board + ****************************************************************************** + * @attention + * + * Copyright (c) 2022 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 VL53L1A2_CONF_H +#define VL53L1A2_CONF_H + +#include "stm32wlxx_hal.h" +#include "stm32wlxx_nucleo_bus.h" +#include "stm32wlxx_nucleo_errno.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ + +/* + * the 53L1A2 BSP driver uses this symbol to allocate a structure for each device + * if you are only using the on-board sensor without break-out boards + * change its to (1U) in order to save space in RAM memory + */ +#define RANGING_SENSOR_INSTANCES_NBR (3U) + +#define VL53L1A2_hi2c (hi2c2) + +#define VL53L1A2_I2C_SCL_GPIO_PORT BUS_I2C2_SCL_GPIO_PORT +#define VL53L1A2_I2C_SCL_GPIO_PIN BUS_I2C2_SCL_GPIO_PIN +#define VL53L1A2_I2C_SDA_GPIO_PORT BUS_I2C2_SDA_GPIO_PORT +#define VL53L1A2_I2C_SDA_GPIO_PIN BUS_I2C2_SDA_GPIO_PIN + +#define VL53L1A2_I2C_Init BSP_I2C2_Init +#define VL53L1A2_I2C_DeInit BSP_I2C2_DeInit +#define VL53L1A2_I2C_WriteReg BSP_I2C2_Send +#define VL53L1A2_I2C_ReadReg BSP_I2C2_Recv +#define VL53L1A2_GetTick BSP_GetTick + +#ifdef __cplusplus +} +#endif + +#endif /* VL53L1A2_CONF_H */ diff --git a/TOF/Target/app_tof_pin_conf.c b/TOF/Target/app_tof_pin_conf.c new file mode 100644 index 0000000..73e1c29 --- /dev/null +++ b/TOF/Target/app_tof_pin_conf.c @@ -0,0 +1,30 @@ +/** + ****************************************************************************** + * @file app_tof_pin_conf.c + * @author IMG SW Application Team + * @brief This file contains functions for TOF pins + ****************************************************************************** + * @attention + * + * Copyright (c) 2022 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 "app_tof_pin_conf.h" + +extern volatile uint8_t ToF_EventDetected; + +void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) +{ + if (GPIO_Pin == TOF_INT_EXTI_PIN) + { + ToF_EventDetected = 1; + } +} diff --git a/TOF/Target/app_tof_pin_conf.h b/TOF/Target/app_tof_pin_conf.h new file mode 100644 index 0000000..5cd9b10 --- /dev/null +++ b/TOF/Target/app_tof_pin_conf.h @@ -0,0 +1,38 @@ +/** + ****************************************************************************** + * @file app_tof_pin_conf.h + * @author IMG SW Application Team + * @brief This file contains definitions for TOF pins + ****************************************************************************** + * @attention + * + * Copyright (c) 2022 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 __APP_TOF_PIN_CONF_H__ +#define __APP_TOF_PIN_CONF_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32wlxx_hal.h" + +/* Exported symbols ----------------------------------------------------------*/ +#define TOF_INT_EXTI_PIN (GPIO_PIN_3) // (GPIO_PIN_4) +#define TOF_INT_EXTI_PORT (GPIOB) + +#ifdef __cplusplus +} +#endif + +#endif /* __APP_TOF_PIN_CONF_H__ */ diff --git a/VL53L1X_BareDriver_with_UltraLowPower/Binary/VL53L1X_BareDriver_with_UltraLowPower.bin b/VL53L1X_BareDriver_with_UltraLowPower/Binary/VL53L1X_BareDriver_with_UltraLowPower.bin deleted file mode 100644 index 917b7c4be57f8033d0b49dd3fe3f17a3a2ef405e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 54184 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%0A^+vV6 zbgZ8G&l!tq!uZ)Q@jGaYX)?RdQqR(e|w`(cCd;>y%WtB#~sgj zM7?RmxTdJuT@yU%Lwv>41)n|RiQHX*ExUZ(|0x}W0+trqs(TH?G zw>M%3J7)RDtsMb&!IPJzVAg*b1=M@|A_}}?bmnn+u0oZ+8|6Iqi=}OAoUEb6@rxt>df~r{TOQ8i z>YK=|^o@WJv~pZa?bxl_B~2@#PwJjze1}5)Q`BQN>9FggyO+#t(q`}Yy#j)@g`OK~ zXAX2vT>l4(neHu!>%nL@VhWsW0skz~J?XT`H8u8QL?tj|ILw&b?AUHZGw5v);;KPZ zqz1b3zkq2eFx5zaSZatp4Tz^IeTZ;a#o3q{w0zICme>xIKTgYetJsG0V`-S|_;%#B zRq|?!tw@Jy8c-U3D>T${p)6nm?@i#n8y2P>r-X>X{NdYx)~J!A(@>v0ufYwUp9m+P zY8;1)fiF1cKs(&AA+EaU`t(>4dyUqPjeAz?Tj_CAD|QcUufppw>H!J6G}!SsPThra zUQUAZ_TT_nv(oCz7MEbm1K^7zTII({vUqXiXKAWlOjE_G)IWbp7{e+@eUmVGR7}(3 zOVzWUiz82@F|u>BP7XQk~88;4H!rbBN;-V=te{~&IZsJH!yD;GK)!A&}QV@{<{y(48w z*QsZnfTbr69Q+QPCdDS6I9wc=iN5n8A?0Ops2&Jtk#m%_;T9E!u8X`OXAaa{4c@=&W(hnd_p=e9u znhwqTtx|@&Ko>`Tt!Nsx>}=aYL;|6Gzlg6#3ypgptJ-%c4cqrQ*jM7!*q_r5*U`EO;c1U(=(lajH9+Ht znuachMmxG1YD_pc*U|JqgWYf=w97BvnAVMNrm>0L;EH{ zFO56Lp<_2v&cj!wHfCXb7Uq$HxlBvuVm}YLW4;U^3SI;YjGL%*_B3>QZLv|Q;o zR!^(6rr{Z;!%HJmxF5Q3d<3|iq_%0Q)kf0krSov2pF(wo>W)aDJLwo8J-@_$1l0T{ zE~#`HIqIWWPOSGYk?20JZbB)=h~3hdg>XO)loM3f_0hW_pLLbK;rLoDwxrECeRM6# z*PvYVb%<1kyewl}UDB=K^$zq;F;F{OPUj|c)fmJ1KSoC_X(1@vf*xyd$_oD;Zw~cK z$2e+6{l>Uk%~P92M{-~MMzt3Xz0^q8tG!$tX&Ft5R9iQXvVwvYeOz0sAi*xsU{T?_ zNT+u&hSPJDqX=b`Sk#!Hj!kIE%x{-Nli2)w9J+e2tzjQW-jM_XhzM^*m7S zqi1nAW1(>cJZ?M@u}&Kk)+}Sx1nLOlEC<5h^hd<~ar(Ot^A6mUm*U>Sx-olR8NCzf zE_0Pkbe^-Re7so>U;gOMu!dq`p@2L`>+WF6&&2BeOrhWuR@!R^4Q!@nCu*Lq-@(+_ z>IYdJN*O%tABgwN+D#`&wlGboDJ&l}jMdb#-ZRJ6+|AOO0-*@r7R7H9c;Wm=5+}bF zK@nHRul*mUYA>kjShM@GRQ)VXRTgNnThw!^(i-9xM1)k%f2F4WSeaO<0=n=oHf2(@nEGT|oLD=Bpf`WC+X3oM32P*cM`hxH-;G6Jlh`Qkda3jI zLHMTQ@!$KA%ftY+2(A{_y*Tn%l17wA+d8+?-;?<5qJG!6)OY~a5FOTDB@n@x4+jrl z!AWF9-OJGU<-E9?MgoGw87`u`0Z-Z&=lC1q3fgAJB0+nbw%32{6BAo4MuKc9?#ZB5 zi{w^kPKl&}Co)l7N(0Ri*KcumPQ&j}@#l@@R8g=!VuhcirL* zts9no1TNGn4aD^))ytoTo4cVPZA0VObiI$LZKjpJx?xGJ5;%t#IBi2Cidq|uT8(Ng zj!rqq;f$L0Ws~T>l;f9q zNz>|yM2-485X8AIG|LX_$`8-LnT7>t8dGs{o$WiOme)`$51^&0nK&;}^)iZ6BAvQU z{TotTEH(12i%HDT)JO&1u+@m=kSdS-YFLqGQ~PFkLFf?*22I?`L9=d`@KdDqrj>&R zY7G z6=ZsPQRo#42hCh1zH!?v>_u8{t{gOEjra5`^mI3RdW&fno}u*w^0?)I*kmt5RliojQHc+19ehpR_JnG7{lVJVXyn|5g&lRr2Dsmk0Tq=R8 zNfPLytt=;mKU^Y#Y)HWJg%Yq2n)Ry&v%XTlyVLz%cL_J_%)-)Z#<(GKR2u*N)T~KU zlXDqr%wyE#j>$&5se`Xq|Ayq@e0v(>x$=?0+Zlg>M87MuV7+SUn{wNfRnOU<%Oi81 z_nKqbw^>#Zd2=dLqK`ElzAHJWWLE{V=;K5tbvAK5?x$y-GNkkRd{<ZXce~v<`#2vQ=wWW@ zmS!ZGD;amUc=`}=EjZ~EvWh75(j-%oAI);)$7iAy6MI?uV`4f|rvCqsK1dWn%ZR)s zN#?#Er8je$4r8S`xfedX;k~S4U6jXH5>BzO>9+}|3RwVbZ^ce0cqz+4YYLkFgqxiQ zv97<1XBQsU&jVK7y6s}W=jUlvpGF4K{}KtYtJnJhFs8j;GCtT zvv<1jns=gx{CCXGg(AJn*u9nV>z4SObdQ6HtI|Dwn7G|I^>|>zvL4+~Ik(%(MoWON zaFpgKG~_imY;&yb2wC#<;G(4xBujAdV5pg6hu1u|3|7)oPhu$TM1mb?^A$ zo9N%m#v07NM;w?RTR&_d3(f)m)Zy@&Yo($Fm$)!0{&jbIwNZb(j!I-hb`Rfp#D*_A zgby2v8s-Z7DtxoL+YPZ|X?F37cZ(~3<@uel{5WyeiYIi=pi|Tx_s(KsE{QuNt`BUu zRwTu5MKheBoZX3=hhp841jAEY%Vzx&u*CI?=xoGZX2558IrqkdH zLp+YMzU-hLQXc5Z%quZzfz-@tDTjKfE*<`;%##|a>o=w)JCx9;CHo)XaoHuhL-@Qt zop9tdDcvS+-RisdwXH`^>q@r;3I&t%9^7;ry`cBk)$0A-c>ajzs#?A-4>)3eV)_J+ zYZWn7;bB%1`H_R9zsQU4U-~MqkmlU!g9RAc%n*6yIi29?Aw}qAhNWbWs2`Hp)X3Wx z975CKZ9&?9Y2?W1sioZdsrV|VREm~Yws_4mGUn%w!k z_{M2&(Hp1rcbc5Vf^O&@k{StKc;obxJKs1x^-d}$+Ao8%_xY!jzOc|Pkf9Yi@{MWe z`|wA}ZSS0B9%Pm>$FGt;O}x~O-S&yTb2%kUDHkmkJi;$43_c0gx(PO?=Uh%6DgM#E zX~Jy5c#`lgaeuqbkoQg%&Ioei4dBQP=gHi&15777+~nQ+DOp?XtzI@y{5av^iGvqs z>}xu_qrJKB$3|)wjK_6D6&x?}xUXLqU{S}s)PRxxDn)kd)w%ke$l9o-^dV{ zffv0T+Lwx0Uk?-ckWy4RO)3(eKIB-%OLoW*<5e7DvC1)`_-0)N9Vr!Q`E$y@C$gm) zd%-)|uG|yZ;@hi#Q$WjiDY~I-!q0ZdM)JDtShU*vht<)<6JEbGqrXnHiWXroVG&kJ zze&6?>nfSk?ZKDZMK;xjA+ zun0fiHxqhhNUztak?Svh7dB&EY%|vA0^>Ka!qK=o;msWm{>fxo9ganOs|9>v%!XJF!CBzqvxetkQM0L{1pW`yEcyI&8-BewUh>*D`P3yr{AB z1%WuS<}4H7wYW>%W>@fpxc{p7YSro;koG33RI4{E{TM4KrKAz_<;SX*FdLqV{5LNM zdlTiAVO#bnkqdmfrrAPm_7ffbkh!e2tgR1Ef^S7r1g_yWm00bCt!o zF57Io#63f`8Y3w+4Y4MDN9nB?VIJq4D=0V<@bq|ikDUX4T^Hvw4KXGaPu{#0PbTN) z8Js9FDkH<7>qhz=euV2Xmhy-vm`b@0bC)0dTAk1<>_W!TCOn=XJjI~zC={~hcm({V z7gxy=^E~bZalIbZKmC6IiN6}ahXpyoy+k^kg4M5ku|%L>i|)hDb*peZ*4*E&qX{ed_=@YNR>cL^zXeqEnF!)E@cPbPddUK z-h=&C;VsDY>7>s=?ab63rj+J+X}7`Ke*!61&Cijh%LctMrW-2E`lEz$N0;p-@7(ux zCVeGNiIf(=+CO8M|Bi0R$1aAnj#Mxu4tQ^WQeo+dzRqRp|Cy~@at1B^bI$zfK{BVq z`$m74?au|+NtkWd-@4oe9XG`pehvPxokZ)w4<*Ta!NGEZ>=2 zp7(Ilm&ca=0_(VQti^{>^AKZx7yd5B>SKm{7K>p1{v-SDFP@3nu}iRY5_x~v`EFhD z4N-hIPz)OpUWeapVcn2dzdh;ATNtk|W}?C3&tRdflHR}#>6m%P?NYvoyQC-QJ8Qh# z!K;lcvYd+kDUEsxJW9JbxaZHx;aMXd*mO4*9)e3*`Q*;Xu^!IMHJzK{t{lFWNy+A zr53$BsOR{=+es333*0|ybLz8;Ov$Y(m-Tc`ZCkto^yXQmB55|Loi1h>vXB1?Gk2Nn zKu`8VPQhgc=Q^!0nt*Ui~jGd_(SQpXbrY9q2s z%<)3R4H__}Lf8&IuwI}Lg|qX;*;1`Uuvbt5|8*2MqBa^2|hS)OuGLF zjp{O5--%0H*DmO8fzS=3bd zGv(+N~%{xqe+be|~?E`x1*Ub?0$MFr8Q(gOIDcRjlS6K?*y>+4BR((5p8Iflm z9LIcTl6te#`^EJX&Zoi_^i$j#7VAMm%KD6}D3$pFaXN7i^!&&WT1}>P@>nihrrwwy zYrZ<#*R6Bh*|>RAz|pwzJC3G}-&w!OQNJnpZM^U_2RGjD zSmKz|oP~B7@cTDzcGR!myuNPp`g&^rGUdVhgPR@q27-<2>mA<-Zk8O)n**C4YAKdH+IHbV+^^Us6jm_&Fn>RW(OY0rY>+f&gxQXUA1%fCJ z-0uk9zj^(pO%FD0Ua(++gZ6hvVAFl;$4MxnWto2r%jpb8lbPme8n1kouqN#08HN_7 zNG^R5M>ej;PeWTh&HWOZkYZGG&SVqTOb(EUsf^a-w$oqyV~l!(0d3w)blfW{W7* + +static const uint8_t VL53L1X_ULP_DEFAULT_CONFIGURATION[] = { + 0x00, /* 0x2d */ + 0x00, /* 0x2e */ + 0x00, /* 0x2f */ + 0x11, /* 0x30 */ + 0x02, /* 0x31 */ + 0x00, /* 0x32 */ + 0x02, /* 0x33 */ + 0x08, /* 0x34 */ + 0x00, /* 0x35 */ + 0x08, /* 0x36 */ + 0x10, /* 0x37 */ + 0x01, /* 0x38 */ + 0x01, /* 0x39 */ + 0x00, /* 0x3a */ + 0x00, /* 0x3b */ + 0x00, /* 0x3c */ + 0x00, /* 0x3d */ + 0xff, /* 0x3e */ + 0x00, /* 0x3f */ + 0x0F, /* 0x40 */ + 0x00, /* 0x41 */ + 0x00, /* 0x42 */ + 0x00, /* 0x43 */ + 0x00, /* 0x44 */ + 0x00, /* 0x45 */ + 0x20, /* 0x46 */ + 0x0b, /* 0x47 */ + 0x00, /* 0x48 */ + 0x00, /* 0x49 */ + 0x02, /* 0x4a */ + 0x14, /* 0x4b */ + 0x21, /* 0x4c */ + 0x00, /* 0x4d */ + 0x00, /* 0x4e */ + 0x05, /* 0x4f */ + 0x00, /* 0x50 */ + 0x00, /* 0x51 */ + 0x00, /* 0x52 */ + 0x00, /* 0x53 */ + 0xc8, /* 0x54 */ + 0x00, /* 0x55 */ + 0x00, /* 0x56 */ + 0x38, /* 0x57 */ + 0xff, /* 0x58 */ + 0x01, /* 0x59 */ + 0x00, /* 0x5a */ + 0x08, /* 0x5b */ + 0x00, /* 0x5c */ + 0x00, /* 0x5d */ + 0x00, /* 0x5e */ + 0x01, /* 0x5f */ + 0x0b, /* 0x60 */ + 0x00, /* 0x61 */ + 0x02, /* 0x62 */ + 0x09, /* 0x63 */ + 0x00, /* 0x64 */ + 0xb4, /* 0x65 */ + 0x00, /* 0x66 */ + 0xbb, /* 0x67 */ + 0x08, /* 0x68 */ + 0x38, /* 0x69 */ + 0x00, /* 0x6a */ + 0x00, /* 0x6b */ + 0x00, /* 0x6c */ + 0x00, /* 0x6d */ + 0x0f, /* 0x6e */ + 0x89, /* 0x6f */ + 0x00, /* 0x70 */ + 0x00, /* 0x71 */ + 0x00, /* 0x72 */ + 0x00, /* 0x73 */ + 0x00, /* 0x74 */ + 0x00, /* 0x75 */ + 0x00, /* 0x76 */ + 0x01, /* 0x77 */ + 0x07, /* 0x78 */ + 0x05, /* 0x79 */ + 0x06, /* 0x7a */ + 0x06, /* 0x7b */ + 0x00, /* 0x7c */ + 0x00, /* 0x7d */ + 0x02, /* 0x7e */ + 0xc7, /* 0x7f */ + 0xff, /* 0x80 */ + 0x9B, /* 0x81 */ + 0x00, /* 0x82 */ + 0x00, /* 0x83 */ + 0x00, /* 0x84 */ + 0x01, /* 0x85 */ + 0x00, /* 0x86 */ + 0x00 /* 0x87 */ +}; + + +uint8_t VL53L1X_ULP_GetSensorId( + uint16_t dev, + uint16_t *p_id) +{ + uint8_t status = VL53L1X_ULP_ERROR_NONE; + + status |= VL53L1X_ULP_RdWord(dev, + VL53L1X_ULP_IDENTIFICATION__MODEL_ID, p_id); + return status; +} + +uint8_t VL53L1X_ULP_SetI2CAddress( + uint16_t dev, + uint8_t new_address) +{ + uint8_t status = VL53L1X_ULP_ERROR_NONE; + + status |= VL53L1X_ULP_WrByte(dev, VL53L1X_ULP_I2C_SLAVE__DEVICE_ADDRESS, + (uint8_t)(new_address >> (uint8_t)1)); + return status; +} + +uint8_t VL53L1X_ULP_SensorInit( + uint16_t dev) +{ + uint8_t status = VL53L1X_ULP_ERROR_NONE; + uint8_t Addr, tmp; + uint8_t continue_loop = 1; + uint16_t i = 0; + + do{ + status |= VL53L1X_ULP_RdByte(dev, + VL53L1X_ULP_FIRMWARE__SYSTEM_STATUS, &tmp); + + if(tmp == (uint8_t)0x3) /* Sensor booted */ + { + continue_loop = (uint8_t)0; + } + else if(i < (uint16_t)1000) /* Wait for boot */ + { + i++; + } + else /* Timeout 1000ms reached */ + { + continue_loop = (uint8_t)0; + status |= (uint8_t)VL53L1X_ULP_ERROR_TIMEOUT; + } + VL53L1X_ULP_WaitMs(1); + }while(continue_loop == (uint8_t)1); + + /* Load default configuration */ + for (Addr = (uint8_t)0x2D; Addr <= (uint8_t)0x87; Addr++) + { + status |= VL53L1X_ULP_WrByte(dev, Addr, + VL53L1X_ULP_DEFAULT_CONFIGURATION[ + Addr - (uint8_t)0x2D]); + } + + /* Start VHV */ + status |= VL53L1X_ULP_WrByte(dev, VL53L1X_ULP_SYSTEM_START, (uint8_t)0x40); + i = (uint8_t)0; + continue_loop = (uint8_t)1; + do{ + status |= VL53L1X_ULP_CheckForDataReady(dev, &tmp); + if(tmp == (uint8_t)1) /* Data ready */ + { + continue_loop = (uint8_t)0; + } + else if(i < (uint16_t)1000) /* Wait for answer */ + { + i++; + } + else /* Timeout 1000ms reached */ + { + continue_loop = (uint8_t)0; + status |= (uint8_t)VL53L1X_ULP_ERROR_TIMEOUT; + } + VL53L1X_ULP_WaitMs(1); + }while(continue_loop == (uint8_t)1); + + status |= VL53L1X_ULP_ClearInterrupt(dev); + status |= VL53L1X_ULP_StopRanging(dev); + status |= VL53L1X_ULP_WrByte(dev, + VL53L1X_ULP_VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND, + (uint8_t)0x09); + status |= VL53L1X_ULP_WrByte(dev, 0x0B, (uint8_t)0); + status |= VL53L1X_ULP_WrWord(dev, 0x0024, 0x500); + status |= VL53L1X_ULP_WrByte(dev, 0x81, 0b10001010); + status |= VL53L1X_ULP_WrByte(dev, 0x004B, 0x03); + + /* Set default inter-measurement */ + status |= VL53L1X_ULP_SetInterMeasurementInMs(dev, 1000); + + return status; +} + +uint8_t VL53L1X_ULP_CheckForDataReady( + uint16_t dev, + uint8_t *p_is_data_ready) +{ + uint8_t status = VL53L1X_ULP_ERROR_NONE; + uint8_t temp; + uint8_t int_pol; + + status |= VL53L1X_ULP_RdByte(dev, VL53L1X_ULP_GPIO_HV_MUX__CTRL, &temp); + temp = temp & (uint8_t)0x10; + temp = temp >> 4; + + if (temp == (uint8_t)1) + { + int_pol = (uint8_t)0; + } + else + { + int_pol = (uint8_t)1; + } + + status |= VL53L1X_ULP_RdByte(dev, VL53L1X_ULP_GPIO__TIO_HV_STATUS, &temp); + + if ((temp & (uint8_t)1) == int_pol) + { + *p_is_data_ready = (uint8_t)1; + } + else + { + *p_is_data_ready = (uint8_t)0; + } + + return status; +} + +uint8_t VL53L1X_ULP_ClearInterrupt( + uint16_t dev) +{ + uint8_t status = VL53L1X_ULP_ERROR_NONE; + + status |= VL53L1X_ULP_WrByte(dev, VL53L1X_ULP_SYSTEM__INTERRUPT_CLEAR, 0x01); + return status; +} + +uint8_t VL53L1X_ULP_StartRangingSingleShot( + uint16_t dev) +{ + uint8_t status = VL53L1X_ULP_ERROR_NONE; + + status |= VL53L1X_ULP_WrByte(dev, VL53L1X_ULP_SYSTEM_START, 0x10); + return status; +} + +uint8_t VL53L1X_ULP_StartRanging( + uint16_t dev) +{ + uint8_t status = VL53L1X_ULP_ERROR_NONE; + + status |= VL53L1X_ULP_WrByte(dev, VL53L1X_ULP_SYSTEM_START, 0x40); + return status; +} + +uint8_t VL53L1X_ULP_StopRanging( + uint16_t dev) +{ + uint8_t status = VL53L1X_ULP_ERROR_NONE; + + status |= VL53L1X_ULP_WrByte(dev, VL53L1X_ULP_SYSTEM_START, 0x00); + return status; +} + +uint8_t VL53L1X_ULP_DumpDebugData( + uint16_t dev, + uint8_t *p_measurement_status, + uint16_t *p_estimated_distance_mm, + uint16_t *p_sigma_mm, + uint16_t *p_signal_kcps, + uint16_t *p_ambient_kcps) +{ + uint8_t status = VL53L1X_ULP_ERROR_NONE; + + uint8_t status_rtn[24] = { 255, 255, 255, 5, 2, 4, 1, 7, 3, 0, + 255, 255, 9, 13, 255, 255, 255, 255, 10, 6, + 255, 255, 11, 12 + }; + + status |= VL53L1X_ULP_RdByte(dev, 0x0089, p_measurement_status); + status |= VL53L1X_ULP_RdWord(dev, 0x0096, p_estimated_distance_mm); + status |= VL53L1X_ULP_RdWord(dev, 0x008E, p_signal_kcps); + status |= VL53L1X_ULP_RdWord(dev, 0x0092, p_sigma_mm); + status |= VL53L1X_ULP_RdWord(dev, 0x0090, p_ambient_kcps); + + (*p_signal_kcps) *= (uint16_t)8; + (*p_sigma_mm) /= (uint16_t)4; + (*p_ambient_kcps) *= (uint16_t)8; + + *p_measurement_status = (*p_measurement_status) & (uint8_t)0x1F; + if ((*p_measurement_status) < (uint8_t)24) + { + *p_measurement_status = status_rtn[(*p_measurement_status)]; + } + + return status; +} + + +uint8_t VL53L1X_ULP_SetMacroTiming( + uint16_t dev, + uint16_t macro_timing) +{ + uint8_t status = VL53L1X_ULP_ERROR_NONE; + + if(((uint16_t)macro_timing >= (uint16_t)1) + && ((uint16_t)macro_timing <= (uint16_t)255)) + { + status |= VL53L1X_ULP_WrWord(dev, + VL53L1X_ULP_RANGE_CONFIG_A, macro_timing); + status |= VL53L1X_ULP_WrWord(dev, + VL53L1X_ULP_RANGE_CONFIG_B, + macro_timing + (uint16_t)0x1); + } + else + { + status = VL53L1X_ULP_ERROR_INVALID_ARGUMENT; + } + + return status; +} + +uint8_t VL53L1X_ULP_GetMacroTiming( + uint16_t dev, + uint16_t *p_macro_timing) +{ + uint8_t status = VL53L1X_ULP_ERROR_NONE; + + status |= VL53L1X_ULP_RdWord(dev, + VL53L1X_ULP_RANGE_CONFIG_A, p_macro_timing); + + return status; +} + +uint8_t VL53L1X_ULP_SetInterMeasurementInMs( + uint16_t dev, + uint32_t inter_measurement_ms) +{ + uint8_t status = VL53L1X_ULP_ERROR_NONE; + uint16_t clock_pll; + float_t inter_measurement_factor = (float_t)1.055; + + if(((uint32_t)inter_measurement_ms >= (uint32_t)10) + && ((uint32_t)inter_measurement_ms <= (uint32_t)60000)) + { + status |= VL53L1X_ULP_RdWord(dev, + VL53L1X_ULP_RESULT__OSC_CALIBRATE_VAL, &clock_pll); + clock_pll = clock_pll & (uint16_t)0x3FF; + inter_measurement_factor = inter_measurement_factor + * (float_t)inter_measurement_ms + * (float_t)clock_pll; + + status |= VL53L1X_ULP_WrDWord(dev, VL53L1X_ULP_INTERMEASUREMENT_MS, + (uint32_t)inter_measurement_factor); + } + else + { + status = VL53L1X_ULP_ERROR_INVALID_ARGUMENT; + } + + return status; +} + +uint8_t VL53L1X_ULP_GetInterMeasurementInMs( + uint16_t dev, + uint32_t *p_inter_measurement_ms) +{ + uint8_t status = VL53L1X_ULP_ERROR_NONE; + uint16_t clock_pll; + uint32_t tmp; + float_t clock_pll_factor = (float_t)1.055; + + status |= VL53L1X_ULP_RdDWord(dev, VL53L1X_ULP_INTERMEASUREMENT_MS, &tmp); + status |= VL53L1X_ULP_RdWord(dev, + VL53L1X_ULP_RESULT__OSC_CALIBRATE_VAL, &clock_pll); + + if(clock_pll == (uint16_t)0) + { + status |= VL53L1X_ULP_ERROR_INVALID_ARGUMENT; + } + else + { + clock_pll = clock_pll & (uint16_t)0x3FF; + clock_pll_factor = clock_pll_factor * (float_t)clock_pll; + clock_pll = (uint16_t)clock_pll_factor; + *p_inter_measurement_ms = (uint16_t)(tmp/(uint32_t)clock_pll); + } + + return status; +} + +uint8_t VL53L1X_ULP_SetROI( + uint16_t dev, + uint8_t roi_width) +{ + uint8_t tmp, status = VL53L1X_ULP_ERROR_NONE; + + status |= VL53L1X_ULP_RdByte(dev, 0x013E, &tmp); + + if(((roi_width >= (uint8_t)4)) + && ((roi_width <= (uint8_t)16))) + { + if (roi_width > (uint8_t)10) + { + tmp = (uint8_t)199; + } + status |= VL53L1X_ULP_WrByte(dev, 0x007F, tmp); + status |= VL53L1X_ULP_WrByte(dev, 0x0080, + ((roi_width - (uint8_t)1) << 4) + | (roi_width - (uint8_t)1)); + } + else + { + status |= VL53L1X_ULP_ERROR_INVALID_ARGUMENT; + } + + return status; +} + +uint8_t VL53L1X_ULP_GetROI( + uint16_t dev, + uint8_t *p_roi_width) +{ + uint8_t tmp, status = VL53L1X_ULP_ERROR_NONE; + + status |= VL53L1X_ULP_RdByte(dev, 0x0080, &tmp); + *p_roi_width = (tmp & (uint8_t)0x0F) + (uint8_t)1; + + return status; +} + +uint8_t VL53L1X_ULP_SetInterruptConfiguration( + uint16_t dev, + uint16_t distance_threshold_mm, + uint8_t enable_interrupt_only_below_threshold) +{ + uint8_t tmp, status = VL53L1X_ULP_ERROR_NONE; + + if(enable_interrupt_only_below_threshold == (uint8_t)0) + { + tmp = (uint8_t)0x20; + } + else + { + tmp = (uint8_t)0x0; + } + + status |= VL53L1X_ULP_WrByte(dev, + VL53L1X_ULP_SYSTEM__INTERRUPT, tmp); + status |= VL53L1X_ULP_WrWord(dev, + VL53L1X_ULP_THRESH_HIGH, distance_threshold_mm); + status |= VL53L1X_ULP_WrWord(dev, + VL53L1X_ULP_THRESH_LOW, distance_threshold_mm); + return status; +} + +uint8_t VL53L1X_ULP_GetInterruptConfiguration( + uint16_t dev, + uint16_t *p_distance_threshold_mm, + uint8_t *p_interrupt_enabled_only_below_threshold) +{ + uint8_t tmp, status = VL53L1X_ULP_ERROR_NONE; + + status |= VL53L1X_ULP_RdWord(dev, + VL53L1X_ULP_THRESH_HIGH, p_distance_threshold_mm); + status |= VL53L1X_ULP_RdByte(dev, + VL53L1X_ULP_SYSTEM__INTERRUPT, &tmp); + + if(tmp == (uint8_t)0x20) + { + *p_interrupt_enabled_only_below_threshold = 0; + } + else + { + *p_interrupt_enabled_only_below_threshold = 1; + } + + return status; +} + +uint8_t VL53L1X_ULP_SetSignalThreshold( + uint16_t dev, + uint16_t signal_kcps) +{ + uint8_t status = VL53L1X_ULP_ERROR_NONE; + + if(((signal_kcps >= (uint16_t)1)) + && ((signal_kcps <= (uint16_t)16384))) + { + status |= VL53L1X_ULP_WrWord(dev, + VL53L1X_ULP_MIN_COUNT_RATE_RTN_LIMIT_MCPS,signal_kcps>>3); + } + else + { + status |= VL53L1X_ULP_ERROR_INVALID_ARGUMENT; + } + + return status; +} + +uint8_t VL53L1X_ULP_GetSignalThreshold( + uint16_t dev, + uint16_t *p_signal_kcps) +{ + uint8_t status = VL53L1X_ULP_ERROR_NONE; + uint16_t tmp = 0; + + status |= VL53L1X_ULP_RdWord(dev, + VL53L1X_ULP_MIN_COUNT_RATE_RTN_LIMIT_MCPS, &tmp); + *p_signal_kcps = tmp <<3; + + return status; +} + +uint8_t VL53L1X_ULP_SetSigmaThreshold( + uint16_t dev, + uint16_t sigma_mm) +{ + uint8_t status = VL53L1X_ULP_ERROR_NONE; + + if(sigma_mm>(uint16_t)((uint16_t)0xFFFF>>2)) + { + status |= (uint8_t)VL53L1X_ULP_ERROR_INVALID_ARGUMENT; + } + else + { + status |= VL53L1X_ULP_WrWord(dev, + VL53L1X_ULP_RANGE_CONFIG__SIGMA_THRESH, sigma_mm<<2); + } + + return status; +} + +uint8_t VL53L1X_ULP_GetSigmaThreshold( + uint16_t dev, + uint16_t *p_sigma_mm) +{ + uint8_t status = VL53L1X_ULP_ERROR_NONE; + + status |= VL53L1X_ULP_RdWord(dev, + VL53L1X_ULP_RANGE_CONFIG__SIGMA_THRESH, p_sigma_mm); + *p_sigma_mm = *p_sigma_mm >> 2; + + return status; +} diff --git a/vl53lx_uld/VL53L1X_ULP_api.h b/vl53lx_uld/VL53L1X_ULP_api.h new file mode 100644 index 0000000..a821f62 --- /dev/null +++ b/vl53lx_uld/VL53L1X_ULP_api.h @@ -0,0 +1,419 @@ +/* +* Copyright (c) 2021, STMicroelectronics - All Rights Reserved +* +* This file : part of VL53L1X ULP and : dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document : strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1X ULP may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* 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 VL53L1X api.h + * @brief Functions definition + */ + +#ifndef VL53L1X_ULP_API_H_ +#define VL53L1X_ULP_API_H_ + +#include "VL53L1X_ULP_platform.h" + +#define VL53L1X_ULP_VERSION "1.0.0" + +/** + * @brief Error types. + */ + +#define VL53L1X_ULP_ERROR_NONE ((uint8_t)0U) +#define VL53L1X_ULP_ERROR_INVALID_ARGUMENT ((uint8_t)254U) +#define VL53L1X_ULP_ERROR_TIMEOUT ((uint8_t)255U) + + +/** + * @brief Firmware addresses. + */ + + +#define VL53L1X_ULP_I2C_SLAVE__DEVICE_ADDRESS ((uint16_t)0x0001) +#define VL53L1X_ULP_VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND ((uint16_t)0x0008) +#define VL53L1X_ULP_GPIO_HV_MUX__CTRL ((uint16_t)0x0030) +#define VL53L1X_ULP_GPIO__TIO_HV_STATUS ((uint16_t)0x0031) +#define VL53L1X_ULP_SYSTEM__INTERRUPT ((uint16_t)0x0046) +#define VL53L1X_ULP_RANGE_CONFIG_A ((uint16_t)0x005E) +#define VL53L1X_ULP_RANGE_CONFIG_B ((uint16_t)0x0061) +#define VL53L1X_ULP_RANGE_CONFIG__SIGMA_THRESH ((uint16_t)0x0064) +#define VL53L1X_ULP_MIN_COUNT_RATE_RTN_LIMIT_MCPS ((uint16_t)0x0066) +#define VL53L1X_ULP_INTERMEASUREMENT_MS ((uint16_t)0x006C) +#define VL53L1X_ULP_THRESH_HIGH ((uint16_t)0x0072) +#define VL53L1X_ULP_THRESH_LOW ((uint16_t)0x0074) +#define VL53L1X_ULP_POWER_GO1 ((uint16_t)0x0083) +#define VL53L1X_ULP_FIRMWARE_ENABLE ((uint16_t)0x0085) +#define VL53L1X_ULP_SYSTEM__INTERRUPT_CLEAR ((uint16_t)0x0086) +#define VL53L1X_ULP_SYSTEM_START ((uint16_t)0x0087) +#define VL53L1X_ULP_RESULT__RANGE_STATUS ((uint16_t)0x0089) +#define VL53L1X_ULP_RESULT__SPAD_NB ((uint16_t)0x008C) +#define VL53L1X_ULP_RESULT__SIGNAL_RATE ((uint16_t)0x008E) +#define VL53L1X_ULP_RESULT__AMBIENT_RATE ((uint16_t)0x0090) +#define VL53L1X_ULP_RESULT__SIGMA ((uint16_t)0x0092) +#define VL53L1X_ULP_RESULT__DISTANCE ((uint16_t)0x0096) +#define VL53L1X_ULP_RESULT__OSC_CALIBRATE_VAL ((uint16_t)0x00DE) +#define VL53L1X_ULP_FIRMWARE__SYSTEM_STATUS ((uint16_t)0x00E5) +#define VL53L1X_ULP_IDENTIFICATION__MODEL_ID ((uint16_t)0x010F) + +/** + * @brief Functions definitions. + */ + +/** + * @brief This function is used to get the sensor id of VL53L1X. The sensor id + * should be 0xEACC. + * @param (uint16_t) dev : Device address. + * @param (uint16_t) *p_id : Sensor id. + * @return (uint8_t) status : 0 if OK. + */ + +uint8_t VL53L1X_ULP_GetSensorId( + uint16_t dev, + uint16_t *p_id); + +/** + * @brief This function sets a new I2C address to a sensor. It can be used for + * example when multiple sensors share the same I2C bus. + * @param (uint16_t) dev : Device to update. + * @param (uint8_t) new_address : New I2C address. + * @return (uint8_t) status : 0 if I2C address has been correctly + * programmed. + */ + +uint8_t VL53L1X_ULP_SetI2CAddress( + uint16_t dev, + uint8_t new_address); + +/** + * @brief This function is used to initialize the sensor. + * @param (uint16_t) dev : Device address. + * @return (uint8_t) status : 0 if init is OK. + */ + +uint8_t VL53L1X_ULP_SensorInit( + uint16_t dev); + +/** + * @brief This function check if a new data is available by polling a dedicated + * register. + * @param (uint16_t) dev : Device address. + * @param (uint8_t) *p_is_data_ready : Pointer containing a flag to know if a + * data is ready : 0 = no data ready, 1 = data ready. + * @return (uint8_t) status : 0 if OK. + */ + +uint8_t VL53L1X_ULP_CheckForDataReady( + uint16_t dev, + uint8_t *p_is_data_ready); + +/** + * @brief This function clears the interrupt. It needs to be called after a + * ranging data reading to arm the interrupt for the next data ready event. + * @param (uint16_t) dev : Device address. + * @return (uint8_t) status : 0 if OK. + */ + +uint8_t VL53L1X_ULP_ClearInterrupt( + uint16_t dev); + +/** + * @brief This function starts a ranging session for only one measurement. + * @param (uint16_t) dev : Device address. + * @return (uint8_t) status : 0 if OK. + */ + +uint8_t VL53L1X_ULP_StartRangingSingleShot( + uint16_t dev); + +/** + * @brief This function starts a ranging session. A manual clear interrupt has + * to be done to restart the next measurement. + * @param (uint16_t) dev : Device address. + * @return (uint8_t) status : 0 if OK. + */ + +uint8_t VL53L1X_ULP_StartRanging( + uint16_t dev); + +/** + * @brief This function stops the ranging in progress. + * @param (uint16_t) dev : Device address. + * @return (uint8_t) status : 0 if OK. + */ + +uint8_t VL53L1X_ULP_StopRanging( + uint16_t dev); + +/** + * @brief This function can be used to dump the debug data (estimated distance, + * measurement status, etc). It is particularly useful to tune the device for a + * specific application. The function can be used when a new measurement is + * ready, after clearing the interrupt. + * @param (uint16_t) dev : Device address. + * @param (uint8_t) *p_measurement_status : Measurement status. A value equal to + * 0 means that the estimated distance should be close to the reality. + * @param (uint16_t) *p_estimated_distance_mm : Estimated target distance in mm. + * @param (uint8_t) *p_sigma_mm : Estimated measurements std deviation in mm. + * @param (uint16_t) *p_signal_kcps : Estimated signal rate of the target in kcps. + * @param (uint16_t) *p_signal_mm : Ambient noise from external light in kcps. + * @return (uint8_t) status : 0 if OK. + */ + +uint8_t VL53L1X_ULP_DumpDebugData( + uint16_t dev, + uint8_t *p_measurement_status, + uint16_t *p_estimated_distance_mm, + uint16_t *p_sigma_mm, + uint16_t *p_signal_kcps, + uint16_t *p_ambient_kcps); + +/** + * @brief Macro timing is equivalent to integration time. A high value increases + * the maximum ranging distance and accuracy, but it also increase the power + * consumption. This function is used to program a new value. + * @param (uint16_t) dev : Device address. + * @param (uint16_t) macro_timing : Macro timing value. Value needs to be + * between 1 and 255. Default is 1 (lowest power consumption). + * @return (uint8_t) status : 0 if OK, or 254 if macro timing is invalid. + */ + +uint8_t VL53L1X_ULP_SetMacroTiming( + uint16_t dev, + uint16_t macro_timing); + +/** + * @brief Macro timing is equivalent to integration time. A high value increases + * the maximum ranging distance and accuracy, but it also increase the power + * consumption. This function is used to get the programmed value. + * @param (uint16_t) dev : Device address. + * @param (uint16_t) *p_macro_timing : Programmed macro timing value. + * @return (uint8_t) status : 0 if OK. + */ + +uint8_t VL53L1X_ULP_GetMacroTiming( + uint16_t dev, + uint16_t *p_macro_timing); + +/** + * @brief This function can be used to program the time between 2 + * consecutive measurements. + * @param (uint16_t) dev : Device address. + * @param (uint32_t) inter_measurement_ms : Time in milliseconds between 2 + * measurements. Min value is 20ms and max is 60000ms. Default is 100ms. + * @return (uint8_t) status : 0 if OK, or 254 if inter-measurement is invalid. + */ + +uint8_t VL53L1X_ULP_SetInterMeasurementInMs( + uint16_t dev, + uint32_t inter_measurement_ms); + +/** + * @brief This function can be used to get the programmed time between 2 + * consecutive measurements. + * @param (uint16_t) dev : Device address. + * @param (uint32_t) *p_inter_measurement_ms : Time in milliseconds between 2 + * measurements. + * @return (uint8_t) status : 0 if OK. + */ + +uint8_t VL53L1X_ULP_GetInterMeasurementInMs( + uint16_t dev, + uint32_t *p_inter_measurement_ms); + +/** + * @brief This function can be used to change the number of SPADs enabled. The + * VL53L1X uses by default a matrix of 256 SPADs which can be reduced. A + * reduced number of SPADs reduces the power consumption, but is also reduces + * the maximum ranging distance and accuracy. By default all SPADs are enabled + * (max ranging distance). + * IMPORTANT : Reducing the number of SPADs does't reduce the FOV. + * @param (uint16_t) dev : Device address. + * @param (uint8_t) roi_width : Size of ROI. The minimum width is 4 (4x4=16 + * SPADs), and the maximum is 16 (16x16=256 SPADs). + * @return (uint8_t) status : 0 if OK, or 254 if roi is invalid. + */ + +uint8_t VL53L1X_ULP_SetROI( + uint16_t dev, + uint8_t roi_width); + +/** + * @brief This function can be used to get the number of SPADs enabled. The + * VL53L1X uses by default a matrix of 256 SPADs which can be reduced. A + * reduced number of SPADs reduces the power consumption, but is also reduces + * the maximum ranging distance and accuracy. By default all SPADs are enabled + * (max ranging distance). + * IMPORTANT : Reducing the number of SPADs does't reduce the FOV. + * @param (uint16_t) dev : Device address. + * @param (uint8_t) *p_roi_width : Size of ROI. + * @return (uint8_t) status : 0 if OK. + */ + +uint8_t VL53L1X_ULP_GetROI( + uint16_t dev, + uint8_t *p_roi_width); + +/** + * @brief This function can be used to program the interrupt. There are 2 + * possible configurations : + * - 1) Interrupt raised when a new measurement is ready, even if the distance + * is wrong. It can be used to debug and tune the sensor. + * - 2) Interrupt raised only when a target is detected. This is more for real + * scene applications. + * By default the sensor is programmed for the first case, it raises an + * interrupt any new measurement is ready. + * @param (uint16_t) dev : Device address. + * @param (uint16_t) distance_threshold_mm : Below this threshold, the + * interrupt will be raised if the measurement is valid (status 0). + * @param (uint8_t) enable_interrupt_only_below_threshold : If this flag is set + * to 0, the sensor is programmed with the first configuration (raise an + * interrupt when a new measurement is ready). Else, the sensor is programmed + * to raise an interrupt ONLY when a valid distance below the threshold is + * reported. + * @return (uint8_t) status : 0 if OK. + */ + +uint8_t VL53L1X_ULP_SetInterruptConfiguration( + uint16_t dev, + uint16_t distance_threshold_mm, + uint8_t enable_interrupt_only_below_threshold); + +/** + * @brief This function can be used to get the programmed the interrupt. There + * are 2 possible configurations : + * - 1) Interrupt raised when a new measurement is ready, even if the distance + * is wrong. It can be used to debug and tune the sensor. + * - 2) Interrupt raised only when a target is detected. This is more for real + * scene applications. + * By default the sensor is programmed for the first case, it raises an + * interrupt any new measurement is ready. + * @param (uint16_t) dev : Device address. + * @param (uint16_t) *p_distance_threshold_mm : Below this threshold, the + * interrupt will be raised if the measurement is valid (status 0). + * @param (uint8_t) *p_interrupt_enabled_only_below_threshold : If this flag is + * set to 0, the sensor is programmed with the first configuration (raise an + * interrupt when a new measurement is ready). Else, the sensor is programmed + * to raise an interrupt ONLY when a valid distance below the threshold is + * reported. + * @return (uint8_t) status : 0 if OK. + */ + +uint8_t VL53L1X_ULP_GetInterruptConfiguration( + uint16_t dev, + uint16_t *p_distance_threshold_mm, + uint8_t *p_interrupt_enabled_only_below_threshold); + +/** + * @brief This function sets a new signal threshold in kcps. If a + * target has a lower signal as the programmed value, the measurement status in + * debug value will be equal to 2. + * @param (uint16_t) dev : Device address. + * @param (uint16_t) signal_kcps : New signal threshold in kcps. The default + * value is 1500 kcps. Minimum is 1 kcps, and maximum is 16384 kcps. + * @return (uint8_t) status : 0 if OK, or 254 if the threshold is not valid. + */ + +uint8_t VL53L1X_ULP_SetSignalThreshold( + uint16_t dev, + uint16_t signal_kcps); + +/** + * @brief This function returns the current signal threshold in kcps. If a + * target has a lower signal as the programmed value, the measurement status in + * debug value will be equal to 2. + * @param (uint16_t) dev : Device address. + * @param (uint16_t) *p_signal_kcps : Pointer of signal threshold in kcps. + * @return (uint8_t) status : 0 if OK. + */ + +uint8_t VL53L1X_ULP_GetSignalThreshold( + uint16_t dev, + uint16_t *p_signal_kcps); + +/** + * @brief This function programs a new sigma threshold. The sigma corresponds to + * the standard deviation of the returned pulse. If the computed sigma is above + * the programmed value, the measurement status in debug value will be equal to + * 1. + * @param (uint16_t) dev : Device address. + * @param (uint16_t) sigma_mm : New sigma threshold in mm. The default value is + * 45mm. Minimum is 1mm, and maximum is 16383mm. +* @return (uint8_t) status : 0 if OK, or 254 if the threshold is not valid. + */ + +uint8_t VL53L1X_ULP_SetSigmaThreshold( + uint16_t dev, + uint16_t sigma_mm); + +/** + * @brief This function gets the current sigma threshold. The sigma corresponds + * to the standard deviation of the returned pulse. If the computed sigma is + * above the programmed value, the measurement status in debug value will be + * equal to 1. + * @param (uint16_t) dev : Device address. + * @param (uint16_t) *p_sigma_mm : Current sigma threshold in mm. + * @return (uint8_t) status : 0 if OK. + */ + +uint8_t VL53L1X_ULP_GetSigmaThreshold( + uint16_t dev, + uint16_t *p_sigma_mm); + +#endif diff --git a/vl53lx_uld/VL53L1X_ULP_platform.c b/vl53lx_uld/VL53L1X_ULP_platform.c new file mode 100644 index 0000000..3f732d3 --- /dev/null +++ b/vl53lx_uld/VL53L1X_ULP_platform.c @@ -0,0 +1,149 @@ +/* + Copyright (c) 2021, STMicroelectronics - All Rights Reserved + + This file : part of VL53L1X ULP and : dual licensed, + either 'STMicroelectronics + Proprietary license' + or 'BSD 3-clause "New" or "Revised" License' , at your option. + +******************************************************************************* + + 'STMicroelectronics Proprietary license' + +******************************************************************************* + + License terms: STMicroelectronics Proprietary in accordance with licensing + terms at www.st.com/sla0081 + + STMicroelectronics confidential + Reproduction and Communication of this document : strictly prohibited unless + specifically authorized in writing by STMicroelectronics. + + +******************************************************************************* + + Alternatively, VL53L1X ULP may be distributed under the terms of + 'BSD 3-clause "New" or "Revised" License', in which case the following + provisions apply instead of the ones mentioned above : + +******************************************************************************* + + License terms: BSD 3-clause "New" or "Revised" License. + + 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. +******************************************************************************* +*/ + +#include "VL53L1X_ULP_platform.h" + +extern I2C_HandleTypeDef hi2c2; + +uint8_t VL53L1X_ULP_RdDWord(uint16_t dev, uint16_t RegisterAdress, uint32_t *value) +{ + uint8_t status = 0; + uint8_t data_write[2]; + uint8_t data_read[4]; + + data_write[0] = (RegisterAdress >> 8) & 0xFF; + data_write[1] = RegisterAdress & 0xFF; + status = HAL_I2C_Master_Transmit(&hi2c2, dev, data_write, 2, 100); + status = HAL_I2C_Master_Receive(&hi2c2, dev, data_read, 4, 100); + *value = ((data_read[0] << 24) | (data_read[1] << 16) | + (data_read[2] << 8) | (data_read[3])); + return status; +} + +uint8_t VL53L1X_ULP_RdWord(uint16_t dev, uint16_t RegisterAdress, uint16_t *value) +{ + uint8_t status = 0; + uint8_t data_write[2]; + uint8_t data_read[2]; + + data_write[0] = (RegisterAdress >> 8) & 0xFF; + data_write[1] = RegisterAdress & 0xFF; + status = HAL_I2C_Master_Transmit(&hi2c2, dev, data_write, 2, 100); + status = HAL_I2C_Master_Receive(&hi2c2, dev, data_read, 2, 100); + *value = (data_read[0] << 8) | (data_read[1]); + return status; +} + +uint8_t VL53L1X_ULP_RdByte(uint16_t dev, uint16_t RegisterAdress, uint8_t *value) +{ + uint8_t status = 0; + uint8_t data_write[2]; + uint8_t data_read[1]; + + data_write[0] = (RegisterAdress >> 8) & 0xFF; + data_write[1] = RegisterAdress & 0xFF; + status = HAL_I2C_Master_Transmit(&hi2c2, dev, data_write, 2, 100); + status = HAL_I2C_Master_Receive(&hi2c2, dev, data_read, 1, 100); + *value = data_read[0]; + return status; +} + +uint8_t VL53L1X_ULP_WrByte(uint16_t dev, uint16_t RegisterAdress, uint8_t value) +{ + uint8_t data_write[3]; + uint8_t status = 0; + + data_write[0] = (RegisterAdress >> 8) & 0xFF; + data_write[1] = RegisterAdress & 0xFF; + data_write[2] = value & 0xFF; + status = HAL_I2C_Master_Transmit(&hi2c2, dev, data_write, 3, 100); + return status; +} + +uint8_t VL53L1X_ULP_WrWord(uint16_t dev, uint16_t RegisterAdress, uint16_t value) +{ + uint8_t data_write[4]; + uint8_t status = 0; + data_write[0] = (RegisterAdress >> 8) & 0xFF; + data_write[1] = RegisterAdress & 0xFF; + data_write[2] = (value >> 8) & 0xFF; + data_write[3] = value & 0xFF; + status = HAL_I2C_Master_Transmit(&hi2c2, dev, data_write, 4, 100); + return status; +} + +uint8_t VL53L1X_ULP_WrDWord(uint16_t dev, uint16_t RegisterAdress, uint32_t value) +{ + uint8_t data_write[6]; + uint8_t status = 0; + + data_write[0] = (RegisterAdress >> 8) & 0xFF; + data_write[1] = RegisterAdress & 0xFF; + data_write[2] = (value >> 24) & 0xFF; + data_write[3] = (value >> 16) & 0xFF; + data_write[4] = (value >> 8) & 0xFF; + data_write[5] = value & 0xFF; + status = HAL_I2C_Master_Transmit(&hi2c2, dev, data_write, 6, 100); + return status; +} + +void VL53L1X_ULP_WaitMs(uint32_t TimeMs) +{ + HAL_Delay(TimeMs); +} diff --git a/vl53lx_uld/VL53L1X_ULP_platform.h b/vl53lx_uld/VL53L1X_ULP_platform.h new file mode 100644 index 0000000..5918002 --- /dev/null +++ b/vl53lx_uld/VL53L1X_ULP_platform.h @@ -0,0 +1,110 @@ +/* + Copyright (c) 2021, STMicroelectronics - All Rights Reserved + + This file : part of VL53L1X ULP and : dual licensed, + either 'STMicroelectronics + Proprietary license' + or 'BSD 3-clause "New" or "Revised" License' , at your option. + +******************************************************************************* + + 'STMicroelectronics Proprietary license' + +******************************************************************************* + + License terms: STMicroelectronics Proprietary in accordance with licensing + terms at www.st.com/sla0081 + + STMicroelectronics confidential + Reproduction and Communication of this document : strictly prohibited unless + specifically authorized in writing by STMicroelectronics. + + +******************************************************************************* + + Alternatively, VL53L1X ULP may be distributed under the terms of + 'BSD 3-clause "New" or "Revised" License', in which case the following + provisions apply instead of the ones mentioned above : + +******************************************************************************* + + License terms: BSD 3-clause "New" or "Revised" License. + + 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. +******************************************************************************* +*/ + +#ifndef _VL53L1X_ULP_PLATFORM_H_ +#define _VL53L1X_ULP_PLATFORM_H_ +#pragma once + +#include +#include + + +/** + * @brief Read 32 bits through I2C. + */ + +uint8_t VL53L1X_ULP_RdDWord(uint16_t dev, uint16_t registerAddr, uint32_t *value); + +/** + * @brief Read 16 bits through I2C. + */ + +uint8_t VL53L1X_ULP_RdWord(uint16_t dev, uint16_t registerAddr, uint16_t *value); + +/** + * @brief Read 8 bits through I2C. + */ + +uint8_t VL53L1X_ULP_RdByte(uint16_t dev, uint16_t registerAddr, uint8_t *value); + +/** + * @brief Write 8 bits through I2C. + */ + +uint8_t VL53L1X_ULP_WrByte(uint16_t dev, uint16_t registerAddr, uint8_t value); + +/** + * @brief Write 16 bits through I2C. + */ + +uint8_t VL53L1X_ULP_WrWord(uint16_t dev, uint16_t RegisterAdress, uint16_t value); + +/** + * @brief Write 32 bits through I2C. + */ + +uint8_t VL53L1X_ULP_WrDWord(uint16_t dev, uint16_t RegisterAdress, uint32_t value); + +/** + * @brief Wait during N milliseconds. + */ + +void VL53L1X_ULP_WaitMs(uint32_t TimeMs); + +#endif // _VL53L1X_ULP_PLATFORM_H_ diff --git a/vl53lx_uld/VL53L1X_api.c b/vl53lx_uld/VL53L1X_api.c new file mode 100644 index 0000000..49e8ed3 --- /dev/null +++ b/vl53lx_uld/VL53L1X_api.c @@ -0,0 +1,850 @@ +/* + Copyright (c) 2017, STMicroelectronics - All Rights Reserved + + This file : part of VL53L1 Core and : dual licensed, + either 'STMicroelectronics + Proprietary license' + or 'BSD 3-clause "New" or "Revised" License' , at your option. + +******************************************************************************* + + 'STMicroelectronics Proprietary license' + +******************************************************************************* + + License terms: STMicroelectronics Proprietary in accordance with licensing + terms at www.st.com/sla0081 + + STMicroelectronics confidential + Reproduction and Communication of this document : strictly prohibited unless + specifically authorized in writing by STMicroelectronics. + + +******************************************************************************* + + Alternatively, VL53L1 Core may be distributed under the terms of + 'BSD 3-clause "New" or "Revised" License', in which case the following + provisions apply instead of the ones mentioned above : + +******************************************************************************* + + License terms: BSD 3-clause "New" or "Revised" License. + + 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 vl53l1x_api.c + * @brief Functions implementation + */ + +#include "VL53L1X_api.h" +#include + +#if 0 +uint8_t VL51L1X_NVM_CONFIGURATION[] = { +0x00, /* 0x00 : not user-modifiable */ +0x29, /* 0x01 : 7 bits I2C address (default=0x29), use SetI2CAddress(). Warning: after changing the register value to a new I2C address, the device will only answer to the new address */ +0x00, /* 0x02 : not user-modifiable */ +0x00, /* 0x03 : not user-modifiable */ +0x00, /* 0x04 : not user-modifiable */ +0x00, /* 0x05 : not user-modifiable */ +0x00, /* 0x06 : not user-modifiable */ +0x00, /* 0x07 : not user-modifiable */ +0x00, /* 0x08 : not user-modifiable */ +0x50, /* 0x09 : not user-modifiable */ +0x00, /* 0x0A : not user-modifiable */ +0x00, /* 0x0B : not user-modifiable */ +0x00, /* 0x0C : not user-modifiable */ +0x00, /* 0x0D : not user-modifiable */ +0x0a, /* 0x0E : not user-modifiable */ +0x00, /* 0x0F : not user-modifiable */ +0x00, /* 0x10 : not user-modifiable */ +0x00, /* 0x11 : not user-modifiable */ +0x00, /* 0x12 : not user-modifiable */ +0x00, /* 0x13 : not user-modifiable */ +0x00, /* 0x14 : not user-modifiable */ +0x00, /* 0x15 : not user-modifiable */ +0x00, /* 0x16 : Xtalk calibration value MSB (7.9 format in kcps), use SetXtalk() */ +0x00, /* 0x17 : Xtalk calibration value LSB */ +0x00, /* 0x18 : not user-modifiable */ +0x00, /* 0x19 : not user-modifiable */ +0x00, /* 0x1a : not user-modifiable */ +0x00, /* 0x1b : not user-modifiable */ +0x00, /* 0x1e : Part to Part offset x4 MSB (in mm), use SetOffset() */ +0x50, /* 0x1f : Part to Part offset x4 LSB */ +0x00, /* 0x20 : not user-modifiable */ +0x00, /* 0x21 : not user-modifiable */ +0x00, /* 0x22 : not user-modifiable */ +0x00, /* 0x23 : not user-modifiable */ +} +#endif + +const uint8_t VL51L1X_DEFAULT_CONFIGURATION[] = { +0x00, /* 0x2d : set bit 2 and 5 to 1 for fast plus mode (1MHz I2C), else don't touch */ +0x00, /* 0x2e : bit 0 if I2C pulled up at 1.8V, else set bit 0 to 1 (pull up at AVDD) */ +0x00, /* 0x2f : bit 0 if GPIO pulled up at 1.8V, else set bit 0 to 1 (pull up at AVDD) */ +0x01, /* 0x30 : set bit 4 to 0 for active high interrupt and 1 for active low (bits 3:0 must be 0x1), use SetInterruptPolarity() */ +0x02, /* 0x31 : bit 1 = interrupt depending on the polarity, use CheckForDataReady() */ +0x00, /* 0x32 : not user-modifiable */ +0x02, /* 0x33 : not user-modifiable */ +0x08, /* 0x34 : not user-modifiable */ +0x00, /* 0x35 : not user-modifiable */ +0x08, /* 0x36 : not user-modifiable */ +0x10, /* 0x37 : not user-modifiable */ +0x01, /* 0x38 : not user-modifiable */ +0x01, /* 0x39 : not user-modifiable */ +0x00, /* 0x3a : not user-modifiable */ +0x00, /* 0x3b : not user-modifiable */ +0x00, /* 0x3c : not user-modifiable */ +0x00, /* 0x3d : not user-modifiable */ +0xff, /* 0x3e : not user-modifiable */ +0x00, /* 0x3f : not user-modifiable */ +0x0F, /* 0x40 : not user-modifiable */ +0x00, /* 0x41 : not user-modifiable */ +0x00, /* 0x42 : not user-modifiable */ +0x00, /* 0x43 : not user-modifiable */ +0x00, /* 0x44 : not user-modifiable */ +0x00, /* 0x45 : not user-modifiable */ +0x20, /* 0x46 : interrupt configuration 0->level low detection, 1-> level high, 2-> Out of window, 3->In window, 0x20-> New sample ready , TBC */ +0x0b, /* 0x47 : not user-modifiable */ +0x00, /* 0x48 : not user-modifiable */ +0x00, /* 0x49 : not user-modifiable */ +0x02, /* 0x4a : not user-modifiable */ +0x0a, /* 0x4b : not user-modifiable */ +0x21, /* 0x4c : not user-modifiable */ +0x00, /* 0x4d : not user-modifiable */ +0x00, /* 0x4e : not user-modifiable */ +0x05, /* 0x4f : not user-modifiable */ +0x00, /* 0x50 : not user-modifiable */ +0x00, /* 0x51 : not user-modifiable */ +0x00, /* 0x52 : not user-modifiable */ +0x00, /* 0x53 : not user-modifiable */ +0xc8, /* 0x54 : not user-modifiable */ +0x00, /* 0x55 : not user-modifiable */ +0x00, /* 0x56 : not user-modifiable */ +0x38, /* 0x57 : not user-modifiable */ +0xff, /* 0x58 : not user-modifiable */ +0x01, /* 0x59 : not user-modifiable */ +0x00, /* 0x5a : not user-modifiable */ +0x08, /* 0x5b : not user-modifiable */ +0x00, /* 0x5c : not user-modifiable */ +0x00, /* 0x5d : not user-modifiable */ +0x01, /* 0x5e : not user-modifiable */ +0xcc, /* 0x5f : not user-modifiable */ +0x0f, /* 0x60 : not user-modifiable */ +0x01, /* 0x61 : not user-modifiable */ +0xf1, /* 0x62 : not user-modifiable */ +0x0d, /* 0x63 : not user-modifiable */ +0x01, /* 0x64 : Sigma threshold MSB (mm in 14.2 format for MSB+LSB), use SetSigmaThreshold(), default value 90 mm */ +0x68, /* 0x65 : Sigma threshold LSB */ +0x00, /* 0x66 : Min count Rate MSB (MCPS in 9.7 format for MSB+LSB), use SetSignalThreshold() */ +0x80, /* 0x67 : Min count Rate LSB */ +0x08, /* 0x68 : not user-modifiable */ +0xb8, /* 0x69 : not user-modifiable */ +0x00, /* 0x6a : not user-modifiable */ +0x00, /* 0x6b : not user-modifiable */ +0x00, /* 0x6c : Intermeasurement period MSB, 32 bits register, use SetIntermeasurementInMs() */ +0x00, /* 0x6d : Intermeasurement period */ +0x0f, /* 0x6e : Intermeasurement period */ +0x89, /* 0x6f : Intermeasurement period LSB */ +0x00, /* 0x70 : not user-modifiable */ +0x00, /* 0x71 : not user-modifiable */ +0x00, /* 0x72 : distance threshold high MSB (in mm, MSB+LSB), use SetD:tanceThreshold() */ +0x00, /* 0x73 : distance threshold high LSB */ +0x00, /* 0x74 : distance threshold low MSB ( in mm, MSB+LSB), use SetD:tanceThreshold() */ +0x00, /* 0x75 : distance threshold low LSB */ +0x00, /* 0x76 : not user-modifiable */ +0x01, /* 0x77 : not user-modifiable */ +0x0f, /* 0x78 : not user-modifiable */ +0x0d, /* 0x79 : not user-modifiable */ +0x0e, /* 0x7a : not user-modifiable */ +0x0e, /* 0x7b : not user-modifiable */ +0x00, /* 0x7c : not user-modifiable */ +0x00, /* 0x7d : not user-modifiable */ +0x02, /* 0x7e : not user-modifiable */ +0xc7, /* 0x7f : ROI center, use SetROI() */ +0xff, /* 0x80 : XY ROI (X=Width, Y=Height), use SetROI() */ +0x9B, /* 0x81 : not user-modifiable */ +0x00, /* 0x82 : not user-modifiable */ +0x00, /* 0x83 : not user-modifiable */ +0x00, /* 0x84 : not user-modifiable */ +0x01, /* 0x85 : not user-modifiable */ +0x00, /* 0x86 : clear interrupt, use ClearInterrupt() */ +0x00 /* 0x87 : start ranging, use StartRanging() or StopRanging(), If you want an automatic start after VL53L1X_init() call, put 0x40 in location 0x87 */ +}; + +static const uint8_t status_rtn[24] = { 255, 255, 255, 5, 2, 4, 1, 7, 3, 0, + 255, 255, 9, 13, 255, 255, 255, 255, 10, 6, + 255, 255, 11, 12 +}; + +VL53L1X_ERROR VL53L1X_GetSWVersion(VL53L1X_Version_t *pVersion) +{ + VL53L1X_ERROR Status = 0; + + pVersion->major = VL53L1X_IMPLEMENTATION_VER_MAJOR; + pVersion->minor = VL53L1X_IMPLEMENTATION_VER_MINOR; + pVersion->build = VL53L1X_IMPLEMENTATION_VER_SUB; + pVersion->revision = VL53L1X_IMPLEMENTATION_VER_REVISION; + return Status; +} + +VL53L1X_ERROR VL53L1X_SetI2CAddress(uint16_t dev, uint8_t new_address) +{ + VL53L1X_ERROR status = 0; + + status = VL53L1_WrByte(dev, VL53L1_I2C_SLAVE__DEVICE_ADDRESS, new_address >> 1); + return status; +} + +VL53L1X_ERROR VL53L1X_SensorInit(uint16_t dev) +{ + VL53L1X_ERROR status = 0; + uint8_t Addr = 0x00, tmp; + + for (Addr = 0x2D; Addr <= 0x87; Addr++){ + status = VL53L1_WrByte(dev, Addr, VL51L1X_DEFAULT_CONFIGURATION[Addr - 0x2D]); + } + status = VL53L1X_StartRanging(dev); + tmp = 0; + while(tmp==0){ + status = VL53L1X_CheckForDataReady(dev, &tmp); + } + status = VL53L1X_ClearInterrupt(dev); + status = VL53L1X_StopRanging(dev); + status = VL53L1_WrByte(dev, VL53L1_VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND, 0x09); /* two bounds VHV */ + status = VL53L1_WrByte(dev, 0x0B, 0); /* start VHV from the previous temperature */ + return status; +} + +VL53L1X_ERROR VL53L1X_ClearInterrupt(uint16_t dev) +{ + VL53L1X_ERROR status = 0; + + status = VL53L1_WrByte(dev, SYSTEM__INTERRUPT_CLEAR, 0x01); + return status; +} + +VL53L1X_ERROR VL53L1X_SetInterruptPolarity(uint16_t dev, uint8_t NewPolarity) +{ + uint8_t Temp; + VL53L1X_ERROR status = 0; + + status = VL53L1_RdByte(dev, GPIO_HV_MUX__CTRL, &Temp); + Temp = Temp & 0xEF; + status = VL53L1_WrByte(dev, GPIO_HV_MUX__CTRL, Temp | (!(NewPolarity & 1)) << 4); + return status; +} + +VL53L1X_ERROR VL53L1X_GetInterruptPolarity(uint16_t dev, uint8_t *pInterruptPolarity) +{ + uint8_t Temp; + VL53L1X_ERROR status = 0; + + status = VL53L1_RdByte(dev, GPIO_HV_MUX__CTRL, &Temp); + Temp = Temp & 0x10; + *pInterruptPolarity = !(Temp>>4); + return status; +} + +VL53L1X_ERROR VL53L1X_StartRanging(uint16_t dev) +{ + VL53L1X_ERROR status = 0; + + status = VL53L1_WrByte(dev, SYSTEM__MODE_START, 0x40); /* Enable VL53L1X */ + return status; +} + +VL53L1X_ERROR VL53L1X_StopRanging(uint16_t dev) +{ + VL53L1X_ERROR status = 0; + + status = VL53L1_WrByte(dev, SYSTEM__MODE_START, 0x00); /* Disable VL53L1X */ + return status; +} + +VL53L1X_ERROR VL53L1X_CheckForDataReady(uint16_t dev, uint8_t *isDataReady) +{ + uint8_t Temp; + uint8_t IntPol; + VL53L1X_ERROR status = 0; + + status = VL53L1X_GetInterruptPolarity(dev, &IntPol); + status = VL53L1_RdByte(dev, GPIO__TIO_HV_STATUS, &Temp); + /* Read in the register to check if a new value is available */ + if (status == 0){ + if ((Temp & 1) == IntPol) + *isDataReady = 1; + else + *isDataReady = 0; + } + return status; +} + +VL53L1X_ERROR VL53L1X_SetTimingBudgetInMs(uint16_t dev, uint16_t TimingBudgetInMs) +{ + uint16_t DM; + VL53L1X_ERROR status=0; + + status = VL53L1X_GetDistanceMode(dev, &DM); + if (DM == 0) + return 1; + else if (DM == 1) { /* Short DistanceMode */ + switch (TimingBudgetInMs) { + case 15: /* only available in short distance mode */ + VL53L1_WrWord(dev, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, + 0x01D); + VL53L1_WrWord(dev, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, + 0x0027); + break; + case 20: + VL53L1_WrWord(dev, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, + 0x0051); + VL53L1_WrWord(dev, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, + 0x006E); + break; + case 33: + VL53L1_WrWord(dev, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, + 0x00D6); + VL53L1_WrWord(dev, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, + 0x006E); + break; + case 50: + VL53L1_WrWord(dev, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, + 0x1AE); + VL53L1_WrWord(dev, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, + 0x01E8); + break; + case 100: + VL53L1_WrWord(dev, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, + 0x02E1); + VL53L1_WrWord(dev, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, + 0x0388); + break; + case 200: + VL53L1_WrWord(dev, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, + 0x03E1); + VL53L1_WrWord(dev, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, + 0x0496); + break; + case 500: + VL53L1_WrWord(dev, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, + 0x0591); + VL53L1_WrWord(dev, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, + 0x05C1); + break; + default: + status = 1; + break; + } + } else { + switch (TimingBudgetInMs) { + case 20: + VL53L1_WrWord(dev, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, + 0x001E); + VL53L1_WrWord(dev, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, + 0x0022); + break; + case 33: + VL53L1_WrWord(dev, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, + 0x0060); + VL53L1_WrWord(dev, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, + 0x006E); + break; + case 50: + VL53L1_WrWord(dev, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, + 0x00AD); + VL53L1_WrWord(dev, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, + 0x00C6); + break; + case 100: + VL53L1_WrWord(dev, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, + 0x01CC); + VL53L1_WrWord(dev, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, + 0x01EA); + break; + case 200: + VL53L1_WrWord(dev, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, + 0x02D9); + VL53L1_WrWord(dev, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, + 0x02F8); + break; + case 500: + VL53L1_WrWord(dev, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, + 0x048F); + VL53L1_WrWord(dev, RANGE_CONFIG__TIMEOUT_MACROP_B_HI, + 0x04A4); + break; + default: + status = 1; + break; + } + } + return status; +} + +VL53L1X_ERROR VL53L1X_GetTimingBudgetInMs(uint16_t dev, uint16_t *pTimingBudget) +{ + uint16_t Temp; + VL53L1X_ERROR status = 0; + + status = VL53L1_RdWord(dev, RANGE_CONFIG__TIMEOUT_MACROP_A_HI, &Temp); + switch (Temp) { + case 0x001D : + *pTimingBudget = 15; + break; + case 0x0051 : + case 0x001E : + *pTimingBudget = 20; + break; + case 0x00D6 : + case 0x0060 : + *pTimingBudget = 33; + break; + case 0x1AE : + case 0x00AD : + *pTimingBudget = 50; + break; + case 0x02E1 : + case 0x01CC : + *pTimingBudget = 100; + break; + case 0x03E1 : + case 0x02D9 : + *pTimingBudget = 200; + break; + case 0x0591 : + case 0x048F : + *pTimingBudget = 500; + break; + default: + status = 1; + *pTimingBudget = 0; + } + return status; +} + +VL53L1X_ERROR VL53L1X_SetDistanceMode(uint16_t dev, uint16_t DM) +{ + uint16_t TB; + VL53L1X_ERROR status = 0; + + status = VL53L1X_GetTimingBudgetInMs(dev, &TB); + if (status != 0) + return 1; + switch (DM) { + case 1: + status = VL53L1_WrByte(dev, PHASECAL_CONFIG__TIMEOUT_MACROP, 0x14); + status = VL53L1_WrByte(dev, RANGE_CONFIG__VCSEL_PERIOD_A, 0x07); + status = VL53L1_WrByte(dev, RANGE_CONFIG__VCSEL_PERIOD_B, 0x05); + status = VL53L1_WrByte(dev, RANGE_CONFIG__VALID_PHASE_HIGH, 0x38); + status = VL53L1_WrWord(dev, SD_CONFIG__WOI_SD0, 0x0705); + status = VL53L1_WrWord(dev, SD_CONFIG__INITIAL_PHASE_SD0, 0x0606); + break; + case 2: + status = VL53L1_WrByte(dev, PHASECAL_CONFIG__TIMEOUT_MACROP, 0x0A); + status = VL53L1_WrByte(dev, RANGE_CONFIG__VCSEL_PERIOD_A, 0x0F); + status = VL53L1_WrByte(dev, RANGE_CONFIG__VCSEL_PERIOD_B, 0x0D); + status = VL53L1_WrByte(dev, RANGE_CONFIG__VALID_PHASE_HIGH, 0xB8); + status = VL53L1_WrWord(dev, SD_CONFIG__WOI_SD0, 0x0F0D); + status = VL53L1_WrWord(dev, SD_CONFIG__INITIAL_PHASE_SD0, 0x0E0E); + break; + default: + status = 1; + break; + } + + if (status == 0) + status = VL53L1X_SetTimingBudgetInMs(dev, TB); + return status; +} + +VL53L1X_ERROR VL53L1X_GetDistanceMode(uint16_t dev, uint16_t *DM) +{ + uint8_t TempDM, status=0; + + status = VL53L1_RdByte(dev,PHASECAL_CONFIG__TIMEOUT_MACROP, &TempDM); + if (TempDM == 0x14) + *DM=1; + if(TempDM == 0x0A) + *DM=2; + return status; +} + +VL53L1X_ERROR VL53L1X_SetInterMeasurementInMs(uint16_t dev, uint16_t InterMeasMs) +{ + uint16_t ClockPLL; + VL53L1X_ERROR status = 0; + + status = VL53L1_RdWord(dev, VL53L1_RESULT__OSC_CALIBRATE_VAL, &ClockPLL); + ClockPLL = ClockPLL&0x3FF; + VL53L1_WrDWord(dev, VL53L1_SYSTEM__INTERMEASUREMENT_PERIOD, + (uint32_t)(ClockPLL * InterMeasMs * 1.075)); + return status; + +} + +VL53L1X_ERROR VL53L1X_GetInterMeasurementInMs(uint16_t dev, uint16_t *pIM) +{ + uint16_t ClockPLL; + VL53L1X_ERROR status = 0; + uint32_t tmp; + + status = VL53L1_RdDWord(dev,VL53L1_SYSTEM__INTERMEASUREMENT_PERIOD, &tmp); + *pIM = (uint16_t)tmp; + status = VL53L1_RdWord(dev, VL53L1_RESULT__OSC_CALIBRATE_VAL, &ClockPLL); + ClockPLL = ClockPLL&0x3FF; + *pIM= (uint16_t)(*pIM/(ClockPLL*1.065)); + return status; +} + +VL53L1X_ERROR VL53L1X_BootState(uint16_t dev, uint8_t *state) +{ + VL53L1X_ERROR status = 0; + uint8_t tmp = 0; + + status = VL53L1_RdByte(dev,VL53L1_FIRMWARE__SYSTEM_STATUS, &tmp); + *state = tmp; + return status; +} + +VL53L1X_ERROR VL53L1X_GetSensorId(uint16_t dev, uint16_t *sensorId) +{ + VL53L1X_ERROR status = 0; + uint16_t tmp = 0; + + status = VL53L1_RdWord(dev, VL53L1_IDENTIFICATION__MODEL_ID, &tmp); + *sensorId = tmp; + return status; +} + +VL53L1X_ERROR VL53L1X_GetDistance(uint16_t dev, uint16_t *distance) +{ + VL53L1X_ERROR status = 0; + uint16_t tmp; + + status = (VL53L1_RdWord(dev, + VL53L1_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0, &tmp)); + *distance = tmp; + return status; +} + +VL53L1X_ERROR VL53L1X_GetSignalPerSpad(uint16_t dev, uint16_t *signalRate) +{ + VL53L1X_ERROR status = 0; + uint16_t SpNb=1, signal; + + status = VL53L1_RdWord(dev, + VL53L1_RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0, &signal); + status = VL53L1_RdWord(dev, + VL53L1_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0, &SpNb); + *signalRate = (uint16_t) (2000.0*signal/SpNb); + return status; +} + +VL53L1X_ERROR VL53L1X_GetAmbientPerSpad(uint16_t dev, uint16_t *ambPerSp) +{ + VL53L1X_ERROR status = 0; + uint16_t AmbientRate, SpNb = 1; + + status = VL53L1_RdWord(dev, RESULT__AMBIENT_COUNT_RATE_MCPS_SD, &AmbientRate); + status = VL53L1_RdWord(dev, VL53L1_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0, &SpNb); + *ambPerSp=(uint16_t) (2000.0 * AmbientRate / SpNb); + return status; +} + +VL53L1X_ERROR VL53L1X_GetSignalRate(uint16_t dev, uint16_t *signal) +{ + VL53L1X_ERROR status = 0; + uint16_t tmp; + + status = VL53L1_RdWord(dev, + VL53L1_RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0, &tmp); + *signal = tmp*8; + return status; +} + +VL53L1X_ERROR VL53L1X_GetSpadNb(uint16_t dev, uint16_t *spNb) +{ + VL53L1X_ERROR status = 0; + uint16_t tmp; + + status = VL53L1_RdWord(dev, + VL53L1_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0, &tmp); + *spNb = tmp >> 8; + return status; +} + +VL53L1X_ERROR VL53L1X_GetAmbientRate(uint16_t dev, uint16_t *ambRate) +{ + VL53L1X_ERROR status = 0; + uint16_t tmp; + + status = VL53L1_RdWord(dev, RESULT__AMBIENT_COUNT_RATE_MCPS_SD, &tmp); + *ambRate = tmp*8; + return status; +} + +VL53L1X_ERROR VL53L1X_GetRangeStatus(uint16_t dev, uint8_t *rangeStatus) +{ + VL53L1X_ERROR status = 0; + uint8_t RgSt; + + *rangeStatus = 255; + status = VL53L1_RdByte(dev, VL53L1_RESULT__RANGE_STATUS, &RgSt); + RgSt = RgSt & 0x1F; + if (RgSt < 24) + *rangeStatus = status_rtn[RgSt]; + return status; +} + +VL53L1X_ERROR VL53L1X_GetResult(uint16_t dev, VL53L1X_Result_t *pResult) +{ + VL53L1X_ERROR status = 0; + uint8_t Temp[17]; + uint8_t RgSt = 255; + + status = VL53L1_ReadMulti(dev, VL53L1_RESULT__RANGE_STATUS, Temp, 17); + RgSt = Temp[0] & 0x1F; + if (RgSt < 24) + RgSt = status_rtn[RgSt]; + pResult->Status = RgSt; + pResult->Ambient = (Temp[7] << 8 | Temp[8]) * 8; + pResult->NumSPADs = Temp[3]; + pResult->SigPerSPAD = (Temp[15] << 8 | Temp[16]) * 8; + pResult->Distance = Temp[13] << 8 | Temp[14]; + + return status; +} + +VL53L1X_ERROR VL53L1X_SetOffset(uint16_t dev, int16_t OffsetValue) +{ + VL53L1X_ERROR status = 0; + int16_t Temp; + + Temp = (OffsetValue*4); + VL53L1_WrWord(dev, ALGO__PART_TO_PART_RANGE_OFFSET_MM, + (uint16_t)Temp); + VL53L1_WrWord(dev, MM_CONFIG__INNER_OFFSET_MM, 0x0); + VL53L1_WrWord(dev, MM_CONFIG__OUTER_OFFSET_MM, 0x0); + return status; +} + +VL53L1X_ERROR VL53L1X_GetOffset(uint16_t dev, int16_t *offset) +{ + VL53L1X_ERROR status = 0; + uint16_t Temp; + + status = VL53L1_RdWord(dev,ALGO__PART_TO_PART_RANGE_OFFSET_MM, &Temp); + Temp = Temp<<3; + Temp = Temp>>5; + *offset = (int16_t)(Temp); + return status; +} + +VL53L1X_ERROR VL53L1X_SetXtalk(uint16_t dev, uint16_t XtalkValue) +{ +/* XTalkValue in count per second to avoid float type */ + VL53L1X_ERROR status = 0; + + status = VL53L1_WrWord(dev, + ALGO__CROSSTALK_COMPENSATION_X_PLANE_GRADIENT_KCPS, + 0x0000); + status = VL53L1_WrWord(dev, ALGO__CROSSTALK_COMPENSATION_Y_PLANE_GRADIENT_KCPS, + 0x0000); + status = VL53L1_WrWord(dev, ALGO__CROSSTALK_COMPENSATION_PLANE_OFFSET_KCPS, + (XtalkValue<<9)/1000); /* * << 9 (7.9 format) and /1000 to convert cps to kpcs */ + return status; +} + +VL53L1X_ERROR VL53L1X_GetXtalk(uint16_t dev, uint16_t *xtalk ) +{ + VL53L1X_ERROR status = 0; + uint32_t tmp; + + status = VL53L1_RdDWord(dev,ALGO__CROSSTALK_COMPENSATION_PLANE_OFFSET_KCPS, &tmp); + *xtalk = (uint16_t)(tmp*1000)>>9; /* * 1000 to convert kcps to cps and >> 9 (7.9 format) */ + return status; +} + +VL53L1X_ERROR VL53L1X_SetDistanceThreshold(uint16_t dev, uint16_t ThreshLow, + uint16_t ThreshHigh, uint8_t Window, + uint8_t IntOnNoTarget) +{ + VL53L1X_ERROR status = 0; + uint8_t Temp = 0; + + status = VL53L1_RdByte(dev, SYSTEM__INTERRUPT_CONFIG_GPIO, &Temp); + Temp = Temp & 0x47; + if (IntOnNoTarget == 0) { + status = VL53L1_WrByte(dev, SYSTEM__INTERRUPT_CONFIG_GPIO, + (Temp | (Window & 0x07))); + } else { + status = VL53L1_WrByte(dev, SYSTEM__INTERRUPT_CONFIG_GPIO, + ((Temp | (Window & 0x07)) | 0x40)); + } + status = VL53L1_WrWord(dev, SYSTEM__THRESH_HIGH, ThreshHigh); + status = VL53L1_WrWord(dev, SYSTEM__THRESH_LOW, ThreshLow); + return status; +} + +VL53L1X_ERROR VL53L1X_GetDistanceThresholdWindow(uint16_t dev, uint16_t *window) +{ + VL53L1X_ERROR status = 0; + uint8_t tmp; + status = VL53L1_RdByte(dev,SYSTEM__INTERRUPT_CONFIG_GPIO, &tmp); + *window = (uint16_t)(tmp & 0x7); + return status; +} + +VL53L1X_ERROR VL53L1X_GetDistanceThresholdLow(uint16_t dev, uint16_t *low) +{ + VL53L1X_ERROR status = 0; + uint16_t tmp; + + status = VL53L1_RdWord(dev,SYSTEM__THRESH_LOW, &tmp); + *low = tmp; + return status; +} + +VL53L1X_ERROR VL53L1X_GetDistanceThresholdHigh(uint16_t dev, uint16_t *high) +{ + VL53L1X_ERROR status = 0; + uint16_t tmp; + + status = VL53L1_RdWord(dev,SYSTEM__THRESH_HIGH, &tmp); + *high = tmp; + return status; +} + +VL53L1X_ERROR VL53L1X_SetROICenter(uint16_t dev, uint8_t ROICenter) +{ + VL53L1X_ERROR status = 0; + status = VL53L1_WrByte(dev, ROI_CONFIG__USER_ROI_CENTRE_SPAD, ROICenter); + return status; +} + +VL53L1X_ERROR VL53L1X_GetROICenter(uint16_t dev, uint8_t *ROICenter) +{ + VL53L1X_ERROR status = 0; + uint8_t tmp; + status = VL53L1_RdByte(dev, ROI_CONFIG__USER_ROI_CENTRE_SPAD, &tmp); + *ROICenter = tmp; + return status; +} + +VL53L1X_ERROR VL53L1X_SetROI(uint16_t dev, uint16_t X, uint16_t Y) +{ + uint8_t OpticalCenter; + VL53L1X_ERROR status = 0; + + status =VL53L1_RdByte(dev, VL53L1_ROI_CONFIG__MODE_ROI_CENTRE_SPAD, &OpticalCenter); + if (X > 16) + X = 16; + if (Y > 16) + Y = 16; + if (X > 10 || Y > 10){ + OpticalCenter = 199; + } + status = VL53L1_WrByte(dev, ROI_CONFIG__USER_ROI_CENTRE_SPAD, OpticalCenter); + status = VL53L1_WrByte(dev, ROI_CONFIG__USER_ROI_REQUESTED_GLOBAL_XY_SIZE, + (Y - 1) << 4 | (X - 1)); + return status; +} + +VL53L1X_ERROR VL53L1X_GetROI_XY(uint16_t dev, uint16_t *ROI_X, uint16_t *ROI_Y) +{ + VL53L1X_ERROR status = 0; + uint8_t tmp; + + status = VL53L1_RdByte(dev,ROI_CONFIG__USER_ROI_REQUESTED_GLOBAL_XY_SIZE, &tmp); + *ROI_X = ((uint16_t)tmp & 0x0F) + 1; + *ROI_Y = (((uint16_t)tmp & 0xF0) >> 4) + 1; + return status; +} + +VL53L1X_ERROR VL53L1X_SetSignalThreshold(uint16_t dev, uint16_t Signal) +{ + VL53L1X_ERROR status = 0; + + VL53L1_WrWord(dev,RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS,Signal>>3); + return status; +} + +VL53L1X_ERROR VL53L1X_GetSignalThreshold(uint16_t dev, uint16_t *signal) +{ + VL53L1X_ERROR status = 0; + uint16_t tmp; + + status = VL53L1_RdWord(dev, + RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS, &tmp); + *signal = tmp <<3; + return status; +} + +VL53L1X_ERROR VL53L1X_SetSigmaThreshold(uint16_t dev, uint16_t Sigma) +{ + VL53L1X_ERROR status = 0; + + if(Sigma>(0xFFFF>>2)){ + return 1; + } + /* 16 bits register 14.2 format */ + status = VL53L1_WrWord(dev,RANGE_CONFIG__SIGMA_THRESH,Sigma<<2); + return status; +} + +VL53L1X_ERROR VL53L1X_GetSigmaThreshold(uint16_t dev, uint16_t *sigma) +{ + VL53L1X_ERROR status = 0; + uint16_t tmp; + + status = VL53L1_RdWord(dev,RANGE_CONFIG__SIGMA_THRESH, &tmp); + *sigma = tmp >> 2; + return status; + +} + +VL53L1X_ERROR VL53L1X_StartTemperatureUpdate(uint16_t dev) +{ + VL53L1X_ERROR status = 0; + uint8_t tmp=0; + + status = VL53L1_WrByte(dev,VL53L1_VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND,0x81); /* full VHV */ + status = VL53L1_WrByte(dev,0x0B,0x92); + status = VL53L1X_StartRanging(dev); + while(tmp==0){ + status = VL53L1X_CheckForDataReady(dev, &tmp); + } + tmp = 0; + status = VL53L1X_ClearInterrupt(dev); + status = VL53L1X_StopRanging(dev); + status = VL53L1_WrByte(dev, VL53L1_VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND, 0x09); /* two bounds VHV */ + status = VL53L1_WrByte(dev, 0x0B, 0); /* start VHV from the previous temperature */ + return status; +} diff --git a/vl53lx_uld/VL53L1X_api.h b/vl53lx_uld/VL53L1X_api.h new file mode 100644 index 0000000..0f6e0a6 --- /dev/null +++ b/vl53lx_uld/VL53L1X_api.h @@ -0,0 +1,393 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file : part of VL53L1 Core and : dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document : strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* 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 vl53l1x_api.h + * @brief Functions definition + */ + +#ifndef _API_H_ +#define _API_H_ + +#include "vl53l1_platform.h" + +#define VL53L1X_IMPLEMENTATION_VER_MAJOR 3 +#define VL53L1X_IMPLEMENTATION_VER_MINOR 2 +#define VL53L1X_IMPLEMENTATION_VER_SUB 0 +#define VL53L1X_IMPLEMENTATION_VER_REVISION 0000 + +typedef int8_t VL53L1X_ERROR; + +#define SOFT_RESET 0x0000 +#define VL53L1_I2C_SLAVE__DEVICE_ADDRESS 0x0001 +#define VL53L1_VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND 0x0008 +#define ALGO__CROSSTALK_COMPENSATION_PLANE_OFFSET_KCPS 0x0016 +#define ALGO__CROSSTALK_COMPENSATION_X_PLANE_GRADIENT_KCPS 0x0018 +#define ALGO__CROSSTALK_COMPENSATION_Y_PLANE_GRADIENT_KCPS 0x001A +#define ALGO__PART_TO_PART_RANGE_OFFSET_MM 0x001E +#define MM_CONFIG__INNER_OFFSET_MM 0x0020 +#define MM_CONFIG__OUTER_OFFSET_MM 0x0022 +#define GPIO_HV_MUX__CTRL 0x0030 +#define GPIO__TIO_HV_STATUS 0x0031 +#define SYSTEM__INTERRUPT_CONFIG_GPIO 0x0046 +#define PHASECAL_CONFIG__TIMEOUT_MACROP 0x004B +#define RANGE_CONFIG__TIMEOUT_MACROP_A_HI 0x005E +#define RANGE_CONFIG__VCSEL_PERIOD_A 0x0060 +#define RANGE_CONFIG__VCSEL_PERIOD_B 0x0063 +#define RANGE_CONFIG__TIMEOUT_MACROP_B_HI 0x0061 +#define RANGE_CONFIG__TIMEOUT_MACROP_B_LO 0x0062 +#define RANGE_CONFIG__SIGMA_THRESH 0x0064 +#define RANGE_CONFIG__MIN_COUNT_RATE_RTN_LIMIT_MCPS 0x0066 +#define RANGE_CONFIG__VALID_PHASE_HIGH 0x0069 +#define VL53L1_SYSTEM__INTERMEASUREMENT_PERIOD 0x006C +#define SYSTEM__THRESH_HIGH 0x0072 +#define SYSTEM__THRESH_LOW 0x0074 +#define SD_CONFIG__WOI_SD0 0x0078 +#define SD_CONFIG__INITIAL_PHASE_SD0 0x007A +#define ROI_CONFIG__USER_ROI_CENTRE_SPAD 0x007F +#define ROI_CONFIG__USER_ROI_REQUESTED_GLOBAL_XY_SIZE 0x0080 +#define SYSTEM__SEQUENCE_CONFIG 0x0081 +#define VL53L1_SYSTEM__GROUPED_PARAMETER_HOLD 0x0082 +#define SYSTEM__INTERRUPT_CLEAR 0x0086 +#define SYSTEM__MODE_START 0x0087 +#define VL53L1_RESULT__RANGE_STATUS 0x0089 +#define VL53L1_RESULT__DSS_ACTUAL_EFFECTIVE_SPADS_SD0 0x008C +#define RESULT__AMBIENT_COUNT_RATE_MCPS_SD 0x0090 +#define VL53L1_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0 0x0096 +#define VL53L1_RESULT__PEAK_SIGNAL_COUNT_RATE_CROSSTALK_CORRECTED_MCPS_SD0 0x0098 +#define VL53L1_RESULT__OSC_CALIBRATE_VAL 0x00DE +#define VL53L1_FIRMWARE__SYSTEM_STATUS 0x00E5 +#define VL53L1_IDENTIFICATION__MODEL_ID 0x010F +#define VL53L1_ROI_CONFIG__MODE_ROI_CENTRE_SPAD 0x013E + +/**************************************** + * PRIVATE define do not edit + ****************************************/ + +/** + * @brief defines SW Version + */ +typedef struct { + uint8_t major; /*!< major number */ + uint8_t minor; /*!< minor number */ + uint8_t build; /*!< build number */ + uint32_t revision; /*!< revision number */ +} VL53L1X_Version_t; + +/** + * @brief defines packed reading results type + */ +typedef struct { + uint8_t Status; /*!< ResultStatus */ + uint16_t Distance; /*!< ResultDistance */ + uint16_t Ambient; /*!< ResultAmbient */ + uint16_t SigPerSPAD;/*!< ResultSignalPerSPAD */ + uint16_t NumSPADs; /*!< ResultNumSPADs */ +} VL53L1X_Result_t; + +/** + * @brief This function returns the SW driver version + */ +VL53L1X_ERROR VL53L1X_GetSWVersion(VL53L1X_Version_t *pVersion); + +/** + * @brief This function sets the sensor I2C address used in case multiple devices application, default address 0x52 + */ +VL53L1X_ERROR VL53L1X_SetI2CAddress(uint16_t, uint8_t new_address); + +/** + * @brief This function loads the 135 bytes default values to initialize the sensor. + * @param dev Device address + * @return 0:success, != 0:failed + */ +VL53L1X_ERROR VL53L1X_SensorInit(uint16_t dev); + +/** + * @brief This function clears the interrupt, to be called after a ranging data reading + * to arm the interrupt for the next data ready event. + */ +VL53L1X_ERROR VL53L1X_ClearInterrupt(uint16_t dev); + +/** + * @brief This function programs the interrupt polarity\n + * 1=active high (default), 0=active low + */ +VL53L1X_ERROR VL53L1X_SetInterruptPolarity(uint16_t dev, uint8_t IntPol); + +/** + * @brief This function returns the current interrupt polarity\n + * 1=active high (default), 0=active low + */ +VL53L1X_ERROR VL53L1X_GetInterruptPolarity(uint16_t dev, uint8_t *pIntPol); + +/** + * @brief This function starts the ranging distance operation\n + * The ranging operation is continuous. The clear interrupt has to be done after each get data to allow the interrupt to raise when the next data is ready\n + * 1=active high (default), 0=active low, use SetInterruptPolarity() to change the interrupt polarity if required. + */ +VL53L1X_ERROR VL53L1X_StartRanging(uint16_t dev); + +/** + * @brief This function stops the ranging. + */ +VL53L1X_ERROR VL53L1X_StopRanging(uint16_t dev); + +/** + * @brief This function checks if the new ranging data is available by polling the dedicated register. + * @param : isDataReady==0 -> not ready; isDataReady==1 -> ready + */ +VL53L1X_ERROR VL53L1X_CheckForDataReady(uint16_t dev, uint8_t *isDataReady); + +/** + * @brief This function programs the timing budget in ms. + * Predefined values = 15, 20, 33, 50, 100(default), 200, 500. + */ +VL53L1X_ERROR VL53L1X_SetTimingBudgetInMs(uint16_t dev, uint16_t TimingBudgetInMs); + +/** + * @brief This function returns the current timing budget in ms. + */ +VL53L1X_ERROR VL53L1X_GetTimingBudgetInMs(uint16_t dev, uint16_t *pTimingBudgetInMs); + +/** + * @brief This function programs the distance mode (1=short, 2=long(default)). + * Short mode max distance is limited to 1.3 m but better ambient immunity.\n + * Long mode can range up to 4 m in the dark with 200 ms timing budget. + */ +VL53L1X_ERROR VL53L1X_SetDistanceMode(uint16_t dev, uint16_t DistanceMode); + +/** + * @brief This function returns the current distance mode (1=short, 2=long). + */ +VL53L1X_ERROR VL53L1X_GetDistanceMode(uint16_t dev, uint16_t *pDistanceMode); + +/** + * @brief This function programs the Intermeasurement period in ms\n + * Intermeasurement period must be >/= timing budget. This condition is not checked by the API, + * the customer has the duty to check the condition. Default = 100 ms + */ +VL53L1X_ERROR VL53L1X_SetInterMeasurementInMs(uint16_t dev, + uint16_t InterMeasurementInMs); + +/** + * @brief This function returns the Intermeasurement period in ms. + */ +VL53L1X_ERROR VL53L1X_GetInterMeasurementInMs(uint16_t dev, uint16_t * pIM); + +/** + * @brief This function returns the boot state of the device (1:booted, 0:not booted) + */ +VL53L1X_ERROR VL53L1X_BootState(uint16_t dev, uint8_t *state); + +/** + * @brief This function returns the sensor id, sensor Id must be 0xEEAC + */ +VL53L1X_ERROR VL53L1X_GetSensorId(uint16_t dev, uint16_t *id); + +/** + * @brief This function returns the distance measured by the sensor in mm + */ +VL53L1X_ERROR VL53L1X_GetDistance(uint16_t dev, uint16_t *distance); + +/** + * @brief This function returns the returned signal per SPAD in kcps/SPAD. + * With kcps stands for Kilo Count Per Second + */ +VL53L1X_ERROR VL53L1X_GetSignalPerSpad(uint16_t dev, uint16_t *signalPerSp); + +/** + * @brief This function returns the ambient per SPAD in kcps/SPAD + */ +VL53L1X_ERROR VL53L1X_GetAmbientPerSpad(uint16_t dev, uint16_t *amb); + +/** + * @brief This function returns the returned signal in kcps. + */ +VL53L1X_ERROR VL53L1X_GetSignalRate(uint16_t dev, uint16_t *signalRate); + +/** + * @brief This function returns the current number of enabled SPADs + */ +VL53L1X_ERROR VL53L1X_GetSpadNb(uint16_t dev, uint16_t *spNb); + +/** + * @brief This function returns the ambient rate in kcps + */ +VL53L1X_ERROR VL53L1X_GetAmbientRate(uint16_t dev, uint16_t *ambRate); + +/** + * @brief This function returns the ranging status error \n + * (0:no error, 1:sigma failed, 2:signal failed, ..., 7:wrap-around) + */ +VL53L1X_ERROR VL53L1X_GetRangeStatus(uint16_t dev, uint8_t *rangeStatus); + +/** + * @brief This function returns measurements and the range status in a single read access + */ +VL53L1X_ERROR VL53L1X_GetResult(uint16_t dev, VL53L1X_Result_t *pResult); + +/** + * @brief This function programs the offset correction in mm + * @param OffsetValue:the offset correction value to program in mm + */ +VL53L1X_ERROR VL53L1X_SetOffset(uint16_t dev, int16_t OffsetValue); + +/** + * @brief This function returns the programmed offset correction value in mm + */ +VL53L1X_ERROR VL53L1X_GetOffset(uint16_t dev, int16_t *Offset); + +/** + * @brief This function programs the xtalk correction value in cps (Count Per Second).\n + * This is the number of photons reflected back from the cover glass in cps. + */ +VL53L1X_ERROR VL53L1X_SetXtalk(uint16_t dev, uint16_t XtalkValue); + +/** + * @brief This function returns the current programmed xtalk correction value in cps + */ +VL53L1X_ERROR VL53L1X_GetXtalk(uint16_t dev, uint16_t *Xtalk); + +/** + * @brief This function programs the threshold detection mode\n + * Example:\n + * VL53L1X_SetDistanceThreshold(dev,100,300,0,1): Below 100 \n + * VL53L1X_SetDistanceThreshold(dev,100,300,1,1): Above 300 \n + * VL53L1X_SetDistanceThreshold(dev,100,300,2,1): Out of window \n + * VL53L1X_SetDistanceThreshold(dev,100,300,3,1): In window \n + * @param dev : device address + * @param ThreshLow(in mm) : the threshold under which one the device raises an interrupt if Window = 0 + * @param ThreshHigh(in mm) : the threshold above which one the device raises an interrupt if Window = 1 + * @param Window detection mode : 0=below, 1=above, 2=out, 3=in + * @param IntOnNoTarget = 1 (No longer used - just use 1) + */ +VL53L1X_ERROR VL53L1X_SetDistanceThreshold(uint16_t dev, uint16_t ThreshLow, + uint16_t ThreshHigh, uint8_t Window, + uint8_t IntOnNoTarget); + +/** + * @brief This function returns the window detection mode (0=below; 1=above; 2=out; 3=in) + */ +VL53L1X_ERROR VL53L1X_GetDistanceThresholdWindow(uint16_t dev, uint16_t *window); + +/** + * @brief This function returns the low threshold in mm + */ +VL53L1X_ERROR VL53L1X_GetDistanceThresholdLow(uint16_t dev, uint16_t *low); + +/** + * @brief This function returns the high threshold in mm + */ +VL53L1X_ERROR VL53L1X_GetDistanceThresholdHigh(uint16_t dev, uint16_t *high); + +/** + * @brief This function programs the ROI (Region of Interest)\n + * The ROI position is centered, only the ROI size can be reprogrammed.\n + * The smallest acceptable ROI size = 4\n + * @param X:ROI Width; Y=ROI Height + */ +VL53L1X_ERROR VL53L1X_SetROI(uint16_t dev, uint16_t X, uint16_t Y); + +/** + *@brief This function returns width X and height Y + */ +VL53L1X_ERROR VL53L1X_GetROI_XY(uint16_t dev, uint16_t *ROI_X, uint16_t *ROI_Y); + +/** + *@brief This function programs the new user ROI center, please to be aware that there is no check in this function. + *if the ROI center vs ROI size is out of border the ranging function return error #13 + */ +VL53L1X_ERROR VL53L1X_SetROICenter(uint16_t dev, uint8_t ROICenter); + +/** + *@brief This function returns the current user ROI center + */ +VL53L1X_ERROR VL53L1X_GetROICenter(uint16_t dev, uint8_t *ROICenter); + +/** + * @brief This function programs a new signal threshold in kcps (default=1024 kcps\n + */ +VL53L1X_ERROR VL53L1X_SetSignalThreshold(uint16_t dev, uint16_t signal); + +/** + * @brief This function returns the current signal threshold in kcps + */ +VL53L1X_ERROR VL53L1X_GetSignalThreshold(uint16_t dev, uint16_t *signal); + +/** + * @brief This function programs a new sigma threshold in mm (default=15 mm) + */ +VL53L1X_ERROR VL53L1X_SetSigmaThreshold(uint16_t dev, uint16_t sigma); + +/** + * @brief This function returns the current sigma threshold in mm + */ +VL53L1X_ERROR VL53L1X_GetSigmaThreshold(uint16_t dev, uint16_t *signal); + +/** + * @brief This function performs the temperature calibration. + * It is recommended to call this function any time the temperature might have changed by more than 8 deg C + * without sensor ranging activity for an extended period. + */ +VL53L1X_ERROR VL53L1X_StartTemperatureUpdate(uint16_t dev); + +#endif diff --git a/vl53lx_uld/VL53L1X_calibration.c b/vl53lx_uld/VL53L1X_calibration.c new file mode 100644 index 0000000..05a7d43 --- /dev/null +++ b/vl53lx_uld/VL53L1X_calibration.c @@ -0,0 +1,136 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file : part of VL53L1 Core and : dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document : strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* 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 vl53l1x_calibration.c + * @brief Calibration functions implementation + */ +#include "VL53L1X_api.h" +#include "VL53L1X_calibration.h" + +#define ALGO__PART_TO_PART_RANGE_OFFSET_MM 0x001E +#define MM_CONFIG__INNER_OFFSET_MM 0x0020 +#define MM_CONFIG__OUTER_OFFSET_MM 0x0022 + +int8_t VL53L1X_CalibrateOffset(uint16_t dev, uint16_t TargetDistInMm, int16_t *offset) +{ + uint8_t i, tmp; + int16_t AverageDistance = 0; + uint16_t distance; + VL53L1X_ERROR status = 0; + + status = VL53L1_WrWord(dev, ALGO__PART_TO_PART_RANGE_OFFSET_MM, 0x0); + status = VL53L1_WrWord(dev, MM_CONFIG__INNER_OFFSET_MM, 0x0); + status = VL53L1_WrWord(dev, MM_CONFIG__OUTER_OFFSET_MM, 0x0); + status = VL53L1X_StartRanging(dev); /* Enable VL53L1X sensor */ + for (i = 0; i < 50; i++) { + tmp = 0; + while (tmp == 0){ + status = VL53L1X_CheckForDataReady(dev, &tmp); + } + status = VL53L1X_GetDistance(dev, &distance); + status = VL53L1X_ClearInterrupt(dev); + AverageDistance = AverageDistance + distance; + } + status = VL53L1X_StopRanging(dev); + AverageDistance = AverageDistance / 50; + *offset = TargetDistInMm - AverageDistance; + status = VL53L1_WrWord(dev, ALGO__PART_TO_PART_RANGE_OFFSET_MM, *offset*4); + return status; +} + +int8_t VL53L1X_CalibrateXtalk(uint16_t dev, uint16_t TargetDistInMm, uint16_t *xtalk) +{ + uint8_t i, tmp; + float AverageSignalRate = 0; + float AverageDistance = 0; + float AverageSpadNb = 0; + uint16_t distance = 0, spadNum; + uint16_t sr; + VL53L1X_ERROR status = 0; + uint32_t calXtalk; + + status = VL53L1_WrWord(dev, 0x0016,0); + status = VL53L1X_StartRanging(dev); + for (i = 0; i < 50; i++) { + tmp = 0; + while (tmp == 0){ + status = VL53L1X_CheckForDataReady(dev, &tmp); + } + status= VL53L1X_GetSignalRate(dev, &sr); + status= VL53L1X_GetDistance(dev, &distance); + status = VL53L1X_ClearInterrupt(dev); + AverageDistance = AverageDistance + distance; + status = VL53L1X_GetSpadNb(dev, &spadNum); + AverageSpadNb = AverageSpadNb + spadNum; + AverageSignalRate = + AverageSignalRate + sr; + } + status = VL53L1X_StopRanging(dev); + AverageDistance = AverageDistance / 50; + AverageSpadNb = AverageSpadNb / 50; + AverageSignalRate = AverageSignalRate / 50; + /* Calculate Xtalk value */ + calXtalk = (uint16_t)(512*(AverageSignalRate*(1-(AverageDistance/TargetDistInMm)))/AverageSpadNb); + *xtalk = (uint16_t)(calXtalk*1000)>>9; + status = VL53L1_WrWord(dev, 0x0016, calXtalk); + return status; +} diff --git a/vl53lx_uld/VL53L1X_calibration.h b/vl53lx_uld/VL53L1X_calibration.h new file mode 100644 index 0000000..c057722 --- /dev/null +++ b/vl53lx_uld/VL53L1X_calibration.h @@ -0,0 +1,93 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file : part of VL53L1 Core and : dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document : strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* 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 vl53l1x_calibration.h + * @brief Calibration Functions definition + */ + +#ifndef _CALIBRATION_H_ +#define _CALIBRATION_H_ + +/** + * @brief This function performs the offset calibration.\n + * The function returns the offset value found and programs the offset compensation into the device. + * @param TargetDistInMm target distance in mm, ST recommended 100 mm + * Target reflectance = grey17% + * @return 0:success, !=0: failed + * @return offset pointer contains the offset found in mm + */ +int8_t VL53L1X_CalibrateOffset(uint16_t dev, uint16_t TargetDistInMm, int16_t *offset); + +/** + * @brief This function performs the xtalk calibration.\n + * The function returns the xtalk value found and programs the xtalk compensation to the device + * @param TargetDistInMm target distance in mm\n + * The target distance : the distance where the sensor start to "under range"\n + * due to the influence of the photons reflected back from the cover glass becoming strong\n + * It's also called inflection point\n + * Target reflectance = grey 17% + * @return 0: success, !=0: failed + * @return xtalk pointer contains the xtalk value found in cps (number of photons in count per second) + */ +int8_t VL53L1X_CalibrateXtalk(uint16_t dev, uint16_t TargetDistInMm, uint16_t *xtalk); + +#endif diff --git a/vl53lx_uld/X-NUCLEO-53L1A1.c b/vl53lx_uld/X-NUCLEO-53L1A1.c new file mode 100644 index 0000000..dccaa1b --- /dev/null +++ b/vl53lx_uld/X-NUCLEO-53L1A1.c @@ -0,0 +1,608 @@ +/** + * @file X-NUCLEO-53L1A1.c + * + * implement X-NUCLEO-53L1A1 Nucleo BSP + */ + +#include "main.h" +#include +#include "X-NUCLEO-53L1A1.h" + +#include "stm32wlxx_hal.h" + + +#ifndef HAL_I2C_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +#pragma message("hal conf should enable i2c") +#endif + +/* when not customized by application define dummy one */ +#ifndef XNUCLEO53L1A1_GetI2cBus +/** + * macro that can be overloaded by user to enforce i2c sharing in RTOS context + */ +#define XNUCLEO53L1A1_GetI2cBus(...) (void)0 +#endif + +#ifndef XNUCLEO53L1A1_PutI2cBus +/** macro can be overloaded by user to enforce i2c sharing in RTOS context + */ +# define XNUCLEO53L1A1_PutI2cBus(...) (void)0 +#endif + + + +/** + * Expander 0 i2c address[7..0] format + */ +#define I2cExpAddr0 ((int)(0x43*2)) +/** + * Expander 1 i2c address[7..0] format + */ +#define I2cExpAddr1 ((int)(0x42*2)) +/** @} XNUCLEO53L1A1_I2CExpanders*/ + + +/** + * GPIO monitor pin state register + * 16 bit register LSB at lowest offset (little endian) + */ +#define GPMR 0x10 +/** + * STMPE1600 GPIO set pin state register + * 16 bit register LSB at lowest offset (little endian) + */ +#define GPSR 0x12 +/** + * STMPE1600 GPIO set pin direction register + * 16 bit register LSB at lowest offset + */ +#define GPDR 0x14 + + +/** @} */ /* defgroup XNUCLEO53L1A1_Board */ + + +/**************************************************** + *@defgroup XNUCLEO53L1A1_globals + *@{ + */ + +/** + * i2c handle to be use of all i2c access + * end user shall provide it to + * can be @a XNUCLEO53L1A1_I2C1Configure() @sa XNUCLEO53L1A1_usage + * @warning do not use any XNUCLEO53L1A1_xxx prior to a first init with valid i2c handle + */ +I2C_HandleTypeDef XNUCLEO53L1A1_hi2c; + + +/** + * cache the full set of expanded GPIO values to avoid i2c reading + */ +static union CurIOVal_u { + uint8_t bytes[4]; /*!< 4 bytes array i/o view */ + uint32_t u32; /*!< single dword i/o view */ +} +/** cache the extended IO values */ +CurIOVal; + +/** + * lookup table for for digit to bit position in @a CurIOVal u32 + */ +static int DisplayBitPos[4]={0, 7, 16, 16+7}; + +/** @} XNUCLEO53L1A1_globals*/ + +/* Forward definition of private function */ + +static int _ExpanderRd(int I2cExpAddr, int index, uint8_t *data, int n_data); +static int _ExpanderWR(int I2cExpAddr, int index, uint8_t *data, int n_data); +static int _ExpandersSetAllIO(void); + +/** + * Expansion board i2c bus recovery + * + * We may get reset in middle of an i2c access (h/w reset button, debug or f/w load) + * hence some agent on bus may be in middle of a transaction and can create issue or even prevent starting (SDA is low) + * this routine does use gpio to manipulate and recover i2c bus line in all cases. + */ +static void _I2cFailRecover(){ + GPIO_InitTypeDef GPIO_InitStruct; + int i, nRetry=0; + + + // We can't assume bus state based on SDA and SCL state (we may be in a data or NAK bit so SCL=SDA=1) + // by setting SDA high and toggling SCL at least 10 time we ensure whatever agent and state + // all agent should end up seeing a "stop" and bus get back to an known idle i2c bus state + + // Enable I/O + __GPIOA_CLK_ENABLE(); + HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_SET); + HAL_GPIO_WritePin(GPIOA, GPIO_PIN_11, GPIO_PIN_SET); + GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_11; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; + GPIO_InitStruct.Pull = GPIO_PULLUP; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + //TODO we could do this faster by not using HAL delay 1ms for clk timing + do{ + for( i=0; i<10; i++){ + HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_RESET); + HAL_Delay(1); + HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_SET); + HAL_Delay(1); + } +// if( HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_9) == 0 ){ +// static int RetryRecover; +// RetryRecover++; +// } + }while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_11) == 0 && nRetry++<7); + + if( HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_11) == 0 ){ + __GPIOB_CLK_ENABLE(); + //We are still in bad i2c state warm user by blinking led but stay here + GPIO_InitStruct.Pin = LED1_Pin ; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(LED3_GPIO_Port, &GPIO_InitStruct); + do{ + HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_SET); + HAL_Delay(33); + HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_RESET); + HAL_Delay(33); + HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_SET); + HAL_Delay(33); + HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_RESET); + HAL_Delay(33*20); + }while(1); + } +} + + + +int XNUCLEO53L1A1_I2C2Configure() { + int status; + GPIO_InitTypeDef GPIO_InitStruct; + + _I2cFailRecover(); + + /* Peripheral clock enable */ + __GPIOA_CLK_ENABLE(); + __I2C2_CLK_ENABLE(); + + /**I2C1 GPIO Configuration\n + PB8 ------> I2C1_SCL\n + PB9 ------> I2C1_SDA + */ + GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_11; + GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF4_I2C2; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + XNUCLEO53L1A1_hi2c.Instance = I2C2; + //XNUCLEO53L1A1_hi2c.Init.Timing = 0x00300F38; /* set 400KHz fast mode i2c*/ + XNUCLEO53L1A1_hi2c.Init.Timing = 0x2010091A; //0x2010091A = 400K Fast Mode, 0x20303E5D, 100K Standard mode, 0x20000209 Fast Mode Plus, 1Mbps + + XNUCLEO53L1A1_hi2c.Init.OwnAddress1 = 0; + XNUCLEO53L1A1_hi2c.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; + XNUCLEO53L1A1_hi2c.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED; + XNUCLEO53L1A1_hi2c.Init.OwnAddress2 = 0; + XNUCLEO53L1A1_hi2c.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED; + XNUCLEO53L1A1_hi2c.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED; + status = HAL_I2C_Init(&XNUCLEO53L1A1_hi2c); + return status; +} + +int XNUCLEO53L1A1_SetIntrStateId(int EnableIntr, int DevNo){ + int status; + IRQn_Type IntrNo; + int IntrPin; + + + switch( DevNo ){ + case XNUCLEO53L1A1_DEV_CENTER : + case 'c' : + IntrNo = VL53L1A1_GPIO1_C_INTx; + IntrPin= VL53L1A1_GPIO1_C_GPIO_PIN; + status = 0; + break; + + case XNUCLEO53L1A1_DEV_LEFT : + case 'l' : + + break; + case 'r' : + case XNUCLEO53L1A1_DEV_RIGHT : + + + break; + + default: + XNUCLEO53L1A1_ErrLog("Invalid DevNo %d",DevNo); + status = -1; + goto done; + } + + if( EnableIntr ){ + __HAL_GPIO_EXTI_CLEAR_IT(IntrPin); + NVIC_ClearPendingIRQ(IntrNo); + HAL_NVIC_EnableIRQ(IntrNo); + /** + * @note When enabling interrupt end user shall check actual state of the line and soft trigger event if active + * Alternatively user can use API and device feature to clear device Interrupt status to possibly generates a new edge. + * on shared pin configuration this must be repeated for all device. + * The same shall be done after clearing a condition in device and interrupt remain active. + */ + } + else{ + HAL_NVIC_DisableIRQ(IntrNo); + __HAL_GPIO_EXTI_CLEAR_IT(IntrPin); + NVIC_ClearPendingIRQ(IntrNo); + } + +done: + return status; +} + + +int XNUCLEO53L1A1_Init(void) { + int status; +// uint8_t ExpanderData[2]; +// XNUCLEO53L1A1_USART2_UART_Init(); + status = XNUCLEO53L1A1_I2C2Configure(); + return status; +} + + +int XNUCLEO53L1A1_GetPB1(int *state) { + int status; + uint8_t PortValue; + status= _ExpanderRd(I2cExpAddr1, GPMR+1, &PortValue,1); + if( status == 0){ + if( PortValue&=0x40 ) + PortValue=1; + else + PortValue=0; + } + else{ + XNUCLEO53L1A1_ErrLog("i/o error"); + } + *state = PortValue; + return status; +} + +int XNUCLEO53L1A1_ResetId(int DevNo, int state) { + int status; + switch( DevNo ){ + case XNUCLEO53L1A1_DEV_CENTER : + case 'c' : + CurIOVal.bytes[3]&=~0x80; /* bit 15 expender 1 => byte #3 */ + if( state ) + CurIOVal.bytes[3]|=0x80; /* bit 15 expender 1 => byte #3 */ + status= _ExpanderWR(I2cExpAddr1, GPSR+1, &CurIOVal.bytes[3], 1); + break; + case XNUCLEO53L1A1_DEV_LEFT : + case 'l' : + CurIOVal.bytes[1]&=~0x40; /* bit 14 expender 0 => byte #1*/ + if( state ) + CurIOVal.bytes[1]|=0x40; /* bit 14 expender 0 => byte #1*/ + status= _ExpanderWR(I2cExpAddr0, GPSR+1, &CurIOVal.bytes[1], 1); + break; + case 'r' : + case XNUCLEO53L1A1_DEV_RIGHT : + CurIOVal.bytes[1]&=~0x80; /* bit 15 expender 0 => byte #1 */ + if( state ) + CurIOVal.bytes[1]|=0x80; /* bit 15 expender 0 => byte #1*/ + status= _ExpanderWR(I2cExpAddr0, GPSR+1, &CurIOVal.bytes[1], 1); + break; + default: + XNUCLEO53L1A1_ErrLog("Invalid DevNo %d",DevNo); + status = -1; + goto done; + } +//error with valid id + if( status ){ + XNUCLEO53L1A1_ErrLog("expander i/o error for DevNo %d state %d ",DevNo, state); + } +done: + return status; +} + + +void VL53L1A1_EXTI_IOConfigure(int DevNo, int IntPriority, int SubPriority){ + GPIO_InitTypeDef GPIO_InitStruct; + + GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; + GPIO_InitStruct.Pull = VL53L1A1_INTR_PIN_PUPD; + + switch (DevNo ) { + case XNUCLEO53L1A1_DEV_CENTER: + case 'c': + VL53L1A1_GPIO1_C_CLK_ENABLE(); + /*Configure GPIO pin : PA4 */ + GPIO_InitStruct.Pin = VL53L1A1_GPIO1_C_GPIO_PIN; + + XNUCLEO53L1A1_SetIntrStateId(1,XNUCLEO53L1A1_DEV_CENTER); + HAL_GPIO_Init(VL53L1A1_GPIO1_C_GPIO_PORT, &GPIO_InitStruct); + HAL_NVIC_SetPriority((IRQn_Type)VL53L1A1_GPIO1_C_GPIO_PIN, IntPriority, SubPriority); + break; + +#if VL53L1A1_GPIO1_SHARED == 0 + case XNUCLEO53L1A1_DEV_LEFT: + case 'l': + break; + + case XNUCLEO53L1A1_DEV_RIGHT: + break; +#endif + } +} + +void VL53L1A1_EXTI_IOUnconfigure(int DevNo){ + switch (DevNo ) { + case XNUCLEO53L1A1_DEV_CENTER: + case 'c': + //XNUCLEO53L1A1_SetIntrStateId(0,XNUCLEO53L1A1_DEV_TOP); + HAL_GPIO_DeInit(VL53L1A1_GPIO1_C_GPIO_PORT, VL53L1A1_GPIO1_C_GPIO_PIN); + __HAL_GPIO_EXTI_CLEAR_IT(VL53L1A1_GPIO1_C_GPIO_PIN); + break; + +#if VL53L1A1_GPIO1_SHARED == 0 + case XNUCLEO53L1A1_DEV_LEFT: + case 'l': + // XNUCLEO53L1A1_SetIntrStateId(0,XNUCLEO53L1A1_DEV_LEFT); + HAL_GPIO_DeInit(VL53L1A1_GPIO1_L_GPIO_PORT, VL53L1A1_GPIO1_L_GPIO_PIN); + __HAL_GPIO_EXTI_CLEAR_IT(VL53L1A1_GPIO1_L_GPIO_PIN); + break; + + case XNUCLEO53L1A1_DEV_RIGHT: + case 'r': + HAL_GPIO_DeInit(VL53L1A1_GPIO1_R_GPIO_PORT, VL53L1A1_GPIO1_R_GPIO_PIN); + __HAL_GPIO_EXTI_CLEAR_IT(VL53L1A1_GPIO1_R_GPIO_PIN); + //XNUCLEO53L1A1_SetIntrStateId(0,XNUCLEO53L1A1_DEV_RIGHT); + break; +#endif + } +} +/** + * Set all i2c expended gpio in one go + * @return i/o operation status + */ +static int _ExpandersSetAllIO(void){ + int status; + status = _ExpanderWR(I2cExpAddr0, GPSR, &CurIOVal.bytes[0], 2); + if( status ){ + goto done_err; + } + status = _ExpanderWR(I2cExpAddr1, GPSR, &CurIOVal.bytes[2], 2); +done_err: + return status; +} + +/** + * STMPE1600 i2c Expender register read + * @param I2cExpAddr Expender address + * @param index register index + * @param data read data buffer + * @param n_data number of byte to read + * @return of if ok else i2c I/O operation status + */ +static int _ExpanderRd(int I2cExpAddr, int index, uint8_t *data, int n_data) { + + int status; + uint8_t RegAddr; + RegAddr = index; + XNUCLEO53L1A1_GetI2cBus(); + do { + status = HAL_I2C_Master_Transmit(&XNUCLEO53L1A1_hi2c, I2cExpAddr, &RegAddr, 1, 100); + if (status) + break; + status = HAL_I2C_Master_Receive(&XNUCLEO53L1A1_hi2c, I2cExpAddr, data, n_data, n_data * 100); + } while (0); + XNUCLEO53L1A1_PutI2cBus(); + return status; +} + +/** + * STMPE1600 i2c Expender register write + * @param I2cExpAddr Expender address + * @param index register index + * @param data data buffer + * @param n_data number of byte to write + * @return of if ok else i2c I/O operation status + */ +static int _ExpanderWR(int I2cExpAddr, int index, uint8_t *data, int n_data) { + + int status; + uint8_t RegAddr[0x10]; + RegAddr[0] = index; + memcpy(RegAddr + 1, data, n_data); + XNUCLEO53L1A1_GetI2cBus(); + status = HAL_I2C_Master_Transmit(&XNUCLEO53L1A1_hi2c, I2cExpAddr, RegAddr, n_data + 1, 100); + XNUCLEO53L1A1_PutI2cBus(); + return status; +} + + +/** + * @defgroup XNUCLEO53L1A1_7Segment 7 segment display + * + * macro use for human readable segment building + * @code + * --s0-- + * s s + * 5 1 + * --s6-- + * s s + * 4 2 + * --s3-- . s7 (dp) + * @endcode + * + * @{ + */ +/** decimal point bit mapping* */ +#define DP (1<<7) + +//VL6180 shield +//#define S0 (1<<0) +//#define S1 (1<<1) +//#define S2 (1<<2) +//#define S3 (1<<3) +//#define S4 (1<<4) +//#define S5 (1<<5) +//#define S6 (1<<6) + +/** sgement s0 bit mapping*/ +#define S0 (1<<3) +/** sgement s1 bit mapping*/ +#define S1 (1<<5) +/** sgement s2 bit mapping*/ +#define S2 (1<<6) +/** sgement s3 bit mapping*/ +#define S3 (1<<4) +/** sgement s4 bit mapping*/ +#define S4 (1<<0) +/** sgement s5 bit mapping*/ +#define S5 (1<<1) +/** sgement s6 bit mapping*/ +#define S6 (1<<2) + +/** + * build a character by defining the non lighted segment (not one and no DP) + * + * @param ... literal sum and or combine of any macro to define any segment #S0 .. #S6 + * + * example '9' is all segment on but S4 + * @code + * ['9']= NOT_7_NO_DP(S4), + * @endcode + */ +#define NOT_7_NO_DP( ... ) (uint8_t) ~( __VA_ARGS__ + DP ) + +/** + * Ascii to 7 segment lookup table + * + * Most common character are supported and follow http://www.twyman.org.uk/Fonts/ + * few extra special \@ ^~ ... etc are present for specific demo purpose + */ +static const uint8_t ascii_to_display_lut[256]={ + [' ']= 0, + ['-']= S6, + ['_']= S3, + ['=']= S3+S6, + ['~']= S0+S3+S6, /* 3 h bar */ + ['^']= S0, /* use as top bar */ + + ['?']= NOT_7_NO_DP(S5+S3+S2), + ['*']= NOT_7_NO_DP(), + ['[']= S0+S3+S4+S5, + [']']= S0+S3+S2+S1, + ['@']= S0+S3, + + ['0']= NOT_7_NO_DP(S6), + ['1']= S1+S2, + ['2']= S0+S1+S6+S4+S3, + ['3']= NOT_7_NO_DP(S4+S5), + ['4']= S5+S1+S6+S2, + ['5']= NOT_7_NO_DP(S1+S4), + ['6']= NOT_7_NO_DP(S1), + ['7']= S0+S1+S2, + ['8']= NOT_7_NO_DP(0), + ['9']= NOT_7_NO_DP(S4), + + ['a']= S2+ S3+ S4+ S6 , + ['b']= NOT_7_NO_DP(S0+S1), + ['c']= S6+S4+S3, + ['d']= NOT_7_NO_DP(S0+S5), + ['e']= NOT_7_NO_DP(S2), + ['f']= S6+S5+S4+S0, /* same as F */ + ['g']= NOT_7_NO_DP(S4), /* same as 9 */ + ['h']= S6+S5+S4+S2, + ['i']= S4, + ['j']= S1+S2+S3+S4, + ['k']= S6+S5+S4+S2, /* a h */ + ['l']= S3+S4, + ['m']= S0+S4+S2, /* same as */ + ['n']= S2+S4+S6, + ['o']= S6+S4+S3+S2, + ['p']= NOT_7_NO_DP(S3+S2), // same as P + ['q']= S0+S1+S2+S5+S6, + ['r']= S4+S6, + ['s']= NOT_7_NO_DP(S1+S4), + ['t']= NOT_7_NO_DP(S0+S1+S2), + ['u']= S4+S3+S2+S5+S1, // U + ['v']= S4+S3+S2, // is u but u use U + ['w']= S1+S3+S5, + ['x']= NOT_7_NO_DP(S0+S3), // similar to H + ['y']= NOT_7_NO_DP(S0+S4), + ['z']= S0+S1+S6+S4+S3, // same as 2 + + ['A']= NOT_7_NO_DP(S3), + ['B']= NOT_7_NO_DP(S0+S1), /* as b */ + ['C']= S0+S3+S4+S5, // same as [ + ['E']= NOT_7_NO_DP(S1+S2), + ['F']= S6+S5+S4+S0, + ['G']= NOT_7_NO_DP(S4), /* same as 9 */ + ['H']= NOT_7_NO_DP(S0+S3), + ['I']= S1+S2, + ['J']= S1+S2+S3+S4, + ['K']= NOT_7_NO_DP(S0+S3), /* same as H */ + ['L']= S3+S4+S5, + ['M']= S0+S4+S2, /* same as m*/ + ['N']= S2+S4+S6, /* same as n*/ + ['O']= NOT_7_NO_DP(S6), + ['P']= NOT_7_NO_DP(S3+S2), + ['Q']= NOT_7_NO_DP(S3+S2), + ['R']= S4+S6, + ['S']= NOT_7_NO_DP(S1+S4), /* sasme as 5 */ + ['T']= NOT_7_NO_DP(S0+S1+S2), /* sasme as t */ + ['U']= NOT_7_NO_DP(S6+S0), + ['V']= S4+S3+S2, // is u but u use U + ['W']= S1+S3+S5, + ['X']= NOT_7_NO_DP(S0+S3), // similar to H + ['Y']= NOT_7_NO_DP(S0+S4), + ['Z']= S0+S1+S6+S4+S3, // same as 2 +}; + +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef S4 +#undef S5 +#undef S6 +#undef DP + +/** @} */ + +int XNUCLEO53L1A1_SetDisplayString(const char *str) { + int status; + uint32_t Segments; + int BitPos; + int i; + + for( i=0; i<4 && str[i]!=0; i++){ + Segments = (uint32_t)ascii_to_display_lut[(uint8_t)str[i]]; + Segments =(~Segments)&0x7F; + BitPos=DisplayBitPos[i]; + CurIOVal.u32 &=~(0x7F< GPIO1_C = PA4 + * @li defined and not 0 : U14=Off and U17=on => GPIO1_C = PC1 + */ +# define VL53L1A1_GPIO1_C_OPTION 0 +#endif + +#ifndef VL53L1A1_GPIO1_L_OPTION +/** + * @def VL53L1A1_GPIO1_L_OPTION + * @brief control left sensor GPIO1 routing solder option + * @warning not used on shared interrupt config + * + * Set option value or un-define it to match with board configuration + * @li not defined or 0 : U10=on and U11=Off => GPIO1_L = PC7 + * @li defined and not 0 : U10=off and U11=on => GPIO1_L = PA9 + */ +# define VL53L1A1_GPIO1_L_OPTION 0 +#endif + +#ifndef VL53L1A1_GPIO1_R_OPTION +/** + * @def VL53L1A1_GPIO1_R_OPTION + * @brief control right sensor GPIO1 routing solder option + * @warning not used on shared interrupt config + * + * Set option value or un-define it to match with board configuration + * @li not defined or 0 : U18=on and U15=Off => GPIO1_R = PA10 + * @li defined and not 0 : U18=off and U15=on => GPIO1_R = PB5 + */ +# define VL53L1A1_GPIO1_R_OPTION 0 +#endif + + + +# define VL53L1A1_GPIO1_C_GPIO_PORT GPIOB +# define VL53L1A1_GPIO1_C_CLK_ENABLE __GPIOB_CLK_ENABLE +# define VL53L1A1_GPIO1_C_GPIO_PIN GPIO_PIN_3 + +# define VL53L1A1_GPIO1_C_INTx EXTI3_IRQn + + + +/* not shared interrupt configuration */ + +# define VL53L1A1_GPIO1_L_GPIO_PORT GPIOC +# define VL53L1A1_GPIO1_L_CLK_ENABLE __GPIOC_CLK_ENABLE +# define VL53L1A1_GPIO1_L_GPIO_PIN GPIO_PIN_7 + + + +# define VL53L1A1_GPIO1_R_GPIO_PORT GPIOA +# define VL53L1A1_GPIO1_R_CLK_ENABLE __GPIOA_CLK_ENABLE +# define VL53L1A1_GPIO1_R_GPIO_PIN GPIO_PIN_10 + + +/** @} */ /* defgroup L53L1A1_GPIO1_MAP */ + +/** + * @defgroup XNUCLEO53L1A1_Debugging VL053L1A1 debugging + * @{ + */ + +#ifndef XNUCLEO53L1A1_TRACE +/** + * @brief enable error output via trace + * + * when undefined (default) no trace no error logging is done, it is safe + * to at least count error just to see if any errors ever occur. + * + * Traces formating and output is end user defined via #trace_printf + */ +# define XNUCLEO53L1A1_TRACE TRACE_UART +#endif // XNUCLEO53L1A1_TRACE + + +/** + * @def XNUCLEO53L1A1_ErrLog(...) + * Macro used to report error log messages with printf format + * + * Our testing version use externally trace_printf, + * We trace out function names and line numbers plus any text formated with some extra arguments + */ +#if XNUCLEO53L1A1_TRACE +# define XNUCLEO53L1A1_ErrLog( msg, ...) trace_printf("[Err] %s l %d \t" msg "\n", __func__, __LINE__, ##__VA_ARGS__) +#else +# define XNUCLEO53L1A1_ErrLog(...) (void)0 +#endif + + + +/** @} */ /* group XNUCLEO53L1A1_Debugging */ + + +/** + * @defgroup XNUCLEO53L1A1_Interface X-NUCLEO-53L1A1 BSP API + * @{ */ + +/** + * 53L0X Device selector + * + * @note Most functions are using a device selector as input. ASCII 'c', 'l' or 'r' are also accepted. + */ +enum XNUCLEO53L1A1_dev_e{ + XNUCLEO53L1A1_DEV_LEFT = 0, //!< left satellite device P21 header : 'l' + XNUCLEO53L1A1_DEV_CENTER = 1, //!< center (built-in) vl053 device : 'c" + XNUCLEO53L1A1_DEV_RIGHT= 2 //!< Right satellite device P22 header : 'r' +}; + +/** + * I2C1 handle + * @note setup and configured by @ref XNUCLEO53L1A1_Init + */ +extern I2C_HandleTypeDef XNUCLEO53L1A1_hi2c; +/** UART2 handle + * + * UART2 is the nucleo Virtual Com Port + * @note setup and configured by @ref XNUCLEO53L1A1_Init*/ +#if VL53L1A1_HAVE_UART +extern UART_HandleTypeDef huart2; + +#if VL53L1A1_UART_DMA_RX +/** UART2 DMA RX available only if support activated*/ +extern DMA_HandleTypeDef hdma_usart2_rx; +#endif + +#if VL53L1A1_UART_DMA_TX +/** UART2 DMA TX available only if support activated */ +extern DMA_HandleTypeDef hdma_usart2_tx; +#endif +#endif//ifdef VL53L1A1_HAVE_UART + +/** + * Initialize VL053L1A1 STM32 expansion board + * + * @note All VL53L0X devices XSDN are asserted and display is turned off + * @return 0 on success + */ +int XNUCLEO53L1A1_Init(void); + +/** + * Set Reset (XSDN) state of a given "id" device + * @param DevNo The device number use @ref XNUCLEO53L1A1_dev_e. Char 't' 'c' 'r' can also be used + * @param state State of the device reset (xsdn) pin @warning reset pin is active low + * @return 0 on success + */ +int XNUCLEO53L1A1_ResetId(int DevNo, int state ); + +/** + * Get PB1 push button state + * + * @param state Actual button state 0/1 boolean type + * @warning In case of error, value of state is unchanged + * @return 0 on success + */ +int XNUCLEO53L1A1_GetPB1(int *state); + +/** + * Set the 7 segments display + * @param str String to set on display + * @warning When string is less than 4 digits, display is left-justified and lower digits are blanked. + * To display a 2 digits value, left justified on the 4 digits, use "%4d" formating + * @warning When more than 4 char are present only first 4 are displayed + * @note Characters that do not have 7 segment font matching in @ref ascii_to_display_lut are left blank + * @return 0 on success + */ +int XNUCLEO53L1A1_SetDisplayString(const char *str); +/** @} */ /* defgroup XNUCLEO53L1A1_Interface */ + +/** + * @ingroup XNUCLEO53L1A1_Interface + * @defgroup MSP_implement MSP and User specific code + * + * Some MSP Micro-controller Support Package code is provided in the BSP source.\n + * The following MSP function and callback are already implemented + * ### UART ### + * @li HAL_UART_MspDeInit and HAL_UART_MspInit + * @li HAL_UART_TxCpltCallback + * @li USART2_IRQHandler + * + * ### EXTI ### + * @li F401RE/L476 EXTI15_10_IRQHandler, EXTI9_5_IRQHandler, EXTI4_IRQHandler and EXTI1_IRQHandler + * @li L053R8 EXTI4_15_IRQHandler, EXTI0_1_IRQHandler and EXTI4_15_IRQHandler + * @li HAL_GPIO_EXTI_Callback + * + * ### DMA ### + * @li L476 DMA1_Channel6_IRQHandler and DMA1_Channel7_IRQHandler + * @li F401 DMA1_Stream5_IRQHandler and DMA1_Stream6_IRQHandler + * @li L053 DMA1_Channel4_5_6_7_IRQHandler + * + * Exact EXTI list depends on soldering options and configured DMA list depends on DMA RX/TX configuration options. + * + * If those functions and callbacks are also to be used by application, the code must be removed or adapted to manage multi-instances + * + * Family-specific code is on dedicated files: + * @li vl53l0A1-l053msp.c for Nucleo-L053R8 + * @li vl53l0A1-x4msp.c for Nucleo-F401RE and Nucleo-L476RG + * @li uart_trace.c for generic uart handling + * @{ + */ + +/** + * @defgroup MSP_implement_common MSP Common to all STM32 + * + * MSP adaption that apply to all mcu (F4,L4,L0) with no or little customization. + * + * @{ + */ + +/** + * Enable Disable interrupt at MCU level (MSP) + * + * Enable/Disable the interrupt for a given sensor Dev number + * + * End user is expected to override VL53L1A1_EXTI_Callback to catch interrupts. + * When the vector is shared applicaton is passed the device and pin corretcy + * In shared line mode application is responsible to find what sensor cause the interrupt and deal with races on interrupt line + * + * @param EnableIntr "boolean" 0 to disable interrupt otherwise interrupt is enabled + * @param DevNo Device number "name" of the sensor see @ref XNUCLEO53L1A1_dev_e + * + * @warning In shared interrupt mode, use only center : other values are not supported and will return an error + * @warning If several lines share the same interrupt vector (l053 mcu), only one sensor interrupt shall be enable at a time + * otherwise the handler may fail to locate and clear the right source (no sharing management) + * + * @return 0 on success \n + * <0 for error (invalid id) + * >0 interrupt configured but with potential sharing on EXTI groups see @ref VL53L1A1_GPIO1_MAP + */ +int XNUCLEO53L1A1_SetIntrStateId(int EnableIntr, int DevNo); + +/** @} */ /* MSP_implemant_common */ + +/** + * MSP Configure expansion board Interrupt i/o + * + * This function configures GPIO i/o and NVIC. See @ref VL53L1A1_GPIO1_MAP for details + * To enable interrupt handling use @ref XNUCLEO53L1A1_SetIntrStateId() + * + * The input pullup/pulldown is configured by static configuration @a #VL53L1A1_INTR_PIN_PUPD + * + * @warning Interrupt is disabled and any pending status flushed out\n + * if initial vl53lx sensor interrupt state is important it must be handled externally (soft trigger) + * @warning If interrupt vector is shared it is better to configure and enable only one at a time + * proper shared management is done but yet some isr could be lost or some other fired spuriously. + * + * @param DevNo device number see @ref XNUCLEO53L1A1_dev_e + * @param IntPriority Interrupt Priority to set + * @param SubPriority Interrupt SubPriority to set + */ +void VL53L1A1_EXTI_IOConfigure(int DevNo, int IntPriority, int SubPriority); + +/** + * Un-configure sensor interrupt line to mcu + * + * The line is DeInited (put back to input?) + * + * This function disables the related i/o pin and flush line interrupt pending (not vector) + * this is to permit shared vector to work. + * To turn off vector use @ref XNUCLEO53L1A1_SetIntrStateId() + * + * @warning because vector and line disable are not done atomically with isr disable, + * a last invalid interrupt may be fired. + * + * @param DevNo device see @ref XNUCLEO53L1A1_dev_e + */ +void VL53L1A1_EXTI_IOUnconfigure(int DevNo); + +/** @} */ /* MSP_implement */ + + +#endif /* _X_NUCLEO_53L1A1_H_ */ diff --git a/vl53lx_uld/vl53l1_error_codes.h b/vl53lx_uld/vl53l1_error_codes.h new file mode 100644 index 0000000..cdc1ec9 --- /dev/null +++ b/vl53lx_uld/vl53l1_error_codes.h @@ -0,0 +1,253 @@ +/* +* Copyright (c) 2017, STMicroelectronics - All Rights Reserved +* +* This file is part of VL53L1 Core and is dual licensed, +* either 'STMicroelectronics +* Proprietary license' +* or 'BSD 3-clause "New" or "Revised" License' , at your option. +* +******************************************************************************** +* +* 'STMicroelectronics Proprietary license' +* +******************************************************************************** +* +* License terms: STMicroelectronics Proprietary in accordance with licensing +* terms at www.st.com/sla0081 +* +* STMicroelectronics confidential +* Reproduction and Communication of this document is strictly prohibited unless +* specifically authorized in writing by STMicroelectronics. +* +* +******************************************************************************** +* +* Alternatively, VL53L1 Core may be distributed under the terms of +* 'BSD 3-clause "New" or "Revised" License', in which case the following +* provisions apply instead of the ones mentioned above : +* +******************************************************************************** +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* 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 vl53l1_error_codes.h + * + * @brief Error Code definitions for VL53L1 API. + * + */ + +#ifndef _VL53L1_ERROR_CODES_H_ +#define _VL53L1_ERROR_CODES_H_ + +#include "vl53l1_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**************************************** + * PRIVATE define do not edit + ****************************************/ + +/** @defgroup VL53L1_define_Error_group Error and Warning code returned by API + * The following DEFINE are used to identify the PAL ERROR + * @{ + */ + +typedef int8_t VL53L1_Error; + +#define VL53L1_ERROR_NONE ((VL53L1_Error) 0) +#define VL53L1_ERROR_CALIBRATION_WARNING ((VL53L1_Error) - 1) + /*!< Warning invalid calibration data may be in used + \a VL53L1_InitData() + \a VL53L1_GetOffsetCalibrationData + \a VL53L1_SetOffsetCalibrationData */ +#define VL53L1_ERROR_MIN_CLIPPED ((VL53L1_Error) - 2) + /*!< Warning parameter passed was clipped to min before to be applied */ + +#define VL53L1_ERROR_UNDEFINED ((VL53L1_Error) - 3) + /*!< Unqualified error */ +#define VL53L1_ERROR_INVALID_PARAMS ((VL53L1_Error) - 4) + /*!< Parameter passed is invalid or out of range */ +#define VL53L1_ERROR_NOT_SUPPORTED ((VL53L1_Error) - 5) + /*!< Function is not supported in current mode or configuration */ +#define VL53L1_ERROR_RANGE_ERROR ((VL53L1_Error) - 6) + /*!< Device report a ranging error interrupt status */ +#define VL53L1_ERROR_TIME_OUT ((VL53L1_Error) - 7) + /*!< Aborted due to time out */ +#define VL53L1_ERROR_MODE_NOT_SUPPORTED ((VL53L1_Error) - 8) + /*!< Asked mode is not supported by the device */ +#define VL53L1_ERROR_BUFFER_TOO_SMALL ((VL53L1_Error) - 9) + /*!< ... */ +#define VL53L1_ERROR_COMMS_BUFFER_TOO_SMALL ((VL53L1_Error) - 10) + /*!< Supplied buffer is larger than I2C supports */ +#define VL53L1_ERROR_GPIO_NOT_EXISTING ((VL53L1_Error) - 11) + /*!< User tried to setup a non-existing GPIO pin */ +#define VL53L1_ERROR_GPIO_FUNCTIONALITY_NOT_SUPPORTED ((VL53L1_Error) - 12) + /*!< unsupported GPIO functionality */ +#define VL53L1_ERROR_CONTROL_INTERFACE ((VL53L1_Error) - 13) + /*!< error reported from IO functions */ +#define VL53L1_ERROR_INVALID_COMMAND ((VL53L1_Error) - 14) + /*!< The command is not allowed in the current device state + * (power down) */ +#define VL53L1_ERROR_DIVISION_BY_ZERO ((VL53L1_Error) - 15) + /*!< In the function a division by zero occurs */ +#define VL53L1_ERROR_REF_SPAD_INIT ((VL53L1_Error) - 16) + /*!< Error during reference SPAD initialization */ +#define VL53L1_ERROR_GPH_SYNC_CHECK_FAIL ((VL53L1_Error) - 17) + /*!< GPH sync interrupt check fail - API out of sync with device*/ +#define VL53L1_ERROR_STREAM_COUNT_CHECK_FAIL ((VL53L1_Error) - 18) + /*!< Stream count check fail - API out of sync with device */ +#define VL53L1_ERROR_GPH_ID_CHECK_FAIL ((VL53L1_Error) - 19) + /*!< GPH ID check fail - API out of sync with device */ +#define VL53L1_ERROR_ZONE_STREAM_COUNT_CHECK_FAIL ((VL53L1_Error) - 20) + /*!< Zone dynamic config stream count check failed - API out of sync */ +#define VL53L1_ERROR_ZONE_GPH_ID_CHECK_FAIL ((VL53L1_Error) - 21) + /*!< Zone dynamic config GPH ID check failed - API out of sync */ + +#define VL53L1_ERROR_XTALK_EXTRACTION_NO_SAMPLE_FAIL ((VL53L1_Error) - 22) + /*!< Thrown when run_xtalk_extraction fn has 0 succesful samples + * when using the full array to sample the xtalk. In this case there is + * not enough information to generate new Xtalk parm info. The function + * will exit and leave the current xtalk parameters unaltered */ +#define VL53L1_ERROR_XTALK_EXTRACTION_SIGMA_LIMIT_FAIL ((VL53L1_Error) - 23) + /*!< Thrown when run_xtalk_extraction fn has found that the + * avg sigma estimate of the full array xtalk sample is > than the + * maximal limit allowed. In this case the xtalk sample is too noisy for + * measurement. The function will exit and leave the current xtalk parameters + * unaltered. */ + + +#define VL53L1_ERROR_OFFSET_CAL_NO_SAMPLE_FAIL ((VL53L1_Error) - 24) + /*!< Thrown if there one of stages has no valid offset calibration + * samples. A fatal error calibration not valid */ +#define VL53L1_ERROR_OFFSET_CAL_NO_SPADS_ENABLED_FAIL ((VL53L1_Error) - 25) + /*!< Thrown if there one of stages has zero effective SPADS + * Traps the case when MM1 SPADs is zero. + * A fatal error calibration not valid */ +#define VL53L1_ERROR_ZONE_CAL_NO_SAMPLE_FAIL ((VL53L1_Error) - 26) + /*!< Thrown if then some of the zones have no valid samples + * A fatal error calibration not valid */ + +#define VL53L1_ERROR_TUNING_PARM_KEY_MISMATCH ((VL53L1_Error) - 27) + /*!< Thrown if the tuning file key table version does not match with + * expected value. The driver expects the key table version to match + * the compiled default version number in the define + * #VL53L1_TUNINGPARM_KEY_TABLE_VERSION_DEFAULT + * */ + +#define VL53L1_WARNING_REF_SPAD_CHAR_NOT_ENOUGH_SPADS ((VL53L1_Error) - 28) + /*!< Thrown if there are less than 5 good SPADs are available. */ +#define VL53L1_WARNING_REF_SPAD_CHAR_RATE_TOO_HIGH ((VL53L1_Error) - 29) + /*!< Thrown if the final reference rate is greater than + the upper reference rate limit - default is 40 Mcps. + Implies a minimum Q3 (x10) SPAD (5) selected */ +#define VL53L1_WARNING_REF_SPAD_CHAR_RATE_TOO_LOW ((VL53L1_Error) - 30) + /*!< Thrown if the final reference rate is less than + the lower reference rate limit - default is 10 Mcps. + Implies maximum Q1 (x1) SPADs selected */ + + +#define VL53L1_WARNING_OFFSET_CAL_MISSING_SAMPLES ((VL53L1_Error) - 31) + /*!< Thrown if there is less than the requested number of + * valid samples. */ +#define VL53L1_WARNING_OFFSET_CAL_SIGMA_TOO_HIGH ((VL53L1_Error) - 32) + /*!< Thrown if the offset calibration range sigma estimate is greater + * than 8.0 mm. This is the recommended min value to yield a stable + * offset measurement */ +#define VL53L1_WARNING_OFFSET_CAL_RATE_TOO_HIGH ((VL53L1_Error) - 33) + /*!< Thrown when VL53L1_run_offset_calibration() peak rate is greater + than that 50.0Mcps. This is the recommended max rate to avoid + pile-up influencing the offset measurement */ +#define VL53L1_WARNING_OFFSET_CAL_SPAD_COUNT_TOO_LOW ((VL53L1_Error) - 34) + /*!< Thrown when VL53L1_run_offset_calibration() when one of stages + range has less that 5.0 effective SPADS. This is the recommended + min value to yield a stable offset */ + + +#define VL53L1_WARNING_ZONE_CAL_MISSING_SAMPLES ((VL53L1_Error) - 35) + /*!< Thrown if one of more of the zones have less than + the requested number of valid samples */ +#define VL53L1_WARNING_ZONE_CAL_SIGMA_TOO_HIGH ((VL53L1_Error) - 36) + /*!< Thrown if one or more zones have sigma estimate value greater + * than 8.0 mm. This is the recommended min value to yield a stable + * offset measurement */ +#define VL53L1_WARNING_ZONE_CAL_RATE_TOO_HIGH ((VL53L1_Error) - 37) + /*!< Thrown if one of more zones have peak rate higher than + that 50.0Mcps. This is the recommended max rate to avoid + pile-up influencing the offset measurement */ + + +#define VL53L1_WARNING_XTALK_MISSING_SAMPLES ((VL53L1_Error) - 38) + /*!< Thrown to notify that some of the xtalk samples did not yield + * valid ranging pulse data while attempting to measure + * the xtalk signal in vl53l1_run_xtalk_extract(). This can signify any of + * the zones are missing samples, for further debug information the + * xtalk_results struct should be referred to. This warning is for + * notification only, the xtalk pulse and shape have still been generated + */ +#define VL53L1_WARNING_XTALK_NO_SAMPLES_FOR_GRADIENT ((VL53L1_Error) - 39) + /*!< Thrown to notify that some of teh xtalk samples used for gradient + * generation did not yield valid ranging pulse data while attempting to + * measure the xtalk signal in vl53l1_run_xtalk_extract(). This can signify + * that any one of the zones 0-3 yielded no successful samples. The + * xtalk_results struct should be referred to for further debug info. + * This warning is for notification only, the xtalk pulse and shape + * have still been generated. + */ +#define VL53L1_WARNING_XTALK_SIGMA_LIMIT_FOR_GRADIENT ((VL53L1_Error) - 40) +/*!< Thrown to notify that some of the xtalk samples used for gradient + * generation did not pass the sigma limit check while attempting to + * measure the xtalk signal in vl53l1_run_xtalk_extract(). This can signify + * that any one of the zones 0-3 yielded an avg sigma_mm value > the limit. + * The xtalk_results struct should be referred to for further debug info. + * This warning is for notification only, the xtalk pulse and shape + * have still been generated. + */ + +#define VL53L1_ERROR_NOT_IMPLEMENTED ((VL53L1_Error) - 41) + /*!< Tells requested functionality has not been implemented yet or + * not compatible with the device */ +#define VL53L1_ERROR_PLATFORM_SPECIFIC_START ((VL53L1_Error) - 60) + /*!< Tells the starting code for platform */ +/** @} VL53L1_define_Error_group */ + + +#ifdef __cplusplus +} +#endif + + +#endif /* _VL53L1_ERROR_CODES_H_ */ diff --git a/vl53lx_uld/vl53l1_platform.c b/vl53lx_uld/vl53l1_platform.c new file mode 100644 index 0000000..83cd535 --- /dev/null +++ b/vl53lx_uld/vl53l1_platform.c @@ -0,0 +1,431 @@ + +/* +* This file is part of VL53L1 Platform +* +* Copyright (c) 2016, STMicroelectronics - All Rights Reserved +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* 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. +* +*/ + + +#include "vl53l1_platform.h" +#include "vl53l1_platform_log.h" +//#include "vl53l1_api.h" +#include "vl53l1_platform_user_config.h" +#include "stm32wlxx_hal.h" +#include +#include +#include +#include "vl53l1_error_codes.h" +#include "X-NUCLEO-53L1A1.h" + + +#define I2C_TIME_OUT_BASE 10 +#define I2C_TIME_OUT_BYTE 1 + +#ifdef VL53L1_LOG_ENABLE +#define trace_print(level, ...) VL53L1_trace_print_module_function(VL53L1_TRACE_MODULE_PLATFORM, level, VL53L1_TRACE_FUNCTION_NONE, ##__VA_ARGS__) +#define trace_i2c(...) VL53L1_trace_print_module_function(VL53L1_TRACE_MODULE_NONE, VL53L1_TRACE_LEVEL_NONE, VL53L1_TRACE_FUNCTION_I2C, ##__VA_ARGS__) +#endif + +#ifndef HAL_I2C_MODULE_ENABLED +#warning "HAL I2C module must be enable " +#endif + +//#define VL53L0X_pI2cHandle (&hi2c1) + +/* when not customized by application define dummy one */ +#ifndef VL53L1_GetI2cBus +/** This macro can be overloaded by user to enforce i2c sharing in RTOS context + */ +# define VL53L1_GetI2cBus(...) (void)0 +#endif + +#ifndef VL53L1_PutI2cBus +/** This macro can be overloaded by user to enforce i2c sharing in RTOS context + */ +# define VL53L1_PutI2cBus(...) (void)0 +#endif + +uint8_t _I2CBuffer[256]; + +int _I2CWrite(uint16_t Dev, uint8_t *pdata, uint32_t count) { + int status; + int i2c_time_out = I2C_TIME_OUT_BASE+ count* I2C_TIME_OUT_BYTE; + + status = HAL_I2C_Master_Transmit(&XNUCLEO53L1A1_hi2c, Dev, pdata, count, i2c_time_out); + if (status) { + //VL6180x_ErrLog("I2C error 0x%x %d len", dev->I2cAddr, len); + //XNUCLEO6180XA1_I2C1_Init(&hi2c1); + } + return status; +} + +int _I2CRead(uint16_t Dev, uint8_t *pdata, uint32_t count) { + int status; + int i2c_time_out = I2C_TIME_OUT_BASE+ count* I2C_TIME_OUT_BYTE; + + status = HAL_I2C_Master_Receive(&XNUCLEO53L1A1_hi2c, Dev|1, pdata, count, i2c_time_out); + if (status) { + //VL6180x_ErrLog("I2C error 0x%x %d len", dev->I2cAddr, len); + //XNUCLEO6180XA1_I2C1_Init(&hi2c1); + } + return status; +} + +VL53L1_Error VL53L1_WriteMulti(uint16_t Dev, uint16_t index, uint8_t *pdata, uint32_t count) { + int status_int; + VL53L1_Error Status = VL53L1_ERROR_NONE; + if (count > sizeof(_I2CBuffer) - 1) { + return VL53L1_ERROR_INVALID_PARAMS; + } + _I2CBuffer[0] = index>>8; + _I2CBuffer[1] = index&0xFF; + memcpy(&_I2CBuffer[2], pdata, count); + VL53L1_GetI2cBus(); + status_int = _I2CWrite(Dev, _I2CBuffer, count + 2); + if (status_int != 0) { + Status = VL53L1_ERROR_CONTROL_INTERFACE; + } + VL53L1_PutI2cBus(); + return Status; +} + +// the ranging_sensor_comms.dll will take care of the page selection +VL53L1_Error VL53L1_ReadMulti(uint16_t Dev, uint16_t index, uint8_t *pdata, uint32_t count) { + VL53L1_Error Status = VL53L1_ERROR_NONE; + int32_t status_int; + + _I2CBuffer[0] = index>>8; + _I2CBuffer[1] = index&0xFF; + VL53L1_GetI2cBus(); + status_int = _I2CWrite(Dev, _I2CBuffer, 2); + if (status_int != 0) { + Status = VL53L1_ERROR_CONTROL_INTERFACE; + goto done; + } + status_int = _I2CRead(Dev, pdata, count); + if (status_int != 0) { + Status = VL53L1_ERROR_CONTROL_INTERFACE; + } +done: + VL53L1_PutI2cBus(); + return Status; +} + +VL53L1_Error VL53L1_WrByte(uint16_t Dev, uint16_t index, uint8_t data) { + VL53L1_Error Status = VL53L1_ERROR_NONE; + int32_t status_int; + + _I2CBuffer[0] = index>>8; + _I2CBuffer[1] = index&0xFF; + _I2CBuffer[2] = data; + + VL53L1_GetI2cBus(); + status_int = _I2CWrite(Dev, _I2CBuffer, 3); + if (status_int != 0) { + Status = VL53L1_ERROR_CONTROL_INTERFACE; + } + VL53L1_PutI2cBus(); + return Status; +} + +VL53L1_Error VL53L1_WrWord(uint16_t Dev, uint16_t index, uint16_t data) { + VL53L1_Error Status = VL53L1_ERROR_NONE; + int32_t status_int; + + _I2CBuffer[0] = index>>8; + _I2CBuffer[1] = index&0xFF; + _I2CBuffer[2] = data >> 8; + _I2CBuffer[3] = data & 0x00FF; + + VL53L1_GetI2cBus(); + status_int = _I2CWrite(Dev, _I2CBuffer, 4); + if (status_int != 0) { + Status = VL53L1_ERROR_CONTROL_INTERFACE; + } + VL53L1_PutI2cBus(); + return Status; +} + +VL53L1_Error VL53L1_WrDWord(uint16_t Dev, uint16_t index, uint32_t data) { + VL53L1_Error Status = VL53L1_ERROR_NONE; + int32_t status_int; + _I2CBuffer[0] = index>>8; + _I2CBuffer[1] = index&0xFF; + _I2CBuffer[2] = (data >> 24) & 0xFF; + _I2CBuffer[3] = (data >> 16) & 0xFF; + _I2CBuffer[4] = (data >> 8) & 0xFF; + _I2CBuffer[5] = (data >> 0 ) & 0xFF; + VL53L1_GetI2cBus(); + status_int = _I2CWrite(Dev, _I2CBuffer, 6); + if (status_int != 0) { + Status = VL53L1_ERROR_CONTROL_INTERFACE; + } + VL53L1_PutI2cBus(); + return Status; +} + +VL53L1_Error VL53L1_UpdateByte(uint16_t Dev, uint16_t index, uint8_t AndData, uint8_t OrData) { + VL53L1_Error Status = VL53L1_ERROR_NONE; + uint8_t data; + + Status = VL53L1_RdByte(Dev, index, &data); + if (Status) { + goto done; + } + data = (data & AndData) | OrData; + Status = VL53L1_WrByte(Dev, index, data); +done: + return Status; +} + +VL53L1_Error VL53L1_RdByte(uint16_t Dev, uint16_t index, uint8_t *data) { + VL53L1_Error Status = VL53L1_ERROR_NONE; + int32_t status_int; + + _I2CBuffer[0] = index>>8; + _I2CBuffer[1] = index&0xFF; + VL53L1_GetI2cBus(); + status_int = _I2CWrite(Dev, _I2CBuffer, 2); + if( status_int ){ + Status = VL53L1_ERROR_CONTROL_INTERFACE; + goto done; + } + status_int = _I2CRead(Dev, data, 1); + if (status_int != 0) { + Status = VL53L1_ERROR_CONTROL_INTERFACE; + } +done: + VL53L1_PutI2cBus(); + return Status; +} + +VL53L1_Error VL53L1_RdWord(uint16_t Dev, uint16_t index, uint16_t *data) { + VL53L1_Error Status = VL53L1_ERROR_NONE; + int32_t status_int; + + _I2CBuffer[0] = index>>8; + _I2CBuffer[1] = index&0xFF; + VL53L1_GetI2cBus(); + status_int = _I2CWrite(Dev, _I2CBuffer, 2); + + if( status_int ){ + Status = VL53L1_ERROR_CONTROL_INTERFACE; + goto done; + } + status_int = _I2CRead(Dev, _I2CBuffer, 2); + if (status_int != 0) { + Status = VL53L1_ERROR_CONTROL_INTERFACE; + goto done; + } + + *data = ((uint16_t)_I2CBuffer[0]<<8) + (uint16_t)_I2CBuffer[1]; +done: + VL53L1_PutI2cBus(); + return Status; +} + +VL53L1_Error VL53L1_RdDWord(uint16_t Dev, uint16_t index, uint32_t *data) { + VL53L1_Error Status = VL53L1_ERROR_NONE; + int32_t status_int; + + _I2CBuffer[0] = index>>8; + _I2CBuffer[1] = index&0xFF; + VL53L1_GetI2cBus(); + status_int = _I2CWrite(Dev, _I2CBuffer, 2); + if (status_int != 0) { + Status = VL53L1_ERROR_CONTROL_INTERFACE; + goto done; + } + status_int = _I2CRead(Dev, _I2CBuffer, 4); + if (status_int != 0) { + Status = VL53L1_ERROR_CONTROL_INTERFACE; + goto done; + } + + *data = ((uint32_t)_I2CBuffer[0]<<24) + ((uint32_t)_I2CBuffer[1]<<16) + ((uint32_t)_I2CBuffer[2]<<8) + (uint32_t)_I2CBuffer[3]; + +done: + VL53L1_PutI2cBus(); + return Status; +} + +VL53L1_Error VL53L1_GetTickCount( + uint32_t *ptick_count_ms) +{ + + /* Returns current tick count in [ms] */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + + //*ptick_count_ms = timeGetTime(); + *ptick_count_ms = 0; + +#ifdef VL53L1_LOG_ENABLE + trace_print( + VL53L1_TRACE_LEVEL_DEBUG, + "VL53L1_GetTickCount() = %5u ms;\n", + *ptick_count_ms); +#endif + + return status; +} + + +#define trace_print(level, ...) \ + _LOG_TRACE_PRINT(VL53L1_TRACE_MODULE_PLATFORM, \ + level, VL53L1_TRACE_FUNCTION_NONE, ##__VA_ARGS__) + +#define trace_i2c(...) \ + _LOG_TRACE_PRINT(VL53L1_TRACE_MODULE_NONE, \ + VL53L1_TRACE_LEVEL_NONE, VL53L1_TRACE_FUNCTION_I2C, ##__VA_ARGS__) + + +VL53L1_Error VL53L1_GetTimerFrequency(int32_t *ptimer_freq_hz) +{ + *ptimer_freq_hz = 0; + + trace_print(VL53L1_TRACE_LEVEL_INFO, "VL53L1_GetTimerFrequency: Freq : %dHz\n", *ptimer_freq_hz); + return VL53L1_ERROR_NONE; +} + + +VL53L1_Error VL53L1_WaitMs(uint16_t dev, int32_t wait_ms){ + (void)dev; + HAL_Delay(wait_ms); + return VL53L1_ERROR_NONE; +} + +VL53L1_Error VL53L1_WaitUs(uint16_t dev, int32_t wait_us){ + (void)dev; + HAL_Delay(wait_us/1000); + return VL53L1_ERROR_NONE; +} + +VL53L1_Error VL53L1_WaitValueMaskEx( + uint16_t dev, + uint32_t timeout_ms, + uint16_t index, + uint8_t value, + uint8_t mask, + uint32_t poll_delay_ms) +{ + + /* + * Platform implementation of WaitValueMaskEx V2WReg script command + * + * WaitValueMaskEx( + * duration_ms, + * index, + * value, + * mask, + * poll_delay_ms); + */ + + VL53L1_Error status = VL53L1_ERROR_NONE; + uint32_t start_time_ms = 0; + uint32_t current_time_ms = 0; + uint32_t polling_time_ms = 0; + uint8_t byte_value = 0; + uint8_t found = 0; +#ifdef VL53L1_LOG_ENABLE + uint8_t trace_functions = VL53L1_TRACE_FUNCTION_NONE; +#endif + +// char register_name[VL53L1_MAX_STRING_LENGTH]; + + /* look up register name */ +#ifdef PAL_EXTENDED + VL53L1_get_register_name( + index, + register_name); +#else +// VL53L1_COPYSTRING(register_name, ""); +#endif + + /* Output to I2C logger for FMT/DFT */ + + /*trace_i2c("WaitValueMaskEx(%5d, 0x%04X, 0x%02X, 0x%02X, %5d);\n", + timeout_ms, index, value, mask, poll_delay_ms); */ + trace_i2c("WaitValueMaskEx(%5d, %s, 0x%02X, 0x%02X, %5d);\n", + timeout_ms, register_name, value, mask, poll_delay_ms); + + /* calculate time limit in absolute time */ + + VL53L1_GetTickCount(&start_time_ms); + + /* remember current trace functions and temporarily disable + * function logging + */ + +#ifdef VL53L1_LOG_ENABLE + trace_functions = VL53L1_get_trace_functions(); + VL53L1_set_trace_functions(VL53L1_TRACE_FUNCTION_NONE); +#endif + + /* wait until value is found, timeout reached on error occurred */ + + while ((status == VL53L1_ERROR_NONE) && + (polling_time_ms < timeout_ms) && + (found == 0)) { + + if (status == VL53L1_ERROR_NONE) + status = VL53L1_RdByte( + dev, + index, + &byte_value); + + if ((byte_value & mask) == value) + found = 1; + + if (status == VL53L1_ERROR_NONE && + found == 0 && + poll_delay_ms > 0) + status = VL53L1_WaitMs( + dev, + poll_delay_ms); + + /* Update polling time (Compare difference rather than absolute to + negate 32bit wrap around issue) */ + VL53L1_GetTickCount(¤t_time_ms); + polling_time_ms = current_time_ms - start_time_ms; + + } + +#ifdef VL53L1_LOG_ENABLE + /* Restore function logging */ + VL53L1_set_trace_functions(trace_functions); +#endif + + if (found == 0 && status == VL53L1_ERROR_NONE) + status = VL53L1_ERROR_TIME_OUT; + + return status; +} diff --git a/vl53lx_uld/vl53l1_platform.h b/vl53lx_uld/vl53l1_platform.h new file mode 100644 index 0000000..e659bc8 --- /dev/null +++ b/vl53lx_uld/vl53l1_platform.h @@ -0,0 +1,141 @@ + +/* +* This file is part of VL53L1 Platform +* +* Copyright (c) 2016, STMicroelectronics - All Rights Reserved +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* 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. +* +*/ + +#ifndef _VL53L1_PLATFORM_H_ +#define _VL53L1_PLATFORM_H_ +#include "stm32wlxx_hal.h" +#include "vl53l1_platform_log.h" +#include "vl53l1_types.h" +#include "vl53l1_error_codes.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +VL53L1_Error VL53L1_CommsInitialise( + uint16_t dev, + uint8_t comms_type, + uint16_t comms_speed_khz); + +VL53L1_Error VL53L1_CommsClose( + uint16_t dev); + +VL53L1_Error VL53L1_WriteMulti( + uint16_t dev, + uint16_t index, + uint8_t *pdata, + uint32_t count); + +VL53L1_Error VL53L1_ReadMulti( + uint16_t dev, + uint16_t index, + uint8_t *pdata, + uint32_t count); + +VL53L1_Error VL53L1_WrByte( + uint16_t dev, + uint16_t index, + uint8_t VL53L1_PRM_00005); + +VL53L1_Error VL53L1_WrWord( + uint16_t dev, + uint16_t index, + uint16_t VL53L1_PRM_00005); + +VL53L1_Error VL53L1_WrDWord( + uint16_t dev, + uint16_t index, + uint32_t VL53L1_PRM_00005); + +VL53L1_Error VL53L1_RdByte( + uint16_t dev, + uint16_t index, + uint8_t *pdata); + +VL53L1_Error VL53L1_RdWord( + uint16_t dev, + uint16_t index, + uint16_t *pdata); + +VL53L1_Error VL53L1_RdDWord( + uint16_t dev, + uint16_t index, + uint32_t *pdata); + +VL53L1_Error VL53L1_WaitUs( + uint16_t dev, + int32_t wait_us); + +VL53L1_Error VL53L1_WaitMs( + uint16_t dev, + int32_t wait_ms); + +VL53L1_Error VL53L1_GetTimerFrequency(int32_t *ptimer_freq_hz); + +VL53L1_Error VL53L1_GetTimerValue(int32_t *ptimer_count); + +VL53L1_Error VL53L1_GpioSetMode(uint8_t pin, uint8_t mode); + +VL53L1_Error VL53L1_GpioSetValue(uint8_t pin, uint8_t value); + +VL53L1_Error VL53L1_GpioGetValue(uint8_t pin, uint8_t *pvalue); + +VL53L1_Error VL53L1_GpioXshutdown(uint8_t value); + +VL53L1_Error VL53L1_GpioCommsSelect(uint8_t value); + +VL53L1_Error VL53L1_GpioPowerEnable(uint8_t value); + +VL53L1_Error VL53L1_GpioInterruptEnable(void (*function)(void), uint8_t edge_type); + +VL53L1_Error VL53L1_GpioInterruptDisable(void); + +VL53L1_Error VL53L1_GetTickCount( + uint32_t *ptime_ms); + +VL53L1_Error VL53L1_WaitValueMaskEx( + uint16_t dev, + uint32_t timeout_ms, + uint16_t index, + uint8_t value, + uint8_t mask, + uint32_t poll_delay_ms); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/vl53lx_uld/vl53l1_platform_log.h b/vl53lx_uld/vl53l1_platform_log.h new file mode 100644 index 0000000..5bff5bd --- /dev/null +++ b/vl53lx_uld/vl53l1_platform_log.h @@ -0,0 +1,223 @@ +/******************************************************************************* +Copyright (C) 2015, STMicroelectronics International N.V. +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 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, FITNESS FOR A PARTICULAR PURPOSE, AND +NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED. +IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. 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 vl53l1_platform_log.h + * + * @brief EwokPlus25 platform logging function definition + */ + + +#ifndef _VL53L1_PLATFORM_LOG_H_ +#define _VL53L1_PLATFORM_LOG_H_ + + +#ifdef VL53L1_LOG_ENABLE + #include "vl53l1_platform_user_config.h" + + #ifdef _MSC_VER + # define EWOKPLUS_EXPORTS __declspec(dllexport) + #else + # define EWOKPLUS_EXPORTS + #endif + + #include "vl53l1_types.h" + + #ifdef __cplusplus + extern "C" { + #endif + + #include + + /** + * @brief Set the level, output and specific functions for module logging. + * + * + * @param filename - full path of output log file, NULL for print to stdout + * + * @param modules - Module or None or All to trace + * VL53L1_TRACE_MODULE_NONE + * VL53L1_TRACE_MODULE_API + * VL53L1_TRACE_MODULE_CORE + * VL53L1_TRACE_MODULE_TUNING + * VL53L1_TRACE_MODULE_CHARACTERISATION + * VL53L1_TRACE_MODULE_PLATFORM + * VL53L1_TRACE_MODULE_ALL + * + * @param level - trace level + * VL53L1_TRACE_LEVEL_NONE + * VL53L1_TRACE_LEVEL_ERRORS + * VL53L1_TRACE_LEVEL_WARNING + * VL53L1_TRACE_LEVEL_INFO + * VL53L1_TRACE_LEVEL_DEBUG + * VL53L1_TRACE_LEVEL_ALL + * VL53L1_TRACE_LEVEL_IGNORE + * + * @param functions - function level to trace; + * VL53L1_TRACE_FUNCTION_NONE + * VL53L1_TRACE_FUNCTION_I2C + * VL53L1_TRACE_FUNCTION_ALL + * + * @return status - always VL53L1_ERROR_NONE + * + */ + + #define VL53L1_TRACE_LEVEL_NONE 0x00000000 + #define VL53L1_TRACE_LEVEL_ERRORS 0x00000001 + #define VL53L1_TRACE_LEVEL_WARNING 0x00000002 + #define VL53L1_TRACE_LEVEL_INFO 0x00000004 + #define VL53L1_TRACE_LEVEL_DEBUG 0x00000008 + #define VL53L1_TRACE_LEVEL_ALL 0x00000010 + #define VL53L1_TRACE_LEVEL_IGNORE 0x00000020 + + #define VL53L1_TRACE_FUNCTION_NONE 0x00000000 + #define VL53L1_TRACE_FUNCTION_I2C 0x00000001 + #define VL53L1_TRACE_FUNCTION_ALL 0x7fffffff + + #define VL53L1_TRACE_MODULE_NONE 0x00000000 + #define VL53L1_TRACE_MODULE_API 0x00000001 + #define VL53L1_TRACE_MODULE_CORE 0x00000002 + #define VL53L1_TRACE_MODULE_PROTECTED 0x00000004 + #define VL53L1_TRACE_MODULE_HISTOGRAM 0x00000008 + #define VL53L1_TRACE_MODULE_REGISTERS 0x00000010 + #define VL53L1_TRACE_MODULE_PLATFORM 0x00000020 + #define VL53L1_TRACE_MODULE_NVM 0x00000040 + #define VL53L1_TRACE_MODULE_CALIBRATION_DATA 0x00000080 + #define VL53L1_TRACE_MODULE_NVM_DATA 0x00000100 + #define VL53L1_TRACE_MODULE_HISTOGRAM_DATA 0x00000200 + #define VL53L1_TRACE_MODULE_RANGE_RESULTS_DATA 0x00000400 + #define VL53L1_TRACE_MODULE_XTALK_DATA 0x00000800 + #define VL53L1_TRACE_MODULE_OFFSET_DATA 0x00001000 + #define VL53L1_TRACE_MODULE_DATA_INIT 0x00002000 + #define VL53L1_TRACE_MODULE_REF_SPAD_CHAR 0x00004000 + #define VL53L1_TRACE_MODULE_SPAD_RATE_MAP 0x00008000 + #ifdef PAL_EXTENDED + #define VL53L1_TRACE_MODULE_SPAD 0x01000000 + #define VL53L1_TRACE_MODULE_FMT 0x02000000 + #define VL53L1_TRACE_MODULE_UTILS 0x04000000 + #define VL53L1_TRACE_MODULE_BENCH_FUNCS 0x08000000 + #endif + #define VL53L1_TRACE_MODULE_CUSTOMER_API 0x40000000 + #define VL53L1_TRACE_MODULE_ALL 0x7fffffff + + + extern uint32_t _trace_level; + + /* + * NOTE: dynamically exported if we enable logging. + * this way, Python interfaces can access this function, but we don't + * need to include it in the .def files. + */ + EWOKPLUS_EXPORTS int8_t VL53L1_trace_config( + char *filename, + uint32_t modules, + uint32_t level, + uint32_t functions); + + /** + * @brief Print trace module function. + * + * @param module - ?? + * @param level - ?? + * @param function - ?? + * @param format - ?? + * + */ + + EWOKPLUS_EXPORTS void VL53L1_trace_print_module_function( + uint32_t module, + uint32_t level, + uint32_t function, + const char *format, ...); + + /** + * @brief Get global _trace_functions parameter + * + * @return _trace_functions + */ + + uint32_t VL53L1_get_trace_functions(void); + + /** + * @brief Set global _trace_functions parameter + * + * @param[in] function : new function code + */ + + void VL53L1_set_trace_functions(uint32_t function); + + + /* + * @brief Returns the current system tick count in [ms] + * + * @return time_ms : current time in [ms] + * + */ + + uint32_t VL53L1_clock(void); + + #define LOG_GET_TIME() \ + ((int)VL53L1_clock()) + + #define _LOG_TRACE_PRINT(module, level, function, ...) \ + VL53L1_trace_print_module_function(module, level, function, ##__VA_ARGS__); + + #define _LOG_FUNCTION_START(module, fmt, ...) \ + VL53L1_trace_print_module_function(module, _trace_level, VL53L1_TRACE_FUNCTION_ALL, "%6ld %s "fmt"\n", LOG_GET_TIME(), __FUNCTION__, ##__VA_ARGS__); + + #define _LOG_FUNCTION_END(module, status, ...)\ + VL53L1_trace_print_module_function(module, _trace_level, VL53L1_TRACE_FUNCTION_ALL, "%6ld %s %d\n", LOG_GET_TIME(), __FUNCTION__, (int)status, ##__VA_ARGS__) + + #define _LOG_FUNCTION_END_FMT(module, status, fmt, ...)\ + VL53L1_trace_print_module_function(module, _trace_level, VL53L1_TRACE_FUNCTION_ALL, "%6ld %s %d "fmt"\n", LOG_GET_TIME(), __FUNCTION__, (int)status, ##__VA_ARGS__) + + #define _LOG_GET_TRACE_FUNCTIONS()\ + VL53L1_get_trace_functions() + + #define _LOG_SET_TRACE_FUNCTIONS(functions)\ + VL53L1_set_trace_functions(functions) + + #define _LOG_STRING_BUFFER(x) char x[VL53L1_MAX_STRING_LENGTH] + + #ifdef __cplusplus + } + #endif + +#else /* VL53L1_LOG_ENABLE - no logging */ + + #define _LOG_TRACE_PRINT(module, level, function, ...) + #define _LOG_FUNCTION_START(module, fmt, ...) + #define _LOG_FUNCTION_END(module, status, ...) + #define _LOG_FUNCTION_END_FMT(module, status, fmt, ...) + #define _LOG_GET_TRACE_FUNCTIONS() 0 + #define _LOG_SET_TRACE_FUNCTIONS(functions) + #define _LOG_STRING_BUFFER(x) + +#endif /* VL53L1_LOG_ENABLE */ + +#endif /* _VL53L1_PLATFORM_LOG_H_ */ diff --git a/vl53lx_uld/vl53l1_platform_user_config.h b/vl53lx_uld/vl53l1_platform_user_config.h new file mode 100644 index 0000000..166a023 --- /dev/null +++ b/vl53lx_uld/vl53l1_platform_user_config.h @@ -0,0 +1,84 @@ +/******************************************************************************* +Copyright (C) 2015, STMicroelectronics International N.V. +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 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, FITNESS FOR A PARTICULAR PURPOSE, AND +NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED. +IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. 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 vl53l1_platform_user_config.h + * + * @brief EwokPlus compile time user modifiable configuration + */ + + +#ifndef _VL53L1_PLATFORM_USER_CONFIG_H_ +#define _VL53L1_PLATFORM_USER_CONFIG_H_ + +#define VL53L1_BYTES_PER_WORD 2 +#define VL53L1_BYTES_PER_DWORD 4 + +/* Define polling delays */ +#define VL53L1_BOOT_COMPLETION_POLLING_TIMEOUT_MS 500 +#define VL53L1_RANGE_COMPLETION_POLLING_TIMEOUT_MS 2000 +#define VL53L1_TEST_COMPLETION_POLLING_TIMEOUT_MS 60000 + +#define VL53L1_POLLING_DELAY_MS 1 + +/* Define LLD TuningParms Page Base Address + * - Part of Patch_AddedTuningParms_11761 + */ +#define VL53L1_TUNINGPARM_PUBLIC_PAGE_BASE_ADDRESS 0x8000 +#define VL53L1_TUNINGPARM_PRIVATE_PAGE_BASE_ADDRESS 0xC000 + +#define VL53L1_GAIN_FACTOR__STANDARD_DEFAULT 0x0800 + /*!< Default standard ranging gain correction factor + 1.11 format. 1.0 = 0x0800, 0.980 = 0x07D7 */ + +#define VL53L1_OFFSET_CAL_MIN_EFFECTIVE_SPADS 0x0500 + /*!< Lower Limit for the MM1 effective SPAD count during offset + calibration Format 8.8 0x0500 -> 5.0 effective SPADs */ + +#define VL53L1_OFFSET_CAL_MAX_PRE_PEAK_RATE_MCPS 0x1900 + /*!< Max Limit for the pre range peak rate during offset + calibration Format 9.7 0x1900 -> 50.0 Mcps. + If larger then in pile up */ + +#define VL53L1_OFFSET_CAL_MAX_SIGMA_MM 0x0040 + /*!< Max sigma estimate limit during offset calibration + Check applies to pre-range, mm1 and mm2 ranges + Format 14.2 0x0040 -> 16.0mm. */ + +#define VL53L1_MAX_USER_ZONES 169 + /*!< Max number of user Zones - maximal limitation from + FW stream divide - value of 254 */ + +#define VL53L1_MAX_RANGE_RESULTS 2 + /*!< Allocates storage for return and reference restults */ + + +#define VL53L1_MAX_STRING_LENGTH 512 + +#endif /* _VL53L1_PLATFORM_USER_CONFIG_H_ */ + diff --git a/vl53lx_uld/vl53l1_platform_user_data.h b/vl53lx_uld/vl53l1_platform_user_data.h new file mode 100644 index 0000000..4a4e162 --- /dev/null +++ b/vl53lx_uld/vl53l1_platform_user_data.h @@ -0,0 +1,66 @@ + +/* +* This file is part of VL53L1 Platform +* +* Copyright (c) 2016, STMicroelectronics - All Rights Reserved +* +* License terms: BSD 3-clause "New" or "Revised" License. +* +* 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 PROFIT S; 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. +* +*/ + +#ifndef _VL53L1_PLATFORM_USER_DATA_H_ +#define _VL53L1_PLATFORM_USER_DATA_H_ +#include "stm32xxx_hal.h" +//#include "vl53l1_def.h" +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef struct { + + VL53L1_DevData_t Data; + + uint8_t I2cDevAddr; + uint8_t comms_type; + uint16_t comms_speed_khz; + uint32_t new_data_ready_poll_duration_ms; + I2C_HandleTypeDef *I2cHandle; + +} VL53L1_Dev_t; + +typedef VL53L1_Dev_t *VL53L1_DEV; + +#define VL53L1DevDataGet(Dev, field) (Dev->Data.field) +#define VL53L1DevDataSet(Dev, field, VL53L1_PRM_00005) ((Dev->Data.field) = (VL53L1_PRM_00005)) +#define VL53L1DevStructGetLLDriverHandle(Dev) (&Dev->Data.LLData) +#define VL53L1DevStructGetLLResultsHandle(Dev) (&Dev->Data.llresults) +#ifdef __cplusplus +} +#endif +#endif diff --git a/vl53lx_uld/vl53l1_platform_user_defines.h b/vl53lx_uld/vl53l1_platform_user_defines.h new file mode 100644 index 0000000..04ad850 --- /dev/null +++ b/vl53lx_uld/vl53l1_platform_user_defines.h @@ -0,0 +1,95 @@ +/******************************************************************************* + Copyright (C) 2016, STMicroelectronics International N.V. + 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 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, FITNESS FOR A PARTICULAR PURPOSE, AND + NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED. + IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. 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. + ******************************************************************************/ + + +#ifndef _VL53L1_PLATFORM_USER_DEFINES_H_ +#define _VL53L1_PLATFORM_USER_DEFINES_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @file vl53l1_platform_user_defines.h + * + * @brief All end user OS/platform/application definitions + */ + + +/** + * @def do_division_u + * @brief customer supplied division operation - 64-bit unsigned + * + * @param dividend unsigned 64-bit numerator + * @param divisor unsigned 64-bit denominator + */ +#define do_division_u(dividend, divisor) (dividend / divisor) + + +/** + * @def do_division_s + * @brief customer supplied division operation - 64-bit signed + * + * @param dividend signed 64-bit numerator + * @param divisor signed 64-bit denominator + */ +#define do_division_s(dividend, divisor) (dividend / divisor) + + +/** + * @def WARN_OVERRIDE_STATUS + * @brief customer supplied macro to optionally output info when a specific + error has been overridden with success within the EwokPlus driver + * + * @param __X__ the macro which enabled the suppression + */ +#define WARN_OVERRIDE_STATUS(__X__)\ + trace_print (VL53L1_TRACE_LEVEL_WARNING, #__X__); + + +#ifdef _MSC_VER +#define DISABLE_WARNINGS() { \ + __pragma (warning (push)); \ + __pragma (warning (disable:4127)); \ + } +#define ENABLE_WARNINGS() { \ + __pragma (warning (pop)); \ + } +#else + #define DISABLE_WARNINGS() + #define ENABLE_WARNINGS() +#endif + + +#ifdef __cplusplus +} +#endif + +#endif // _VL53L1_PLATFORM_USER_DEFINES_H_ + diff --git a/vl53lx_uld/vl53l1_types.h b/vl53lx_uld/vl53l1_types.h new file mode 100644 index 0000000..c0603b7 --- /dev/null +++ b/vl53lx_uld/vl53l1_types.h @@ -0,0 +1,114 @@ +/******************************************************************************* +Copyright (C) 2015, STMicroelectronics International N.V. +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 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, FITNESS FOR A PARTICULAR PURPOSE, AND +NON-INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS ARE DISCLAIMED. +IN NO EVENT SHALL STMICROELECTRONICS INTERNATIONAL N.V. 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 vl53l1_types.h + * @brief VL53L1 types definition + */ + +#ifndef _VL53L1_TYPES_H_ +#define _VL53L1_TYPES_H_ + +/** @defgroup porting_type Basic type definition + * @ingroup api_platform + * + * @brief file vl53l1_types.h files hold basic type definition that may requires porting + * + * contains type that must be defined for the platform\n + * when target platform and compiler provide stdint.h and stddef.h it is enough to include it.\n + * If stdint.h is not available review and adapt all signed and unsigned 8/16/32 bits basic types. \n + * If stddef.h is not available review and adapt NULL definition . + */ +#include +#include +#include +#include +#include + +#ifndef NULL +#error "Error NULL definition should be done. Please add required include " +#endif + + +#if !defined(STDINT_H) && !defined(_STDINT_H) && !defined(_GCC_STDINT_H) && !defined(__STDINT_DECLS) && !defined(_GCC_WRAP_STDINT_H) && !defined(_STDINT) + + #pragma message("Please review type definition of STDINT define for your platform and add to list above ") + + /* + * target platform do not provide stdint or use a different #define than above + * to avoid seeing the message below addapt the #define list above or implement + * all type and delete these pragma + */ + +/** \ingroup VL53L1_portingType_group + * @{ + */ + + +typedef unsigned long long uint64_t; + + +/** @brief Typedef defining 32 bit unsigned int type.\n + * The developer should modify this to suit the platform being deployed. + */ +typedef unsigned int uint32_t; + +/** @brief Typedef defining 32 bit int type.\n + * The developer should modify this to suit the platform being deployed. + */ +typedef int int32_t; + +/** @brief Typedef defining 16 bit unsigned short type.\n + * The developer should modify this to suit the platform being deployed. + */ +typedef unsigned short uint16_t; + +/** @brief Typedef defining 16 bit short type.\n + * The developer should modify this to suit the platform being deployed. + */ +typedef short int16_t; + +/** @brief Typedef defining 8 bit unsigned char type.\n + * The developer should modify this to suit the platform being deployed. + */ +typedef unsigned char uint8_t; + +/** @brief Typedef defining 8 bit char type.\n + * The developer should modify this to suit the platform being deployed. + */ +typedef signed char int8_t; + +/** @} */ +#endif /* _STDINT_H */ + + +/** use where fractional values are expected + * + * Given a floating point value f it's .16 bit point is (int)(f*(1<<16))*/ +typedef uint32_t FixPoint1616_t; + +#endif /* VL53L1_TYPES_H_ */ -- 2.40.1 From 3d80479b6a29b4778ab1f025a1873c665cf7a2b7 Mon Sep 17 00:00:00 2001 From: YunHorn Technology Date: Wed, 28 Aug 2024 12:39:55 +0800 Subject: [PATCH 4/4] add i2c drivers, MCU/BOARD NAME changed to YUNHORN-STS-WLE5CC --- Core/Inc/stm32wlxx_hal_conf.h | 2 +- Core/Src/i2c.c | 1 + STM32CubeIDE/.cproject | 12 ++++++------ 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Core/Inc/stm32wlxx_hal_conf.h b/Core/Inc/stm32wlxx_hal_conf.h index 60fd3b2..b06c984 100644 --- a/Core/Inc/stm32wlxx_hal_conf.h +++ b/Core/Inc/stm32wlxx_hal_conf.h @@ -41,7 +41,7 @@ /*#define HAL_DAC_MODULE_ENABLED */ /*#define HAL_GTZC_MODULE_ENABLED */ /*#define HAL_HSEM_MODULE_ENABLED */ -/*#define HAL_I2C_MODULE_ENABLED */ +#define HAL_I2C_MODULE_ENABLED /*#define HAL_I2S_MODULE_ENABLED */ /*#define HAL_IPCC_MODULE_ENABLED */ /*#define HAL_IRDA_MODULE_ENABLED */ diff --git a/Core/Src/i2c.c b/Core/Src/i2c.c index 3ab7d85..0911d30 100644 --- a/Core/Src/i2c.c +++ b/Core/Src/i2c.c @@ -21,6 +21,7 @@ /* Includes ------------------------------------------------------------------*/ #include "i2c.h" #include "main.h" +#include "yunhorn_sts_prd_conf.h" /* USER CODE BEGIN 0 */ I2C_HandleTypeDef hi2c2; DMA_HandleTypeDef hdma_i2c2_rx; diff --git a/STM32CubeIDE/.cproject b/STM32CubeIDE/.cproject index 93edae5..468e7ec 100644 --- a/STM32CubeIDE/.cproject +++ b/STM32CubeIDE/.cproject @@ -17,11 +17,11 @@ -