Contains Ayoub's Ranging and Custom interfaces for the VL53L3CX

Committer:
charlesmn
Date:
Wed Jul 21 14:47:53 2021 +0000
Revision:
1:dae4cb24beec
Parent:
0:c1910e04fc6c
strip out commented out code

Who changed what in which revision?

UserRevisionLine numberNew contents of line
charlesmn 0:c1910e04fc6c 1 /**
charlesmn 0:c1910e04fc6c 2 ******************************************************************************
charlesmn 0:c1910e04fc6c 3 * @file 53l3a2_ranging_sensor.c
charlesmn 0:c1910e04fc6c 4 * @author IMG SW Application Team
charlesmn 0:c1910e04fc6c 5 * @brief This file includes the driver for Ranging Sensor modules mounted on
charlesmn 0:c1910e04fc6c 6 * X-NUCLEO 53L3A2 expansion board.
charlesmn 0:c1910e04fc6c 7 ******************************************************************************
charlesmn 0:c1910e04fc6c 8 * @attention
charlesmn 0:c1910e04fc6c 9 *
charlesmn 0:c1910e04fc6c 10 * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
charlesmn 0:c1910e04fc6c 11 * All rights reserved.</center></h2>
charlesmn 0:c1910e04fc6c 12 *
charlesmn 0:c1910e04fc6c 13 * This software component is licensed by ST under BSD 3-Clause license,
charlesmn 0:c1910e04fc6c 14 * the "License"; You may not use this file except in compliance with the
charlesmn 0:c1910e04fc6c 15 * License. You may obtain a copy of the License at:
charlesmn 0:c1910e04fc6c 16 * opensource.org/licenses/BSD-3-Clause
charlesmn 0:c1910e04fc6c 17 *
charlesmn 0:c1910e04fc6c 18 ******************************************************************************
charlesmn 0:c1910e04fc6c 19 */
charlesmn 0:c1910e04fc6c 20
charlesmn 0:c1910e04fc6c 21 /* Includes ------------------------------------------------------------------ */
charlesmn 0:c1910e04fc6c 22
charlesmn 0:c1910e04fc6c 23 #include "53l3a2_ranging_sensor.h"
charlesmn 0:c1910e04fc6c 24 #include "vl53lx_platform.h"
charlesmn 0:c1910e04fc6c 25 extern void wait_ms(int ms);
charlesmn 0:c1910e04fc6c 26
charlesmn 0:c1910e04fc6c 27
charlesmn 0:c1910e04fc6c 28 /* Common Error codes */
charlesmn 0:c1910e04fc6c 29 #define BSP_ERROR_NONE 0
charlesmn 0:c1910e04fc6c 30 #define BSP_ERROR_NO_INIT -1
charlesmn 0:c1910e04fc6c 31 #define BSP_ERROR_WRONG_PARAM -2
charlesmn 0:c1910e04fc6c 32 #define BSP_ERROR_BUSY -3
charlesmn 0:c1910e04fc6c 33 #define BSP_ERROR_PERIPH_FAILURE -4
charlesmn 0:c1910e04fc6c 34 #define BSP_ERROR_COMPONENT_FAILURE -5
charlesmn 0:c1910e04fc6c 35 #define BSP_ERROR_UNKNOWN_FAILURE -6
charlesmn 0:c1910e04fc6c 36 #define BSP_ERROR_UNKNOWN_COMPONENT -7
charlesmn 0:c1910e04fc6c 37 #define BSP_ERROR_BUS_FAILURE -8
charlesmn 0:c1910e04fc6c 38 #define BSP_ERROR_CLOCK_FAILURE -9
charlesmn 0:c1910e04fc6c 39 #define BSP_ERROR_MSP_FAILURE -10
charlesmn 0:c1910e04fc6c 40 #define BSP_ERROR_FEATURE_NOT_SUPPORTED -11
charlesmn 0:c1910e04fc6c 41
charlesmn 0:c1910e04fc6c 42
charlesmn 0:c1910e04fc6c 43
charlesmn 0:c1910e04fc6c 44 #define RANGING_SENSOR_INSTANCES_NBR (3U)
charlesmn 0:c1910e04fc6c 45
charlesmn 0:c1910e04fc6c 46 /** @addtogroup BSP
charlesmn 0:c1910e04fc6c 47 * @{
charlesmn 0:c1910e04fc6c 48 */
charlesmn 0:c1910e04fc6c 49
charlesmn 0:c1910e04fc6c 50 /** @addtogroup XNUCLEO_53L3A2
charlesmn 0:c1910e04fc6c 51 * @{
charlesmn 0:c1910e04fc6c 52 */
charlesmn 0:c1910e04fc6c 53
charlesmn 0:c1910e04fc6c 54 /** @addtogroup XNUCLEO_53L3A2_RANGING_SENSOR
charlesmn 0:c1910e04fc6c 55 * @{
charlesmn 0:c1910e04fc6c 56 */
charlesmn 0:c1910e04fc6c 57
charlesmn 0:c1910e04fc6c 58 /** @addtogroup XNUCLEO_53L3A2_RANGING_SENSOR_Exported_Variables
charlesmn 0:c1910e04fc6c 59 * @{
charlesmn 0:c1910e04fc6c 60 */
charlesmn 0:c1910e04fc6c 61 void *VL53L3A2_RANGING_SENSOR_CompObj[RANGING_SENSOR_INSTANCES_NBR] = {0};
charlesmn 0:c1910e04fc6c 62 /**
charlesmn 0:c1910e04fc6c 63 * @}
charlesmn 0:c1910e04fc6c 64 */
charlesmn 0:c1910e04fc6c 65
charlesmn 0:c1910e04fc6c 66 /** @defgroup XNUCLEO_53L3A2_RANGING_SENSOR_Private_Variables Private Variables
charlesmn 0:c1910e04fc6c 67 * @{
charlesmn 0:c1910e04fc6c 68 */
charlesmn 0:c1910e04fc6c 69 static RANGING_SENSOR_Drv_t *VL53L3A2_RANGING_SENSOR_Drv = NULL;
charlesmn 0:c1910e04fc6c 70 static RANGING_SENSOR_Capabilities_t VL53L3A2_RANGING_SENSOR_Cap;
charlesmn 0:c1910e04fc6c 71 /**
charlesmn 0:c1910e04fc6c 72 * @}
charlesmn 0:c1910e04fc6c 73 */
charlesmn 0:c1910e04fc6c 74
charlesmn 0:c1910e04fc6c 75 /** @defgroup XNUCLEO_53L3A2_RANGING_SENSOR_Private_Functions_Prototypes Private Functions Prototypes
charlesmn 0:c1910e04fc6c 76 * @{
charlesmn 0:c1910e04fc6c 77 */
charlesmn 0:c1910e04fc6c 78 static int32_t VL53L3CX_Probe(uint32_t Instance);
charlesmn 0:c1910e04fc6c 79 /**
charlesmn 0:c1910e04fc6c 80 * @}
charlesmn 0:c1910e04fc6c 81 */
charlesmn 0:c1910e04fc6c 82
charlesmn 0:c1910e04fc6c 83 /**
charlesmn 0:c1910e04fc6c 84 * @brief Initialize the ranging sensor.
charlesmn 0:c1910e04fc6c 85 * @param Instance Ranging sensor instance.
charlesmn 0:c1910e04fc6c 86 * @retval BSP status
charlesmn 0:c1910e04fc6c 87 */
charlesmn 0:c1910e04fc6c 88 int32_t VL53L3A2_RANGING_SENSOR_Init(uint32_t Instance)
charlesmn 0:c1910e04fc6c 89 {
charlesmn 0:c1910e04fc6c 90 int32_t ret;
charlesmn 0:c1910e04fc6c 91 printf("VL53L3A2_RANGING_SENSOR_Init start \n");
charlesmn 0:c1910e04fc6c 92
charlesmn 0:c1910e04fc6c 93 if (Instance >= RANGING_SENSOR_INSTANCES_NBR)
charlesmn 0:c1910e04fc6c 94 {
charlesmn 0:c1910e04fc6c 95 ret = BSP_ERROR_WRONG_PARAM;
charlesmn 0:c1910e04fc6c 96 }
charlesmn 0:c1910e04fc6c 97 else if (VL53L3A2_Init() != 0)
charlesmn 0:c1910e04fc6c 98 {
charlesmn 0:c1910e04fc6c 99 printf("VL53L3A2_Init failed\n");
charlesmn 0:c1910e04fc6c 100 ret = BSP_ERROR_PERIPH_FAILURE;
charlesmn 0:c1910e04fc6c 101 }
charlesmn 0:c1910e04fc6c 102 else
charlesmn 0:c1910e04fc6c 103 {
charlesmn 0:c1910e04fc6c 104 wait_ms(100);
charlesmn 0:c1910e04fc6c 105 (void)VL53L3A2_RANGING_SENSOR_SetPowerMode(Instance, RANGING_SENSOR_POWERMODE_OFF);
charlesmn 0:c1910e04fc6c 106
charlesmn 0:c1910e04fc6c 107 wait_ms(100);
charlesmn 0:c1910e04fc6c 108 (void)VL53L3A2_RANGING_SENSOR_SetPowerMode(Instance, RANGING_SENSOR_POWERMODE_ON);
charlesmn 0:c1910e04fc6c 109 ;
charlesmn 0:c1910e04fc6c 110 wait_ms(100);
charlesmn 0:c1910e04fc6c 111 ret = VL53L3CX_Probe(Instance);
charlesmn 0:c1910e04fc6c 112 }
charlesmn 0:c1910e04fc6c 113 printf("VL53L3A2_RANGING_SENSOR_Init end \n");
charlesmn 0:c1910e04fc6c 114 return ret;
charlesmn 0:c1910e04fc6c 115 }
charlesmn 0:c1910e04fc6c 116
charlesmn 0:c1910e04fc6c 117 /**
charlesmn 0:c1910e04fc6c 118 * @brief De-initialize the ranging sensor.
charlesmn 0:c1910e04fc6c 119 * @param Instance Ranging sensor instance.
charlesmn 0:c1910e04fc6c 120 * @retval BSP status
charlesmn 0:c1910e04fc6c 121 */
charlesmn 0:c1910e04fc6c 122 int32_t VL53L3A2_RANGING_SENSOR_DeInit(uint32_t Instance)
charlesmn 0:c1910e04fc6c 123 {
charlesmn 0:c1910e04fc6c 124 int32_t ret;
charlesmn 0:c1910e04fc6c 125
charlesmn 0:c1910e04fc6c 126 if (Instance >= RANGING_SENSOR_INSTANCES_NBR)
charlesmn 0:c1910e04fc6c 127 {
charlesmn 0:c1910e04fc6c 128 ret = BSP_ERROR_WRONG_PARAM;
charlesmn 0:c1910e04fc6c 129 }
charlesmn 0:c1910e04fc6c 130 else if (VL53L3A2_DeInit() != 0)
charlesmn 0:c1910e04fc6c 131 {
charlesmn 0:c1910e04fc6c 132 ret = BSP_ERROR_PERIPH_FAILURE;
charlesmn 0:c1910e04fc6c 133 }
charlesmn 0:c1910e04fc6c 134 else if (VL53L3A2_RANGING_SENSOR_Drv->DeInit(VL53L3A2_RANGING_SENSOR_CompObj[Instance]) < 0)
charlesmn 0:c1910e04fc6c 135 {
charlesmn 0:c1910e04fc6c 136 ret = BSP_ERROR_COMPONENT_FAILURE;
charlesmn 0:c1910e04fc6c 137 }
charlesmn 0:c1910e04fc6c 138 else
charlesmn 0:c1910e04fc6c 139 {
charlesmn 0:c1910e04fc6c 140 ret = BSP_ERROR_NONE;
charlesmn 0:c1910e04fc6c 141 }
charlesmn 0:c1910e04fc6c 142
charlesmn 0:c1910e04fc6c 143 return ret;
charlesmn 0:c1910e04fc6c 144 }
charlesmn 0:c1910e04fc6c 145
charlesmn 0:c1910e04fc6c 146 /**
charlesmn 0:c1910e04fc6c 147 * @brief Read the ranging sensor device ID.
charlesmn 0:c1910e04fc6c 148 * @param Instance Ranging sensor instance.
charlesmn 0:c1910e04fc6c 149 * @param pId Pointer to the device ID.
charlesmn 0:c1910e04fc6c 150 * @retval BSP status
charlesmn 0:c1910e04fc6c 151 */
charlesmn 0:c1910e04fc6c 152 int32_t VL53L3A2_RANGING_SENSOR_ReadID(uint32_t Instance, uint32_t *pId)
charlesmn 0:c1910e04fc6c 153 {
charlesmn 0:c1910e04fc6c 154 int32_t ret;
charlesmn 0:c1910e04fc6c 155
charlesmn 0:c1910e04fc6c 156 if (Instance >= RANGING_SENSOR_INSTANCES_NBR)
charlesmn 0:c1910e04fc6c 157 {
charlesmn 0:c1910e04fc6c 158 ret = BSP_ERROR_WRONG_PARAM;
charlesmn 0:c1910e04fc6c 159 }
charlesmn 0:c1910e04fc6c 160 else if (VL53L3A2_RANGING_SENSOR_Drv->ReadID(VL53L3A2_RANGING_SENSOR_CompObj[Instance], pId) < 0)
charlesmn 0:c1910e04fc6c 161 {
charlesmn 0:c1910e04fc6c 162 ret = BSP_ERROR_COMPONENT_FAILURE;
charlesmn 0:c1910e04fc6c 163 }
charlesmn 0:c1910e04fc6c 164 else
charlesmn 0:c1910e04fc6c 165 {
charlesmn 0:c1910e04fc6c 166 ret = BSP_ERROR_NONE;
charlesmn 0:c1910e04fc6c 167 }
charlesmn 0:c1910e04fc6c 168
charlesmn 0:c1910e04fc6c 169 return ret;
charlesmn 0:c1910e04fc6c 170 }
charlesmn 0:c1910e04fc6c 171
charlesmn 0:c1910e04fc6c 172 /**
charlesmn 0:c1910e04fc6c 173 * @brief Get the ranging sensor capabilities.
charlesmn 0:c1910e04fc6c 174 * @param Instance Ranging sensor instance.
charlesmn 0:c1910e04fc6c 175 * @param pCapabilities Pointer to the ranging sensor capabilities.
charlesmn 0:c1910e04fc6c 176 * @note This function should be called after the init.
charlesmn 0:c1910e04fc6c 177 * @retval BSP status
charlesmn 0:c1910e04fc6c 178 */
charlesmn 0:c1910e04fc6c 179 int32_t VL53L3A2_RANGING_SENSOR_GetCapabilities(uint32_t Instance, RANGING_SENSOR_Capabilities_t *pCapabilities)
charlesmn 0:c1910e04fc6c 180 {
charlesmn 0:c1910e04fc6c 181 int32_t ret;
charlesmn 0:c1910e04fc6c 182
charlesmn 0:c1910e04fc6c 183 if (Instance >= RANGING_SENSOR_INSTANCES_NBR)
charlesmn 0:c1910e04fc6c 184 {
charlesmn 0:c1910e04fc6c 185 ret = BSP_ERROR_WRONG_PARAM;
charlesmn 0:c1910e04fc6c 186 }
charlesmn 0:c1910e04fc6c 187 else if (VL53L3A2_RANGING_SENSOR_Drv->GetCapabilities(VL53L3A2_RANGING_SENSOR_CompObj[Instance], pCapabilities) < 0)
charlesmn 0:c1910e04fc6c 188 {
charlesmn 0:c1910e04fc6c 189 ret = BSP_ERROR_COMPONENT_FAILURE;
charlesmn 0:c1910e04fc6c 190 }
charlesmn 0:c1910e04fc6c 191 else
charlesmn 0:c1910e04fc6c 192 {
charlesmn 0:c1910e04fc6c 193 ret = BSP_ERROR_NONE;
charlesmn 0:c1910e04fc6c 194 }
charlesmn 0:c1910e04fc6c 195
charlesmn 0:c1910e04fc6c 196 return ret;
charlesmn 0:c1910e04fc6c 197 }
charlesmn 0:c1910e04fc6c 198
charlesmn 0:c1910e04fc6c 199 /**
charlesmn 0:c1910e04fc6c 200 * @brief Set the ranging configuration profile.
charlesmn 0:c1910e04fc6c 201 * @param Instance Ranging sensor instance.
charlesmn 0:c1910e04fc6c 202 * @param pConfig Pointer to the new configuration profile to be applied.
charlesmn 0:c1910e04fc6c 203 * @retval BSP status
charlesmn 0:c1910e04fc6c 204 */
charlesmn 0:c1910e04fc6c 205 int32_t VL53L3A2_RANGING_SENSOR_ConfigProfile(uint32_t Instance, RANGING_SENSOR_ProfileConfig_t *pConfig)
charlesmn 0:c1910e04fc6c 206 {
charlesmn 0:c1910e04fc6c 207 int32_t ret;
charlesmn 0:c1910e04fc6c 208
charlesmn 0:c1910e04fc6c 209 if (Instance >= RANGING_SENSOR_INSTANCES_NBR)
charlesmn 0:c1910e04fc6c 210 {
charlesmn 0:c1910e04fc6c 211 ret = BSP_ERROR_WRONG_PARAM;
charlesmn 0:c1910e04fc6c 212 }
charlesmn 0:c1910e04fc6c 213 else if (VL53L3A2_RANGING_SENSOR_Drv->ConfigProfile(VL53L3A2_RANGING_SENSOR_CompObj[Instance], pConfig) < 0)
charlesmn 0:c1910e04fc6c 214 {
charlesmn 0:c1910e04fc6c 215 ret = BSP_ERROR_COMPONENT_FAILURE;
charlesmn 0:c1910e04fc6c 216 }
charlesmn 0:c1910e04fc6c 217 else
charlesmn 0:c1910e04fc6c 218 {
charlesmn 0:c1910e04fc6c 219 ret = BSP_ERROR_NONE;
charlesmn 0:c1910e04fc6c 220 }
charlesmn 0:c1910e04fc6c 221
charlesmn 0:c1910e04fc6c 222 return ret;
charlesmn 0:c1910e04fc6c 223 }
charlesmn 0:c1910e04fc6c 224
charlesmn 0:c1910e04fc6c 225 /**
charlesmn 0:c1910e04fc6c 226 * @brief Configure the Region of Interest of the ranging sensor.
charlesmn 0:c1910e04fc6c 227 * @param Instance Ranging sensor instance.
charlesmn 0:c1910e04fc6c 228 * @param pConfig Pointer to the ROI configuration struct.
charlesmn 0:c1910e04fc6c 229 * @retval BSP status
charlesmn 0:c1910e04fc6c 230 */
charlesmn 0:c1910e04fc6c 231 int32_t VL53L3A2_RANGING_SENSOR_ConfigROI(uint32_t Instance, RANGING_SENSOR_ROIConfig_t *pConfig)
charlesmn 0:c1910e04fc6c 232 {
charlesmn 0:c1910e04fc6c 233 int32_t ret;
charlesmn 0:c1910e04fc6c 234
charlesmn 0:c1910e04fc6c 235 if (Instance >= RANGING_SENSOR_INSTANCES_NBR)
charlesmn 0:c1910e04fc6c 236 {
charlesmn 0:c1910e04fc6c 237 ret = BSP_ERROR_WRONG_PARAM;
charlesmn 0:c1910e04fc6c 238 }
charlesmn 0:c1910e04fc6c 239 else if (VL53L3A2_RANGING_SENSOR_Cap.CustomROI == 0U)
charlesmn 0:c1910e04fc6c 240 {
charlesmn 0:c1910e04fc6c 241 ret = BSP_ERROR_FEATURE_NOT_SUPPORTED;
charlesmn 0:c1910e04fc6c 242 }
charlesmn 0:c1910e04fc6c 243 else if (VL53L3A2_RANGING_SENSOR_Drv->ConfigROI(VL53L3A2_RANGING_SENSOR_CompObj[Instance], pConfig) < 0)
charlesmn 0:c1910e04fc6c 244 {
charlesmn 0:c1910e04fc6c 245 ret = BSP_ERROR_COMPONENT_FAILURE;
charlesmn 0:c1910e04fc6c 246 }
charlesmn 0:c1910e04fc6c 247 else
charlesmn 0:c1910e04fc6c 248 {
charlesmn 0:c1910e04fc6c 249 ret = BSP_ERROR_NONE;
charlesmn 0:c1910e04fc6c 250 }
charlesmn 0:c1910e04fc6c 251
charlesmn 0:c1910e04fc6c 252 return ret;
charlesmn 0:c1910e04fc6c 253 }
charlesmn 0:c1910e04fc6c 254
charlesmn 0:c1910e04fc6c 255 /**
charlesmn 0:c1910e04fc6c 256 * @brief Configure the IT event generation parameters.
charlesmn 0:c1910e04fc6c 257 * @param Instance Ranging sensor instance.
charlesmn 0:c1910e04fc6c 258 * @param pConfig Pointer to the IT configuration struct.
charlesmn 0:c1910e04fc6c 259 * @note The threshold modes can be used only if supported by the device (check the capabilities).
charlesmn 0:c1910e04fc6c 260 * @retval BSP status
charlesmn 0:c1910e04fc6c 261 */
charlesmn 0:c1910e04fc6c 262 int32_t VL53L3A2_RANGING_SENSOR_ConfigIT(uint32_t Instance, RANGING_SENSOR_ITConfig_t *pConfig)
charlesmn 0:c1910e04fc6c 263 {
charlesmn 0:c1910e04fc6c 264 int32_t ret;
charlesmn 0:c1910e04fc6c 265
charlesmn 0:c1910e04fc6c 266 if (Instance >= RANGING_SENSOR_INSTANCES_NBR)
charlesmn 0:c1910e04fc6c 267 {
charlesmn 0:c1910e04fc6c 268 ret = BSP_ERROR_WRONG_PARAM;
charlesmn 0:c1910e04fc6c 269 }
charlesmn 0:c1910e04fc6c 270 else if (VL53L3A2_RANGING_SENSOR_Drv->ConfigIT(VL53L3A2_RANGING_SENSOR_CompObj[Instance], pConfig) < 0)
charlesmn 0:c1910e04fc6c 271 {
charlesmn 0:c1910e04fc6c 272 ret = BSP_ERROR_COMPONENT_FAILURE;
charlesmn 0:c1910e04fc6c 273 }
charlesmn 0:c1910e04fc6c 274 else
charlesmn 0:c1910e04fc6c 275 {
charlesmn 0:c1910e04fc6c 276 ret = BSP_ERROR_NONE;
charlesmn 0:c1910e04fc6c 277 }
charlesmn 0:c1910e04fc6c 278
charlesmn 0:c1910e04fc6c 279 return ret;
charlesmn 0:c1910e04fc6c 280 }
charlesmn 0:c1910e04fc6c 281
charlesmn 0:c1910e04fc6c 282 /**
charlesmn 0:c1910e04fc6c 283 * @brief Get the last distance measurement information.
charlesmn 0:c1910e04fc6c 284 * @param Instance Ranging sensor instance.
charlesmn 0:c1910e04fc6c 285 * @param pResult Pointer to the result struct.
charlesmn 0:c1910e04fc6c 286 * @retval BSP status
charlesmn 0:c1910e04fc6c 287 */
charlesmn 0:c1910e04fc6c 288 int32_t VL53L3A2_RANGING_SENSOR_GetDistance(uint32_t Instance, RANGING_SENSOR_Result_t *pResult)
charlesmn 0:c1910e04fc6c 289 {
charlesmn 0:c1910e04fc6c 290 int32_t ret;
charlesmn 0:c1910e04fc6c 291
charlesmn 0:c1910e04fc6c 292 if (Instance >= RANGING_SENSOR_INSTANCES_NBR)
charlesmn 0:c1910e04fc6c 293 {
charlesmn 0:c1910e04fc6c 294 ret = BSP_ERROR_WRONG_PARAM;
charlesmn 0:c1910e04fc6c 295 }
charlesmn 0:c1910e04fc6c 296 else if (VL53L3A2_RANGING_SENSOR_Drv->GetDistance(VL53L3A2_RANGING_SENSOR_CompObj[Instance], pResult) < 0)
charlesmn 0:c1910e04fc6c 297 {
charlesmn 0:c1910e04fc6c 298 ret = BSP_ERROR_COMPONENT_FAILURE;
charlesmn 0:c1910e04fc6c 299 }
charlesmn 0:c1910e04fc6c 300 else
charlesmn 0:c1910e04fc6c 301 {
charlesmn 0:c1910e04fc6c 302 ret = BSP_ERROR_NONE;
charlesmn 0:c1910e04fc6c 303 }
charlesmn 0:c1910e04fc6c 304
charlesmn 0:c1910e04fc6c 305 return ret;
charlesmn 0:c1910e04fc6c 306 }
charlesmn 0:c1910e04fc6c 307
charlesmn 0:c1910e04fc6c 308 /**
charlesmn 0:c1910e04fc6c 309 * @brief Start ranging.
charlesmn 0:c1910e04fc6c 310 * @param Instance Ranging sensor instance.
charlesmn 0:c1910e04fc6c 311 * @param Mode The desired RANGING_SENSOR_Mode_t
charlesmn 0:c1910e04fc6c 312 * @retval BSP status
charlesmn 0:c1910e04fc6c 313 */
charlesmn 0:c1910e04fc6c 314 int32_t VL53L3A2_RANGING_SENSOR_Start(uint32_t Instance, uint32_t Mode)
charlesmn 0:c1910e04fc6c 315 {
charlesmn 0:c1910e04fc6c 316 int32_t ret;
charlesmn 0:c1910e04fc6c 317
charlesmn 0:c1910e04fc6c 318 if (Instance >= RANGING_SENSOR_INSTANCES_NBR)
charlesmn 0:c1910e04fc6c 319 {
charlesmn 0:c1910e04fc6c 320 ret = BSP_ERROR_WRONG_PARAM;
charlesmn 0:c1910e04fc6c 321 }
charlesmn 0:c1910e04fc6c 322 else if (VL53L3A2_RANGING_SENSOR_Drv->Start(VL53L3A2_RANGING_SENSOR_CompObj[Instance], Mode) < 0)
charlesmn 0:c1910e04fc6c 323 {
charlesmn 0:c1910e04fc6c 324 ret = BSP_ERROR_COMPONENT_FAILURE;
charlesmn 0:c1910e04fc6c 325 }
charlesmn 0:c1910e04fc6c 326 else
charlesmn 0:c1910e04fc6c 327 {
charlesmn 0:c1910e04fc6c 328 ret = BSP_ERROR_NONE;
charlesmn 0:c1910e04fc6c 329 }
charlesmn 0:c1910e04fc6c 330
charlesmn 0:c1910e04fc6c 331 return ret;
charlesmn 0:c1910e04fc6c 332 }
charlesmn 0:c1910e04fc6c 333
charlesmn 0:c1910e04fc6c 334 /**
charlesmn 0:c1910e04fc6c 335 * @brief Stop ranging.
charlesmn 0:c1910e04fc6c 336 * @param Instance Ranging sensor instance.
charlesmn 0:c1910e04fc6c 337 * @retval BSP status
charlesmn 0:c1910e04fc6c 338 */
charlesmn 0:c1910e04fc6c 339 int32_t VL53L3A2_RANGING_SENSOR_Stop(uint32_t Instance)
charlesmn 0:c1910e04fc6c 340 {
charlesmn 0:c1910e04fc6c 341 int32_t ret;
charlesmn 0:c1910e04fc6c 342
charlesmn 0:c1910e04fc6c 343 if (Instance >= RANGING_SENSOR_INSTANCES_NBR)
charlesmn 0:c1910e04fc6c 344 {
charlesmn 0:c1910e04fc6c 345 ret = BSP_ERROR_WRONG_PARAM;
charlesmn 0:c1910e04fc6c 346 }
charlesmn 0:c1910e04fc6c 347 else if (VL53L3A2_RANGING_SENSOR_Drv->Stop(VL53L3A2_RANGING_SENSOR_CompObj[Instance]) < 0)
charlesmn 0:c1910e04fc6c 348 {
charlesmn 0:c1910e04fc6c 349 ret = BSP_ERROR_COMPONENT_FAILURE;
charlesmn 0:c1910e04fc6c 350 }
charlesmn 0:c1910e04fc6c 351 else
charlesmn 0:c1910e04fc6c 352 {
charlesmn 0:c1910e04fc6c 353 ret = BSP_ERROR_NONE;
charlesmn 0:c1910e04fc6c 354 }
charlesmn 0:c1910e04fc6c 355
charlesmn 0:c1910e04fc6c 356 return ret;
charlesmn 0:c1910e04fc6c 357 }
charlesmn 0:c1910e04fc6c 358
charlesmn 0:c1910e04fc6c 359 /**
charlesmn 0:c1910e04fc6c 360 * @brief Set the I2C address of the device.
charlesmn 0:c1910e04fc6c 361 * @param Instance Ranging sensor instance.
charlesmn 0:c1910e04fc6c 362 * @param Address New I2C address.
charlesmn 0:c1910e04fc6c 363 * @retval BSP status
charlesmn 0:c1910e04fc6c 364 */
charlesmn 0:c1910e04fc6c 365 int32_t VL53L3A2_RANGING_SENSOR_SetAddress(uint32_t Instance, uint32_t Address)
charlesmn 0:c1910e04fc6c 366 {
charlesmn 0:c1910e04fc6c 367 int32_t ret;
charlesmn 0:c1910e04fc6c 368
charlesmn 0:c1910e04fc6c 369 if (Instance >= RANGING_SENSOR_INSTANCES_NBR)
charlesmn 0:c1910e04fc6c 370 {
charlesmn 0:c1910e04fc6c 371 ret = BSP_ERROR_WRONG_PARAM;
charlesmn 0:c1910e04fc6c 372 }
charlesmn 0:c1910e04fc6c 373 else if (VL53L3A2_RANGING_SENSOR_Drv->SetAddress(VL53L3A2_RANGING_SENSOR_CompObj[Instance], Address) < 0)
charlesmn 0:c1910e04fc6c 374 {
charlesmn 0:c1910e04fc6c 375 ret = BSP_ERROR_COMPONENT_FAILURE;
charlesmn 0:c1910e04fc6c 376 }
charlesmn 0:c1910e04fc6c 377 else
charlesmn 0:c1910e04fc6c 378 {
charlesmn 0:c1910e04fc6c 379 ret = BSP_ERROR_NONE;
charlesmn 0:c1910e04fc6c 380 }
charlesmn 0:c1910e04fc6c 381
charlesmn 0:c1910e04fc6c 382 return ret;
charlesmn 0:c1910e04fc6c 383 }
charlesmn 0:c1910e04fc6c 384
charlesmn 0:c1910e04fc6c 385 /**
charlesmn 0:c1910e04fc6c 386 * @brief Get the I2C address of the device.
charlesmn 0:c1910e04fc6c 387 * @param Instance Ranging sensor instance.
charlesmn 0:c1910e04fc6c 388 * @param pAddress Pointer to the current I2C address.
charlesmn 0:c1910e04fc6c 389 * @retval BSP status
charlesmn 0:c1910e04fc6c 390 */
charlesmn 0:c1910e04fc6c 391 int32_t VL53L3A2_RANGING_SENSOR_GetAddress(uint32_t Instance, uint32_t *pAddress)
charlesmn 0:c1910e04fc6c 392 {
charlesmn 0:c1910e04fc6c 393 int32_t ret;
charlesmn 0:c1910e04fc6c 394
charlesmn 0:c1910e04fc6c 395 if (Instance >= RANGING_SENSOR_INSTANCES_NBR)
charlesmn 0:c1910e04fc6c 396 {
charlesmn 0:c1910e04fc6c 397 ret = BSP_ERROR_WRONG_PARAM;
charlesmn 0:c1910e04fc6c 398 }
charlesmn 0:c1910e04fc6c 399 else if (VL53L3A2_RANGING_SENSOR_Drv->GetAddress(VL53L3A2_RANGING_SENSOR_CompObj[Instance], pAddress) < 0)
charlesmn 0:c1910e04fc6c 400 {
charlesmn 0:c1910e04fc6c 401 ret = BSP_ERROR_COMPONENT_FAILURE;
charlesmn 0:c1910e04fc6c 402 }
charlesmn 0:c1910e04fc6c 403 else
charlesmn 0:c1910e04fc6c 404 {
charlesmn 0:c1910e04fc6c 405 ret = BSP_ERROR_NONE;
charlesmn 0:c1910e04fc6c 406 }
charlesmn 0:c1910e04fc6c 407
charlesmn 0:c1910e04fc6c 408 return ret;
charlesmn 0:c1910e04fc6c 409 }
charlesmn 0:c1910e04fc6c 410
charlesmn 0:c1910e04fc6c 411 /**
charlesmn 0:c1910e04fc6c 412 * @brief Set the power mode.
charlesmn 0:c1910e04fc6c 413 * @param Instance Ranging sensor instance.
charlesmn 0:c1910e04fc6c 414 * @param PowerMode New power mode to be entered.
charlesmn 0:c1910e04fc6c 415 * @retval BSP status
charlesmn 0:c1910e04fc6c 416 */
charlesmn 0:c1910e04fc6c 417 int32_t VL53L3A2_RANGING_SENSOR_SetPowerMode(uint32_t Instance, uint32_t PowerMode)
charlesmn 0:c1910e04fc6c 418 {
charlesmn 0:c1910e04fc6c 419 int32_t ret;
charlesmn 0:c1910e04fc6c 420
charlesmn 0:c1910e04fc6c 421 if (Instance >= RANGING_SENSOR_INSTANCES_NBR)
charlesmn 0:c1910e04fc6c 422 {
charlesmn 0:c1910e04fc6c 423 ret = BSP_ERROR_WRONG_PARAM;
charlesmn 0:c1910e04fc6c 424 }
charlesmn 0:c1910e04fc6c 425 else if (PowerMode == RANGING_SENSOR_POWERMODE_ON)
charlesmn 0:c1910e04fc6c 426 {
charlesmn 0:c1910e04fc6c 427 if (VL53L3A2_ResetId((uint8_t)Instance, 1) < 0)
charlesmn 0:c1910e04fc6c 428 {
charlesmn 0:c1910e04fc6c 429 ret = BSP_ERROR_PERIPH_FAILURE;
charlesmn 0:c1910e04fc6c 430 }
charlesmn 0:c1910e04fc6c 431 else
charlesmn 0:c1910e04fc6c 432 {
charlesmn 0:c1910e04fc6c 433 // HAL_Delay(2);
charlesmn 0:c1910e04fc6c 434 wait_ms(100);
charlesmn 0:c1910e04fc6c 435 ret = BSP_ERROR_NONE;
charlesmn 0:c1910e04fc6c 436 }
charlesmn 0:c1910e04fc6c 437 }
charlesmn 0:c1910e04fc6c 438 else if (PowerMode == RANGING_SENSOR_POWERMODE_OFF)
charlesmn 0:c1910e04fc6c 439 {
charlesmn 0:c1910e04fc6c 440 if (VL53L3A2_ResetId((uint8_t)Instance, 0) < 0)
charlesmn 0:c1910e04fc6c 441 {
charlesmn 0:c1910e04fc6c 442 ret = BSP_ERROR_PERIPH_FAILURE;
charlesmn 0:c1910e04fc6c 443 }
charlesmn 0:c1910e04fc6c 444 else
charlesmn 0:c1910e04fc6c 445 {
charlesmn 0:c1910e04fc6c 446 // HAL_Delay(2);
charlesmn 0:c1910e04fc6c 447 wait_ms(100);
charlesmn 0:c1910e04fc6c 448 ret = BSP_ERROR_NONE;
charlesmn 0:c1910e04fc6c 449 }
charlesmn 0:c1910e04fc6c 450 }
charlesmn 0:c1910e04fc6c 451 else
charlesmn 0:c1910e04fc6c 452 {
charlesmn 0:c1910e04fc6c 453 ret = BSP_ERROR_WRONG_PARAM;
charlesmn 0:c1910e04fc6c 454 }
charlesmn 0:c1910e04fc6c 455
charlesmn 0:c1910e04fc6c 456 return ret;
charlesmn 0:c1910e04fc6c 457 }
charlesmn 0:c1910e04fc6c 458
charlesmn 0:c1910e04fc6c 459 /**
charlesmn 0:c1910e04fc6c 460 * @brief Set the power mode.
charlesmn 0:c1910e04fc6c 461 * @param Instance Ranging sensor instance.
charlesmn 0:c1910e04fc6c 462 * @param pPowerMode Pointer to the current power mode.
charlesmn 0:c1910e04fc6c 463 * @retval BSP status
charlesmn 0:c1910e04fc6c 464 */
charlesmn 0:c1910e04fc6c 465 int32_t VL53L3A2_RANGING_SENSOR_GetPowerMode(uint32_t Instance, uint32_t *pPowerMode)
charlesmn 0:c1910e04fc6c 466 {
charlesmn 0:c1910e04fc6c 467 int32_t ret;
charlesmn 0:c1910e04fc6c 468
charlesmn 0:c1910e04fc6c 469 if (Instance >= RANGING_SENSOR_INSTANCES_NBR)
charlesmn 0:c1910e04fc6c 470 {
charlesmn 0:c1910e04fc6c 471 ret = BSP_ERROR_WRONG_PARAM;
charlesmn 0:c1910e04fc6c 472 }
charlesmn 0:c1910e04fc6c 473 else if (VL53L3A2_RANGING_SENSOR_Drv->GetPowerMode(VL53L3A2_RANGING_SENSOR_CompObj[Instance], pPowerMode) < 0)
charlesmn 0:c1910e04fc6c 474 {
charlesmn 0:c1910e04fc6c 475 ret = BSP_ERROR_COMPONENT_FAILURE;
charlesmn 0:c1910e04fc6c 476 }
charlesmn 0:c1910e04fc6c 477 else
charlesmn 0:c1910e04fc6c 478 {
charlesmn 0:c1910e04fc6c 479 ret = BSP_ERROR_NONE;
charlesmn 0:c1910e04fc6c 480 }
charlesmn 0:c1910e04fc6c 481
charlesmn 0:c1910e04fc6c 482 return ret;
charlesmn 0:c1910e04fc6c 483 }
charlesmn 0:c1910e04fc6c 484
charlesmn 0:c1910e04fc6c 485 /**
charlesmn 0:c1910e04fc6c 486 * @brief Perform an offset calibration.
charlesmn 0:c1910e04fc6c 487 * @param Instance Ranging sensor instance.
charlesmn 0:c1910e04fc6c 488 * @param CalDistance Calibration distance in mm.
charlesmn 0:c1910e04fc6c 489 * @retval BSP status
charlesmn 0:c1910e04fc6c 490 */
charlesmn 0:c1910e04fc6c 491 int32_t VL53L3A2_RANGING_SENSOR_OffsetCalibration(uint32_t Instance, uint32_t CalDistance)
charlesmn 0:c1910e04fc6c 492 {
charlesmn 0:c1910e04fc6c 493 int32_t ret;
charlesmn 0:c1910e04fc6c 494
charlesmn 0:c1910e04fc6c 495 if (Instance >= RANGING_SENSOR_INSTANCES_NBR)
charlesmn 0:c1910e04fc6c 496 {
charlesmn 0:c1910e04fc6c 497 ret = BSP_ERROR_WRONG_PARAM;
charlesmn 0:c1910e04fc6c 498 }
charlesmn 0:c1910e04fc6c 499 else if (VL53L3CX_OffsetCalibration(VL53L3A2_RANGING_SENSOR_CompObj[Instance], CalDistance) < 0)
charlesmn 0:c1910e04fc6c 500 {
charlesmn 0:c1910e04fc6c 501 ret = BSP_ERROR_COMPONENT_FAILURE;
charlesmn 0:c1910e04fc6c 502 }
charlesmn 0:c1910e04fc6c 503 else
charlesmn 0:c1910e04fc6c 504 {
charlesmn 0:c1910e04fc6c 505 ret = BSP_ERROR_NONE;
charlesmn 0:c1910e04fc6c 506 }
charlesmn 0:c1910e04fc6c 507
charlesmn 0:c1910e04fc6c 508 return ret;
charlesmn 0:c1910e04fc6c 509 }
charlesmn 0:c1910e04fc6c 510
charlesmn 0:c1910e04fc6c 511 /**
charlesmn 0:c1910e04fc6c 512 * @brief Perform a xtalk calibration.
charlesmn 0:c1910e04fc6c 513 * @param Instance Ranging sensor instance.
charlesmn 0:c1910e04fc6c 514 * @retval BSP status
charlesmn 0:c1910e04fc6c 515 */
charlesmn 0:c1910e04fc6c 516 int32_t VL53L3A2_RANGING_SENSOR_XTalkCalibration(uint32_t Instance)
charlesmn 0:c1910e04fc6c 517 {
charlesmn 0:c1910e04fc6c 518 int32_t ret;
charlesmn 0:c1910e04fc6c 519
charlesmn 0:c1910e04fc6c 520 if (Instance >= RANGING_SENSOR_INSTANCES_NBR)
charlesmn 0:c1910e04fc6c 521 {
charlesmn 0:c1910e04fc6c 522 ret = BSP_ERROR_WRONG_PARAM;
charlesmn 0:c1910e04fc6c 523 }
charlesmn 0:c1910e04fc6c 524 else if (VL53L3CX_XTalkCalibration(VL53L3A2_RANGING_SENSOR_CompObj[Instance]) < 0)
charlesmn 0:c1910e04fc6c 525 {
charlesmn 0:c1910e04fc6c 526 ret = BSP_ERROR_COMPONENT_FAILURE;
charlesmn 0:c1910e04fc6c 527 }
charlesmn 0:c1910e04fc6c 528 else
charlesmn 0:c1910e04fc6c 529 {
charlesmn 0:c1910e04fc6c 530 ret = BSP_ERROR_NONE;
charlesmn 0:c1910e04fc6c 531 }
charlesmn 0:c1910e04fc6c 532
charlesmn 0:c1910e04fc6c 533 return ret;
charlesmn 0:c1910e04fc6c 534 }
charlesmn 0:c1910e04fc6c 535
charlesmn 0:c1910e04fc6c 536 /** @defgroup XNUCLEO_53L3A2_RANGING_SENSOR_Private_Functions Private Functions
charlesmn 0:c1910e04fc6c 537 * @{
charlesmn 0:c1910e04fc6c 538 */
charlesmn 0:c1910e04fc6c 539
charlesmn 0:c1910e04fc6c 540 /**
charlesmn 0:c1910e04fc6c 541 * @brief Register Bus IOs if component ID is OK.
charlesmn 0:c1910e04fc6c 542 * @param Instance Ranging sensor instance.
charlesmn 0:c1910e04fc6c 543 * @retval BSP status
charlesmn 0:c1910e04fc6c 544 */
charlesmn 0:c1910e04fc6c 545 static int32_t VL53L3CX_Probe(uint32_t Instance)
charlesmn 0:c1910e04fc6c 546 {
charlesmn 0:c1910e04fc6c 547 int32_t ret;
charlesmn 0:c1910e04fc6c 548 VL53L3CX_IO_t IOCtx;
charlesmn 0:c1910e04fc6c 549 uint32_t id;
charlesmn 0:c1910e04fc6c 550 static VL53L3CX_Object_t VL53L3CXObj[RANGING_SENSOR_INSTANCES_NBR];
charlesmn 0:c1910e04fc6c 551
charlesmn 0:c1910e04fc6c 552 /* Configure the ranging sensor driver */
charlesmn 0:c1910e04fc6c 553 IOCtx.Address = RANGING_SENSOR_VL53L3CX_ADDRESS; //default address
charlesmn 0:c1910e04fc6c 554 //// IOCtx.Init = VL53L3A2_I2C_Init;
charlesmn 0:c1910e04fc6c 555 //// IOCtx.DeInit = VL53L3A2_I2C_DeInit;
charlesmn 0:c1910e04fc6c 556 //// IOCtx.WriteReg = VL53L3A2_I2C_WriteReg;
charlesmn 0:c1910e04fc6c 557 //// IOCtx.ReadReg = VL53L3A2_I2C_ReadReg;/
charlesmn 0:c1910e04fc6c 558 //// IOCtx.GetTick = VL53L3A2_GetTick;
charlesmn 0:c1910e04fc6c 559 IOCtx.GetTick = GetTickCountMs; // 1ms ticks
charlesmn 0:c1910e04fc6c 560
charlesmn 0:c1910e04fc6c 561 //printf("VL53L3CX_Probe start %d %d\n",Instance,VL53L3CXObj[Instance].IO.Address);
charlesmn 0:c1910e04fc6c 562
charlesmn 0:c1910e04fc6c 563 uint32_t i2c_addr=0x52;
charlesmn 0:c1910e04fc6c 564 VL53L3CXObj[Instance].IO.Address = i2c_addr;
charlesmn 0:c1910e04fc6c 565
charlesmn 0:c1910e04fc6c 566
charlesmn 0:c1910e04fc6c 567 if (VL53L3CX_RegisterBusIO(&(VL53L3CXObj[Instance]), &IOCtx) != VL53L3CX_OK)
charlesmn 0:c1910e04fc6c 568 {
charlesmn 0:c1910e04fc6c 569 ret = BSP_ERROR_COMPONENT_FAILURE;
charlesmn 0:c1910e04fc6c 570 }
charlesmn 0:c1910e04fc6c 571 else
charlesmn 0:c1910e04fc6c 572 if (VL53L3CX_ReadID(&(VL53L3CXObj[Instance]), &id) != VL53L3CX_OK)
charlesmn 0:c1910e04fc6c 573 {
charlesmn 0:c1910e04fc6c 574 printf("VL53L3CX_ReadID failed\n");
charlesmn 0:c1910e04fc6c 575 ret = BSP_ERROR_COMPONENT_FAILURE;
charlesmn 0:c1910e04fc6c 576 }
charlesmn 0:c1910e04fc6c 577 else
charlesmn 0:c1910e04fc6c 578 {
charlesmn 0:c1910e04fc6c 579 if (id != VL53L3CX_ID)
charlesmn 0:c1910e04fc6c 580 {
charlesmn 0:c1910e04fc6c 581 printf("VL53L3CX_ID failed\n");
charlesmn 0:c1910e04fc6c 582 ret = BSP_ERROR_UNKNOWN_COMPONENT;
charlesmn 0:c1910e04fc6c 583 }
charlesmn 0:c1910e04fc6c 584 else
charlesmn 0:c1910e04fc6c 585 {
charlesmn 0:c1910e04fc6c 586
charlesmn 0:c1910e04fc6c 587 VL53L3A2_RANGING_SENSOR_Drv = (RANGING_SENSOR_Drv_t *) &VL53L3CX_RANGING_SENSOR_Driver;
charlesmn 0:c1910e04fc6c 588 VL53L3A2_RANGING_SENSOR_CompObj[Instance] = &(VL53L3CXObj[Instance]);
charlesmn 0:c1910e04fc6c 589 if (VL53L3A2_RANGING_SENSOR_Drv->Init(VL53L3A2_RANGING_SENSOR_CompObj[Instance]) != VL53L3CX_OK)
charlesmn 0:c1910e04fc6c 590 {
charlesmn 0:c1910e04fc6c 591 printf("Init failed\n");
charlesmn 0:c1910e04fc6c 592 ret = BSP_ERROR_COMPONENT_FAILURE;
charlesmn 0:c1910e04fc6c 593 }
charlesmn 0:c1910e04fc6c 594 else if (VL53L3A2_RANGING_SENSOR_Drv->GetCapabilities(VL53L3A2_RANGING_SENSOR_CompObj[Instance], &VL53L3A2_RANGING_SENSOR_Cap) != VL53L3CX_OK)
charlesmn 0:c1910e04fc6c 595 {
charlesmn 0:c1910e04fc6c 596 printf("GetCapabilities failed\n");
charlesmn 0:c1910e04fc6c 597 ret = BSP_ERROR_COMPONENT_FAILURE;
charlesmn 0:c1910e04fc6c 598 }
charlesmn 0:c1910e04fc6c 599 else
charlesmn 0:c1910e04fc6c 600 {
charlesmn 0:c1910e04fc6c 601 ret = BSP_ERROR_NONE;
charlesmn 0:c1910e04fc6c 602 }
charlesmn 0:c1910e04fc6c 603 }
charlesmn 0:c1910e04fc6c 604
charlesmn 0:c1910e04fc6c 605 }
charlesmn 0:c1910e04fc6c 606
charlesmn 0:c1910e04fc6c 607 return ret;
charlesmn 0:c1910e04fc6c 608 }
charlesmn 0:c1910e04fc6c 609
charlesmn 0:c1910e04fc6c 610 /**
charlesmn 0:c1910e04fc6c 611 * @}
charlesmn 0:c1910e04fc6c 612 */
charlesmn 0:c1910e04fc6c 613
charlesmn 0:c1910e04fc6c 614 /**
charlesmn 0:c1910e04fc6c 615 * @}
charlesmn 0:c1910e04fc6c 616 */
charlesmn 0:c1910e04fc6c 617
charlesmn 0:c1910e04fc6c 618 /**
charlesmn 0:c1910e04fc6c 619 * @}
charlesmn 0:c1910e04fc6c 620 */
charlesmn 0:c1910e04fc6c 621
charlesmn 0:c1910e04fc6c 622 /**
charlesmn 0:c1910e04fc6c 623 * @}
charlesmn 0:c1910e04fc6c 624 */
charlesmn 0:c1910e04fc6c 625
charlesmn 0:c1910e04fc6c 626 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
charlesmn 0:c1910e04fc6c 627