Просмотр исходного кода

Добавил библиотеки для шилда.

TelenkovDmitry 9 месяцев назад
Родитель
Сommit
77c00223ff

+ 64 - 0
modules/bsp/stm32xxx_hal.h

@@ -0,0 +1,64 @@
+/**
+  ******************************************************************************
+  * @file    stm32xxx_hal.h
+  * @date    10/03/2015 18:07:07
+  * @brief   This file allows to select the right stm32 hal file
+  ******************************************************************************
+  *
+  * COPYRIGHT(c) 2015 STMicroelectronics
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32xxx_HAL_H
+#define __STM32xxx_HAL_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif 
+
+/* Includes ------------------------------------------------------------------*/
+#ifdef STM32F401xE
+#include "stm32f4xx_hal.h"
+#endif
+#ifdef STM32L053xx
+#include "stm32l0xx_hal.h"
+#endif
+#ifdef STM32L476xx
+#include "stm32l4xx_hal.h"
+#endif
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32xxx_HAL_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

+ 106 - 0
modules/bsp/vl6180x_platform.h

@@ -0,0 +1,106 @@
+/*******************************************************************************
+################################################################################
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License version 2 and only version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+#------------------------------------------------------------------------------
+#                             Imaging Division
+################################################################################
+********************************************************************************/
+
+
+/* vl6180x_platform.h STM32 Nucleo F401 single device  sample code project */
+
+#ifndef VL6180x_PLATFORM
+#define VL6180x_PLATFORM
+
+
+#include "vl6180x_def.h"
+
+
+#define VL6180x_SINGLE_DEVICE_DRIVER 	0
+#define VL6180x_RANGE_STATUS_ERRSTRING  1
+#define VL6180X_SAFE_POLLING_ENTER 		0
+#define VL6180X_LOG_ENABLE			    0
+
+
+#define VL6180x_DEV_DATA_ATTR
+#define ROMABLE_DATA
+
+
+#if VL6180X_LOG_ENABLE
+/*  dot not include non ansi here trace was a case :( */
+#ifdef TRACE
+#include "diag/trace.h"
+#define LOG_GET_TIME()  HAL_GetTick()
+#else
+/* these is nto stm32 vl6180x GNuArm eclpse build*/
+#define trace_printf(...) (void)0
+#define LOG_GET_TIME() (int)0 /* add your code here expect to be an integer native (%d) type  value  */
+#endif
+
+
+
+#define LOG_FUNCTION_START(fmt, ... ) \
+    trace_printf("beg %s start @%d\t" fmt "\n", __func__, LOG_GET_TIME(), ##__VA_ARGS__)
+
+#define LOG_FUNCTION_END(status)\
+        trace_printf("end %s @%d %d\n", __func__, LOG_GET_TIME(), (int)status)
+
+#define LOG_FUNCTION_END_FMT(status, fmt, ... )\
+        trace_printf("End %s @%d %d\t"fmt"\n" , __func__, LOG_GET_TIME(), (int)status, ##__VA_ARGS__)
+
+#define VL6180x_ErrLog(msg, ... )\
+    do{\
+        trace_printf("ERR in %s line %d\n" msg, __func__, __LINE__, ##__VA_ARGS__);\
+    }while(0)
+
+#else /* VL6180X_LOG_ENABLE no logging */
+
+	#define LOG_FUNCTION_START(...) (void)0
+	#define LOG_FUNCTION_END(...) (void)0
+	#define LOG_FUNCTION_END_FMT(...) (void)0
+    #define VL6180x_ErrLog(... ) (void)0
+#endif
+
+
+#if  VL6180x_SINGLE_DEVICE_DRIVER
+    #error "VL6180x_SINGLE_DEVICE_DRIVER must be set"
+#endif
+		
+struct MyVL6180Dev_t {
+		struct VL6180xDevData_t Data;
+		uint8_t I2cAddr;
+		uint8_t DevID;
+    
+	// misc flags for application 	
+    unsigned Present:1;
+    unsigned Ready:1;
+};
+typedef struct MyVL6180Dev_t *VL6180xDev_t;
+
+#define VL6180xDevDataGet(dev, field) (dev->Data.field)
+#define VL6180xDevDataSet(dev, field, data) (dev->Data.field)=(data)
+
+
+void VL6180x_PollDelay(VL6180xDev_t dev);
+
+void DISP_ExecLoopBody(void);
+#define VL6180x_PollDelay(dev)   DISP_ExecLoopBody();
+
+
+#endif  /* VL6180x_PLATFORM */
+
+
+

+ 62 - 0
modules/bsp/vl6180x_types.h

@@ -0,0 +1,62 @@
+/*******************************************************************************
+Copyright © 2014, 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 VL6180x_TYPES_H_
+#define VL6180x_TYPES_H_
+
+
+#include <stdint.h>
+#include <stddef.h> /* these is for NULL */
+
+#ifndef NULL
+#error "review  NULL definition or add required include "
+#endif
+
+#if !defined(STDINT_H) &&  !defined(_GCC_STDINT_H) && !defined(__STDINT_DECLS) && !defined(_STDINT) && !defined(_STDINT_H)
+
+#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
+  */
+
+typedef unsigned int uint32_t;
+typedef int int32_t;
+
+typedef unsigned short uint16_t;
+typedef short int16_t;
+
+typedef unsigned char uint8_t;
+
+typedef signed char int8_t;
+
+#endif /* _STDINT_H */
+
+#endif /* VL6180x_TYPES_H_ */

+ 666 - 0
modules/bsp/x-nucleo-6180xa1.c

@@ -0,0 +1,666 @@
+/*
+ * @file x-nucleo-6180xa1.c
+ * $Date: 2015-10-21 16:55:39 +0200 (Wed, 21 Oct 2015) $
+ * $Revision: 2560 $
+ */
+
+#include <string.h>
+
+/** Configure VL6180 pins  to Output */
+#include "stm32xxx_hal.h"
+#ifndef HAL_I2C_MODULE_ENABLED
+#define HAL_I2C_MODULE_ENABLED
+#pragma message("hal conf should enable i2c")
+#endif
+
+#include "x-nucleo-6180xa1.h"
+
+#define V1_CHIP_SWITCH_PORT GPIOA
+#define V1_CHIP_SWITCH_PIN  GPIO_PIN_7
+#define V1_CHIP_ENABLE_PORT GPIOA
+#define V1_CHIP_ENABLE_PIN  GPIO_PIN_5
+
+#define V1_IRQ_PIN          GPIO_PIN_6
+#define V2_IRQ_PIN          GPIO_PIN_0
+
+#ifdef __STM32F4xx_HAL_H 
+    #define V1_IRQ EXTI9_5_IRQn
+    #define V2_IRQ EXTI0_IRQn
+#else 
+#ifdef __STM32L4xx_HAL_H
+    #define V1_IRQ EXTI9_5_IRQn
+    #define V2_IRQ EXTI0_IRQn
+#else
+    #define V1_IRQ EXTI4_15_IRQn
+    #define V2_IRQ EXTI0_1_IRQn
+#endif
+#endif
+
+
+
+/* local private prototypes */
+static void _V1_GPIO_Init(void);
+static void _V1_Set7SegmentDP( int dp);
+static void _V1_Set7Segment(uint8_t value);
+static void _V1_DisplayOff(void);
+
+
+static void _V2_GPIO_Init(void);
+static int _V2_GetSwicth(void);
+
+
+#define EXPANDER_I2C_ADDRESS    (0x42*2)
+#define GPMR    0x10
+#define GPSR    0x12
+#define GPDR    0x14
+
+
+
+#define V2_D1       (1<<7)
+// second byte or word MSB
+#define V2_D2       (1<<8)
+#define V2_D3       (1<<9)
+#define V2_D4       (1<<10)
+#define V2_DISP_SEL (1<<11)
+#define V2_CHIPEN   (1<<12)
+#define V2_CHIPEN_B (1<<13)
+#define V2_CHIPEN_L (1<<14)
+#define V2_CHIPEN_R (1<<15)
+
+static int IsV2=0;
+I2C_HandleTypeDef *_hi2c;
+uint16_t _V2PadVal; /* gpio SR value caching to avoid reading on each new bit set */
+static int I2cExpAddr=EXPANDER_I2C_ADDRESS;
+
+static int _err=0;
+
+static void _V2_DisplayOff(void);
+static void _V2_SetChipEn( int No, int state );
+
+
+
+int XNUCLEO6180XA1_IsV2(void){
+		return IsV2; 
+}
+
+
+
+int XNUCLEO6180XA1_EXTI_CallBackHandle(uint16_t GPIO_Pin){
+    int IsVL6180XIntPin = IsV2 ?  GPIO_Pin == V2_IRQ_PIN : GPIO_Pin == V1_IRQ_PIN;
+    if( IsVL6180XIntPin){
+        XNUCLEO6180XA1_UserIntHandler();
+    }
+    return IsVL6180XIntPin;
+}
+
+void XNUCLEO6180XA1_Reset(int state){
+    if( !IsV2)
+        HAL_GPIO_WritePin(V1_CHIP_ENABLE_PORT, V1_CHIP_ENABLE_PIN , (GPIO_PinState)state);
+    else{
+        _V2_SetChipEn(0, state);
+    }
+}
+
+
+int XNUCLEO6180XA1_ResetId(int state, int id)
+{
+    int status;
+    if( IsV2 && id>=0 && id<4){
+        _V2_SetChipEn(id, state);
+        status=0;
+    }
+    else{
+    /* Error case */
+        status=-1;
+    }
+    return status;
+}
+
+int XNUCLEO6180XA1_GetSwitch(void){
+    GPIO_PinState state ;
+    if( !IsV2)
+        state = HAL_GPIO_ReadPin(V1_CHIP_SWITCH_PORT, V1_CHIP_SWITCH_PIN);
+    else{
+        state= _V2_GetSwicth() ? GPIO_PIN_SET : GPIO_PIN_RESET ;
+    }
+    return state;
+}
+
+/* public API */
+void XNUCLEO6180XA1_GPIO_Init(void) {
+//    this must be done after i2c init _V1_GPIO_Init();
+}
+
+
+
+int V2_ExpanderRd(int  index,  uint8_t *data, int n_data){
+
+    int status;
+    uint8_t RegAddr;
+    RegAddr=index;
+
+    do{
+        status=HAL_I2C_Master_Transmit(_hi2c, I2cExpAddr, &RegAddr, 1, 100);
+        if( status )
+            break;
+        status =HAL_I2C_Master_Receive(_hi2c, I2cExpAddr, data, n_data, n_data*100);
+    }while(0);
+    return status;
+}
+
+int V2_ExpanderWR( int index,  uint8_t *data, int n_data){
+
+    int status;
+    uint8_t RegAddr[0x10];
+    RegAddr[0]=index;
+    memcpy(RegAddr+1, data, n_data);
+    status=HAL_I2C_Master_Transmit(_hi2c, I2cExpAddr, RegAddr, n_data+1, 100);
+    return status;
+}
+
+
+/**
+ *
+ * @param No    0= top , 1= Left, 2=Bottom 3=Right
+ * @param state
+ */
+static void _V2_SetChipEn( int No, int state ){
+    //int mask = V2_CHIPEN << No;
+    int mask = (No==3) ? V2_CHIPEN_R : ((No==2) ? V2_CHIPEN_B : ((No==1) ? V2_CHIPEN_L : V2_CHIPEN));
+    if( state)
+        _V2PadVal|=mask ;
+    else
+        _V2PadVal&=~mask;
+
+    V2_ExpanderWR(GPSR, (uint8_t*)&_V2PadVal,2);
+}
+
+int _V2_GetSwicth(){
+    int status;
+    uint16_t Value;
+    status=V2_ExpanderRd(GPMR, (uint8_t*)&Value,2);
+
+    if(status ==0 ){
+        Value&=V2_DISP_SEL;
+    }
+    else{
+        //TODO ("VL6180x Expander rd fail");
+        _err++;
+        Value=0;
+    }
+    return Value;
+}
+
+static void _I2cFailRecover(){
+    GPIO_InitTypeDef GPIO_InitStruct;
+    int i, nRetry=0;
+
+
+    // We may get reset after in middle of an i2c access (h/w reset button use or debug load)
+    // hence some agent on bus may be in middle of a a transaction and will create issue or even prevent starting (SDA is low)
+    // 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 will end up seeing a "stop" end bus we back to an known idle i2c  bus state
+
+    // Enable I/O
+    __GPIOB_CLK_ENABLE();
+    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);
+    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_SET);
+    GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9 ;
+    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
+    GPIO_InitStruct.Pull = GPIO_PULLUP;
+    HAL_GPIO_Init(GPIOB, &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(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET);
+            HAL_Delay(1);
+            HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);
+            HAL_Delay(1);
+        }
+//        if( HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_9) == 0 ){
+//            static int RetryRecover;
+//            RetryRecover++;
+//        }
+    }while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_9) == 0 && nRetry++<7);
+
+    if( HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_9) == 0 ){
+        __GPIOA_CLK_ENABLE();
+        //We are still in bad i2c state warm user by blinking led but stay here
+        GPIO_InitStruct.Pin = GPIO_PIN_5 ;
+        GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+        GPIO_InitStruct.Pull = GPIO_NOPULL;
+        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+        do{
+            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
+            HAL_Delay(33);
+            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
+            HAL_Delay(33);
+            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
+            HAL_Delay(33);
+            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
+            HAL_Delay(33*20);
+        }while(1);
+    }
+}
+
+/**
+ * F401 valid may not work for over device
+ */
+void XNUCLEO6180XA1_I2C1_Init(I2C_HandleTypeDef *hi2c1) {
+    GPIO_InitTypeDef GPIO_InitStruct;
+    uint8_t ExpanderID[2];
+
+    int status;
+
+    _I2cFailRecover();
+    /* Peripheral clock enable */
+    __GPIOB_CLK_ENABLE();
+    __I2C1_CLK_ENABLE();
+    /**I2C1 GPIO Configuration
+     PB8     ------> I2C1_SCL
+     PB9     ------> I2C1_SDA
+     */
+    GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;
+    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
+    GPIO_InitStruct.Pull = GPIO_PULLUP;
+    GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
+    GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
+    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+
+    hi2c1->Instance = I2C1;
+#ifdef __STM32F4xx_HAL_H
+    hi2c1->Init.ClockSpeed = 400000;
+    hi2c1->Init.DutyCycle = I2C_DUTYCYCLE_2;
+#else 
+    hi2c1->Init.Timing = 0x00300F38; /* set 400KHz fast mode i2c*/
+#endif
+    hi2c1->Init.OwnAddress1 = 0;
+    hi2c1->Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
+    hi2c1->Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;
+    hi2c1->Init.OwnAddress2 = 0;
+    hi2c1->Init.GeneralCallMode = I2C_GENERALCALL_DISABLED;
+    hi2c1->Init.NoStretchMode = I2C_NOSTRETCH_DISABLED;
+    
+    HAL_I2C_Init(hi2c1);
+    
+    
+    /* try to detect v1 v2 by reading i2c expander register
+     *  if rd i2c fail assume it is a v1 shield it may be a v2 with an i2c bus hangs (happen some time)*/
+    _hi2c=hi2c1;
+    status = V2_ExpanderRd( 0, ExpanderID, 2);
+    if( status == 0 && ExpanderID[0]==0 && ExpanderID[1]==0x16){
+        IsV2=1;
+        _V2_GPIO_Init();
+    }
+    else{
+        _V1_GPIO_Init();
+    }
+}
+
+/**
+ * @brief Default  do nothing interrupt callback
+ */
+#pragma weak XNUCLEO6180XA1_UserIntHandler
+void  XNUCLEO6180XA1_UserIntHandler(void)  {
+}
+
+void XNUCLEO6180XA1_ClearInterrupt(void){
+    if( !IsV2 )
+        NVIC_ClearPendingIRQ(V1_IRQ);
+    else
+        NVIC_ClearPendingIRQ(V2_IRQ);
+}
+
+
+void XNUCLEO6180XA1_DisableInterrupt(void){
+    if( !IsV2){
+        HAL_NVIC_DisableIRQ(V1_IRQ);
+        __HAL_GPIO_EXTI_CLEAR_IT(V1_IRQ_PIN);
+        NVIC_ClearPendingIRQ(V1_IRQ);
+    }
+    else{
+        HAL_NVIC_DisableIRQ(V2_IRQ);
+        __HAL_GPIO_EXTI_CLEAR_IT(V2_IRQ_PIN);
+        NVIC_ClearPendingIRQ(V2_IRQ);
+    }
+
+}
+void XNUCLEO6180XA1_EnableInterrupt(void){
+    if( !IsV2 ){
+        __HAL_GPIO_EXTI_CLEAR_IT(V1_IRQ_PIN);
+        NVIC_ClearPendingIRQ(V1_IRQ);
+        HAL_NVIC_EnableIRQ(V1_IRQ);
+    }
+    else{
+        __HAL_GPIO_EXTI_CLEAR_IT(V2_IRQ_PIN);
+        NVIC_ClearPendingIRQ(V2_IRQ);
+        HAL_NVIC_EnableIRQ(V2_IRQ);
+    }
+
+}
+
+/**
+ * Display digit enable pad/pin LUT
+ * D1 is left most digit  (ms nibble) on the display
+ * D3 is right most digit (ls nibble) on the display
+ */
+#define PA  0
+#define PB  1
+#define PC  2
+#define MAKE_PAD(port, pin)  (((port)<<4)|pin)
+
+/* digit enable pad/pin LUT  */
+static uint8_t DisplayEn[] = {
+    MAKE_PAD( PB, 0), /* D1 0 */
+    MAKE_PAD( PA, 4), /* D2 1 */
+    MAKE_PAD( PA, 1), /* D3 2 */
+    MAKE_PAD( PA, 0), /* D4 3 */
+};
+
+/* 7 segment code to pad/pin LUT  */
+static uint8_t DisplaySeg[] = {
+        MAKE_PAD( PB, 6 ), /* 0 A  */
+        MAKE_PAD( PC, 7 ), /* 1 B  */
+        MAKE_PAD( PA, 9 ), /* 2 C  */
+        MAKE_PAD( PA, 8 ), /* 3 D  */
+        MAKE_PAD( PB, 10), /* 4 E  */
+        MAKE_PAD( PB, 4 ), /* 5 F  */
+        MAKE_PAD( PB, 5 ), /* 6 G  */
+        MAKE_PAD( PB, 3 ), /* 7 DP */
+        /* Note that PB3 these is conflicting wit jtag/SWO used for trace
+         * activating PB3 as ooutput will prevent trace to work  */
+};
+#undef MAKE_PAD
+#undef PA
+#undef PB
+#undef PC
+
+#define pad_write(pad, state)   HAL_GPIO_WritePin( (GPIO_TypeDef*)((char*)GPIOA + (pad>>4)*((char*)GPIOB-(char*)GPIOA)), 1<<(pad&0x0F), state);
+
+/*
+   --s0--
+   s    s
+   5    1
+   --s6--
+   s    s
+   4    2
+   --s3-- s7
+
+ */
+
+#define DP  (1<<7)
+#define NOT_7_NO_DP( ... ) (uint8_t) ~( __VA_ARGS__ + DP )
+#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)
+
+/* refer to http://www.twyman.org.uk/Fonts/ */
+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']=           S0+S1+S2+S5+S6, // sames as 'q'
+      ['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
+
+
+static void _V1_DisplayString(const char *str, int SegDelayMs){
+    int i;
+    const char *pc;
+    for( i=0, pc=str; i<4 && *pc!=0 ; i++, pc++){
+        _V1_Set7Segment( ascii_to_display_lut[(uint8_t)*pc]);
+        if( *(pc+1)== '.'){
+            _V1_Set7SegmentDP(1);
+            pc++;
+        }
+        /* digit on */
+        pad_write(DisplayEn[i], GPIO_PIN_RESET); /* activate led */
+        XNUCLEO6180XA1_WaitMilliSec(SegDelayMs);
+        /* digit off */
+        pad_write(DisplayEn[i], GPIO_PIN_SET); /* turn off led */
+    }
+}
+
+static  void _V2_Set7Segment( int Leds, int digit ){
+    _V2PadVal |= 0x7F; /* clear 7 seg bits */
+    _V2PadVal |= V2_D1|V2_D2|V2_D3|V2_D4; /* all segment off */
+    _V2PadVal &= ~(V2_D1<<digit);         /* digit on */
+    _V2PadVal &= ~(Leds&0x7F);
+    V2_ExpanderWR(GPSR, (uint8_t*)&_V2PadVal, 2);
+}
+
+
+static  void _V2_DisplayString(const char *str, int SegDelayMs){
+    int i;
+    const char *pc;
+
+    for( i=0, pc=str; i<4 && *pc!=0 ; i++, pc++){
+        _V2_Set7Segment( ascii_to_display_lut[(uint8_t)*pc], i);
+        if( *(pc+1)== '.'){
+            pc++;
+        }
+        XNUCLEO6180XA1_WaitMilliSec(SegDelayMs);
+        _V2_DisplayOff();
+    }
+}
+
+/**
+ * accept . on any digit
+ */
+void XNUCLEO6180XA1_DisplayString(const char *str, int SegDelayMs){
+    if( !IsV2)
+        _V1_DisplayString(str, SegDelayMs);
+    else
+        _V2_DisplayString(str, SegDelayMs);
+ }
+
+
+
+
+static void _V1_GPIO_Init(void) {
+
+    GPIO_InitTypeDef GPIO_InitStruct;
+
+    /* GPIO Ports Clock Enable */
+    __GPIOC_CLK_ENABLE();
+    __GPIOH_CLK_ENABLE();
+    __GPIOA_CLK_ENABLE();
+    __GPIOB_CLK_ENABLE();
+
+
+    /*Configure GPIO pins : PA0 PA1 PA4 PA5 PA8 PA9 */
+    GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_8 | GPIO_PIN_9;
+    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
+    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+    /*Configure GPIO pins : PA7 select  */
+    GPIO_InitStruct.Pin = GPIO_PIN_7;
+    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+
+    /*Configure GPIO pins : PA6 interrupt */
+    GPIO_InitStruct.Pin = GPIO_PIN_6;
+    GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+    /*Configure GPIO pins : PB0 PB10 PB3 PB4 PB5  PB6 */
+    GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_10 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6;
+#ifndef OS_USE_TRACE_ITM
+    GPIO_InitStruct.Pin |=  GPIO_PIN_3;
+#endif
+    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
+    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+
+
+
+    /*Configure GPIO pin : PC7 7 segment  B */
+    GPIO_InitStruct.Pin = GPIO_PIN_7;
+    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
+    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
+    /* turn off all 7 seg digit */
+    _V1_DisplayOff();
+}
+
+
+
+static void _V2_GPIO_Init(){
+    uint16_t PadDir;
+
+    GPIO_InitTypeDef GPIO_InitStruct;
+
+    __GPIOA_CLK_ENABLE();
+    __GPIOB_CLK_ENABLE();
+    
+    /*Configure GPIO pins interrupt PA4 = INTB , PA5 = INTL, pA10 = INTR */
+    GPIO_InitStruct.Pin = GPIO_PIN_4 | GPIO_PIN_5 |GPIO_PIN_10 ;
+    GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+
+    /* PB0 = INT */
+    GPIO_InitStruct.Pin = GPIO_PIN_0;
+    GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
+    GPIO_InitStruct.Pull = GPIO_NOPULL;
+    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+
+    /* expender config */
+    PadDir=~V2_DISP_SEL;
+    V2_ExpanderWR(GPDR, (uint8_t*)&PadDir, 2);
+
+    _V2_DisplayOff();
+
+}
+
+static void _V2_DisplayOff() {
+    _V2PadVal |= (V2_D1|V2_D2|V2_D3| V2_D4); /* segment en off */
+    V2_ExpanderWR(GPSR, (uint8_t*)&_V2PadVal, 2);
+}
+
+static void _V1_DisplayOff() {
+    int i;
+    for( i=0; i<4; i++ ){
+        pad_write(DisplayEn[i], GPIO_PIN_SET); /* turn off led */
+    }
+}
+
+/* set 7 segment bus to display decode "value" */
+static void _V1_Set7Segment(const uint8_t value) {
+    int i;
+    GPIO_PinState state;
+    for (i = 0; i < sizeof(DisplaySeg)/sizeof(DisplaySeg[0]); i++) {
+        int cur_bit;
+        cur_bit = value & (1 << i);
+        state = cur_bit ?  GPIO_PIN_RESET: GPIO_PIN_SET; /* port clear= segment on */
+        pad_write(DisplaySeg[i], state);
+    }
+}
+
+/* set state of decimal point on 7 segment bus */
+static void _V1_Set7SegmentDP( int dp_state) {
+    GPIO_PinState state;
+
+
+    state = dp_state ?  GPIO_PIN_RESET: GPIO_PIN_SET; // port clear= segment on
+    pad_write(DisplaySeg[7], state);
+    //HAL_GPIO_WritePin((void*)GPIOA + DisplaySeg[7].port*((void*)GPIOB-(void*)GPIOA), 1<<DisplaySeg[7].pin, state);
+}
+
+
+

+ 53 - 0
modules/bsp/x-nucleo-6180xa1.h

@@ -0,0 +1,53 @@
+/*
+ * @file x-nucleo-6180xa1.h
+ * $Date: 2015-03-30 16:27:10 +0200 (Mon, 30 Mar 2015) $
+ * $Revision: 2215 $
+ */
+
+#ifndef XNUCLEO6180XA1_H_
+#define XNUCLEO6180XA1_H_
+
+
+#define SWITCH_VAL_RANGING  0
+
+/* function below must be provided  */
+void XNUCLEO6180XA1_WaitMilliSec(int SegDelayMs);
+/* optional list */
+void XNUCLEO6180XA1_UserIntHandler(void);
+
+/* provided */
+void XNUCLEO6180XA1_GPIO_Init(void);
+void XNUCLEO6180XA1_I2C1_Init(I2C_HandleTypeDef *hi2c1);
+void XNUCLEO6180XA1_DisplayString(const char *str, int SegDelayMs);
+
+void XNUCLEO6180XA1_EnableInterrupt(void);
+void XNUCLEO6180XA1_DisableInterrupt(void);
+void XNUCLEO6180XA1_ClearInterrupt(void);
+
+int XNUCLEO6180XA1_GetSwitch(void);
+void XNUCLEO6180XA1_Reset(int state);
+
+/**
+ * @brief  get version of Expansion board
+ * @warning to be called only aftrer @a XNUCLEO6180XA1_I2C1_Init() get called
+ * @return True if connected shield is v2
+ */
+int XNUCLEO6180XA1_IsV2(void);
+
+/**
+ * @brief  tio be called by HAL EXTI handler dispatecher
+ * @warning to be called only aftrer @a XNUCLEO6180XA1_I2C1_Init() get called
+ * @param pin
+ * @return  non 0 if the GPIO_pin is the GPIO pin for active VL6180x GPIO int line
+ */
+int XNUCLEO6180XA1_EXTI_CallBackHandle(uint16_t GPIO_Pin);
+
+
+/*all function below only valid for v2 */
+#define XNUCLEO6180XA1_ID_TOP   0
+#define XNUCLEO6180XA1_ID_BOT   1
+#define XNUCLEO6180XA1_ID_LEFT  2
+#define XNUCLEO6180XA1_ID_RIGHT 3
+int XNUCLEO6180XA1_ResetId(int state, int id);
+
+#endif /* XNUCLEO6180XA1_H_ */

+ 22 - 1
modules/lt8920/lt8920_test.cpp

@@ -3,6 +3,7 @@
 #include "lt8920.h"
 #include "stm32l0xx_nucleo.h"
 #include <stdio.h>
+#include <string.h>
 
 LT8920 lt;
 
@@ -14,7 +15,7 @@ char sbuf[64];
  
  
 //
-void lt_test_1(void)
+void lt_scanner_init(void)
 {
     lt.begin();
     lt.setCurrentControl(15, 15);  
@@ -45,4 +46,24 @@ void lt_scanner_test(void)
         printf("\r\n");
     }
     HAL_Delay(250);
+}
+
+//
+void lt_sender_init(void)
+{
+    lt.begin();
+    lt.setCurrentControl(0, 0);
+    lt.setDataRate(LT8920::LT8920_1MBPS);
+    lt.setChannel(0x20);
+}
+
+//
+void lt_sender_test(void)
+{
+    static uint8_t number = 0;
+    char data[16] = {0};
+    
+    HAL_Delay(100);
+    sprintf(data, "number: %d\n", number++);
+    lt.sendPacket((uint8_t*)data, strlen(data) + 1);
 }

+ 8 - 1
modules/lt8920/lt8920_test.h

@@ -3,9 +3,16 @@
 
 
 //
-void lt_test_1(void);
+void lt_scanner_init(void);
 
 //
 void lt_scanner_test(void);
 
+//
+void lt_sender_init(void);
+
+//
+void lt_sender_test(void);
+
+
 #endif

+ 2769 - 0
modules/vl6180x/vl6180x_api.c

@@ -0,0 +1,2769 @@
+/*******************************************************************************
+Copyright © 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.
+********************************************************************************/
+
+/*
+ * $Date: 2018-07-04 16:49:57 +0200 (Wed, 04 Jul 2018) $
+ * $Revision: 2768 $
+ */
+#include "vl6180x_api.h"
+
+#define VL6180x_9to7Conv(x) (x)
+
+/* TODO when set all "cached" value with "default init" are updated after init from register read back */
+#define REFRESH_CACHED_DATA_AFTER_INIT  1
+
+
+#define IsValidGPIOFunction(x) ((x) == GPIOx_SELECT_GPIO_INTERRUPT_OUTPUT || (x) == GPIOx_SELECT_OFF)
+
+
+/** default value ECE factor Molecular */
+#define DEF_ECE_FACTOR_M    85
+/** default value ECE factor Denominator */
+#define DEF_ECE_FACTOR_D    100
+/** default value ALS integration time */
+#define DEF_INT_PEFRIOD     100
+/** default value ALS gain */
+#define DEF_ALS_GAIN        1
+/** default value ALS scaler */
+#define DEF_ALS_SCALER      1
+/** default value for DMAX Enable */
+#define DEF_DMAX_ENABLE     1
+/** default ambient tuning factor %x1000 */
+#define DEF_AMBIENT_TUNING  80
+
+#define DEF_CROSS_TALK_VALID_HEIGHT_VALUE   20
+
+
+#if VL6180x_SINGLE_DEVICE_DRIVER
+extern  struct VL6180xDevData_t SingleVL6180xDevData;
+#define VL6180xDevDataGet(dev, field) (SingleVL6180xDevData.field)
+#define VL6180xDevDataSet(dev, field, data) SingleVL6180xDevData.field = (data)
+#endif
+
+#define LUXRES_FIX_PREC 8
+#define GAIN_FIX_PREC    8  /* ! if not sme as LUX_PREC then :( adjust GetLux */
+#define AN_GAIN_MULT    (1 << GAIN_FIX_PREC)
+
+
+static int32_t _GetAveTotalTime(VL6180xDev_t dev);
+static int VL6180x_RangeSetEarlyConvergenceEestimateThreshold(VL6180xDev_t dev);
+
+/**
+ * ScalerLookUP scaling factor-1 to register #RANGE_SCALER lookup
+ */
+static const uint16_t ScalerLookUP[]      ROMABLE_DATA = {253, 127, 84}; /* lookup table for scaling->scalar 1x2x 3x */
+/**
+ * scaling factor to Upper limit look up
+ */
+static const uint16_t UpperLimitLookUP[]  ROMABLE_DATA = {185, 370, 580}; /* lookup table for scaling->limit  1x2x3x */
+/**
+ * Als Code gain to fix point gain lookup
+ */
+static const uint16_t AlsGainLookUp[8]    ROMABLE_DATA = {
+	(uint16_t)(20.0f * AN_GAIN_MULT),
+	(uint16_t)(10.0f * AN_GAIN_MULT),
+	(uint16_t)(5.0f  * AN_GAIN_MULT),
+	(uint16_t)(2.5f  * AN_GAIN_MULT),
+	(uint16_t)(1.67f * AN_GAIN_MULT),
+	(uint16_t)(1.25f * AN_GAIN_MULT),
+	(uint16_t)(1.0f  * AN_GAIN_MULT),
+	(uint16_t)(40.0f * AN_GAIN_MULT),
+};
+
+
+#if VL6180x_RANGE_STATUS_ERRSTRING
+const char *ROMABLE_DATA VL6180x_RangeStatusErrString[] = {
+	"No Error",
+	"VCSEL Continuity Test",
+	"VCSEL Watchdog Test",
+	"VCSEL Watchdog",
+	"PLL1 Lock",
+	"PLL2 Lock",
+	"Early Convergence Estimate",
+	"Max Convergence",
+	"No Target Ignore",
+	"Not used 9",
+	"Not used 10",
+	"Max Signal To Noise Ratio",
+	"Raw Ranging Algo Underflow",
+	"Raw Ranging Algo Overflow",
+	"Ranging Algo Underflow",
+	"Ranging Algo Overflow",
+
+	"Filtered by post processing (WAF)",
+	"Ranging filtering (WAF) on-going",
+	"Data not ready",
+};
+
+const char *VL6180x_RangeGetStatusErrString(uint8_t RangeErrCode)
+{
+	if (RangeErrCode > sizeof(VL6180x_RangeStatusErrString) / sizeof(VL6180x_RangeStatusErrString[0]))
+		return NULL;
+	return  VL6180x_RangeStatusErrString[RangeErrCode];
+}
+#endif
+
+#if VL6180x_UPSCALE_SUPPORT == 1
+	#define _GetUpscale(dev, ...)  1
+	#define _SetUpscale(...) -1
+	#define DEF_UPSCALE 1
+#elif VL6180x_UPSCALE_SUPPORT == 2
+	#define _GetUpscale(dev, ...)  2
+	#define _SetUpscale(...)
+	#define DEF_UPSCALE 2
+#elif VL6180x_UPSCALE_SUPPORT == 3
+	#define _GetUpscale(dev, ...)  3
+	#define _SetUpscale(...)
+	#define DEF_UPSCALE 3
+#else
+	#define DEF_UPSCALE (-(VL6180x_UPSCALE_SUPPORT))
+	#define _GetUpscale(dev, ...) VL6180xDevDataGet(dev, UpscaleFactor)
+	#define _SetUpscale(dev, Scaling) VL6180xDevDataSet(dev, UpscaleFactor, Scaling)
+#endif
+
+
+#if VL6180x_SINGLE_DEVICE_DRIVER
+/**
+ * the unique driver data  When single device driver is active
+ */
+struct VL6180xDevData_t VL6180x_DEV_DATA_ATTR  SingleVL6180xDevData = {
+	.EceFactorM        = DEF_ECE_FACTOR_M,
+	.EceFactorD        = DEF_ECE_FACTOR_D,
+#ifdef VL6180x_HAVE_UPSCALE_DATA
+	.UpscaleFactor     = DEF_UPSCALE,
+#endif
+#ifdef VL6180x_HAVE_ALS_DATA
+	.IntegrationPeriod = DEF_INT_PEFRIOD,
+	.AlsGainCode       = DEF_ALS_GAIN,
+	.AlsScaler         = DEF_ALS_SCALER,
+#endif
+#ifdef VL6180x_HAVE_DMAX_RANGING
+	.DMaxEnable =   DEF_DMAX_ENABLE,
+#endif
+};
+#endif /* VL6180x_SINGLE_DEVICE_DRIVER */
+
+
+
+#define Fix7_2_KCPs(x) ((((uint32_t)(x))*1000)>>7)
+
+
+#if VL6180x_WRAP_AROUND_FILTER_SUPPORT || VL6180x_HAVE_DMAX_RANGING
+static int _GetRateResult(VL6180xDev_t dev, VL6180x_RangeData_t *pRangeData);
+#endif
+
+#if VL6180x_WRAP_AROUND_FILTER_SUPPORT
+static int _filter_Init(VL6180xDev_t dev);
+static int _filter_GetResult(VL6180xDev_t dev, VL6180x_RangeData_t *pData);
+	#define _IsWrapArroundActive(dev) VL6180xDevDataGet(dev, WrapAroundFilterActive)
+#else
+	#define _IsWrapArroundActive(dev) 0
+#endif
+
+
+#if VL6180x_HAVE_DMAX_RANGING
+	void _DMax_OneTimeInit(VL6180xDev_t dev);
+	static int _DMax_InitData(VL6180xDev_t dev);
+	static int _DMax_Compute(VL6180xDev_t dev, VL6180x_RangeData_t *pRange);
+	#define _IsDMaxActive(dev) VL6180xDevDataGet(dev, DMaxEnable)
+#else
+	#define _DMax_InitData(...) 0 /* success */
+	#define _DMax_OneTimeInit(...) (void)0
+	#define _IsDMaxActive(...) 0
+#endif
+
+static int VL6180x_RangeStaticInit(VL6180xDev_t dev);
+static int  VL6180x_UpscaleStaticInit(VL6180xDev_t dev);
+
+int VL6180x_WaitDeviceBooted(VL6180xDev_t dev)
+{
+	uint8_t FreshOutReset;
+	int status;
+	LOG_FUNCTION_START("");
+	do {
+		status = VL6180x_RdByte(dev, SYSTEM_FRESH_OUT_OF_RESET, &FreshOutReset);
+	} while (FreshOutReset != 1 && status == 0);
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+int VL6180x_InitData(VL6180xDev_t dev)
+{
+	int status, dmax_status ;
+	int8_t offset;
+	uint8_t FreshOutReset;
+	uint32_t CalValue;
+	uint16_t u16;
+	uint32_t XTalkCompRate_KCps;
+
+	LOG_FUNCTION_START("");
+
+	VL6180xDevDataSet(dev, EceFactorM, DEF_ECE_FACTOR_M);
+	VL6180xDevDataSet(dev, EceFactorD, DEF_ECE_FACTOR_D);
+
+	VL6180xDevDataSet(dev, RangeIgnore.Enabled, 0);
+
+#ifdef VL6180x_HAVE_UPSCALE_DATA
+	VL6180xDevDataSet(dev, UpscaleFactor,  DEF_UPSCALE);
+#endif
+
+#ifdef VL6180x_HAVE_ALS_DATA
+	VL6180xDevDataSet(dev, IntegrationPeriod, DEF_INT_PEFRIOD);
+	VL6180xDevDataSet(dev, AlsGainCode, DEF_ALS_GAIN);
+	VL6180xDevDataSet(dev, AlsScaler, DEF_ALS_SCALER);
+#endif
+
+#ifdef VL6180x_HAVE_WRAP_AROUND_DATA
+	VL6180xDevDataSet(dev, WrapAroundFilterActive, (VL6180x_WRAP_AROUND_FILTER_SUPPORT > 0));
+	VL6180xDevDataSet(dev, DMaxEnable, DEF_DMAX_ENABLE);
+#endif
+
+	_DMax_OneTimeInit(dev);
+	do {
+
+		/* backup offset initial value from nvm these must be done prior any over call that use offset */
+		status = VL6180x_RdByte(dev, SYSRANGE_PART_TO_PART_RANGE_OFFSET, (uint8_t *)&offset);
+		if (status) {
+			VL6180x_ErrLog("SYSRANGE_PART_TO_PART_RANGE_OFFSET rd fail");
+			break;
+		}
+		VL6180xDevDataSet(dev, Part2PartOffsetNVM, offset);
+
+		status = VL6180x_RdDWord(dev, SYSRANGE_RANGE_IGNORE_THRESHOLD, &CalValue);
+		if (status) {
+			VL6180x_ErrLog("Part2PartAmbNVM rd fail");
+			break;
+		}
+		if ((CalValue&0xFFFF0000) == 0) {
+			CalValue = 0x00CE03F8;
+		}
+		VL6180xDevDataSet(dev, Part2PartAmbNVM, CalValue);
+
+		status = VL6180x_RdWord(dev, SYSRANGE_CROSSTALK_COMPENSATION_RATE , &u16);
+		if (status) {
+			VL6180x_ErrLog("SYSRANGE_CROSSTALK_COMPENSATION_RATE rd fail ");
+			break;
+		}
+		XTalkCompRate_KCps = Fix7_2_KCPs(u16);
+		VL6180xDevDataSet(dev, XTalkCompRate_KCps, XTalkCompRate_KCps);
+
+		dmax_status = _DMax_InitData(dev);
+		if (dmax_status < 0) {
+			VL6180x_ErrLog("DMax init failure");
+			break;
+		}
+
+		/* Read or wait for fresh out of reset  */
+		status = VL6180x_RdByte(dev, SYSTEM_FRESH_OUT_OF_RESET, &FreshOutReset);
+		if (status) {
+			VL6180x_ErrLog("SYSTEM_FRESH_OUT_OF_RESET rd fail");
+			break;
+		}
+		if (FreshOutReset != 1 || dmax_status)
+			status = CALIBRATION_WARNING;
+
+	} while (0);
+
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+int8_t VL6180x_GetOffsetCalibrationData(VL6180xDev_t dev)
+{
+	int8_t offset;
+	LOG_FUNCTION_START("");
+	offset = VL6180xDevDataGet(dev, Part2PartOffsetNVM);
+	LOG_FUNCTION_END(offset);
+	return offset;
+}
+
+int  VL6180x_SetOffsetCalibrationData(VL6180xDev_t dev, int8_t offset)
+{
+	int status;
+	LOG_FUNCTION_START("%d", offset);
+	VL6180xDevDataSet(dev, Part2PartOffsetNVM, offset);
+	offset /= _GetUpscale(dev);
+	status = VL6180x_WrByte(dev, SYSRANGE_PART_TO_PART_RANGE_OFFSET, offset);
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+int  VL6180x_SetXTalkCompensationRate(VL6180xDev_t dev, FixPoint97_t Rate)
+{
+	int status;
+	LOG_FUNCTION_START("%d", Rate);
+	status = VL6180x_WrWord(dev, SYSRANGE_CROSSTALK_COMPENSATION_RATE, Rate);
+	if (status == 0) {
+		uint32_t XTalkCompRate_KCps;
+		XTalkCompRate_KCps = Fix7_2_KCPs(Rate);
+		VL6180xDevDataSet(dev, XTalkCompRate_KCps, XTalkCompRate_KCps);
+		/* update dmax whenever xtalk rate changes */
+		status = _DMax_InitData(dev);
+	}
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+int VL6180x_SetI2CAddress(VL6180xDev_t dev, uint8_t NewAddress)
+{
+	int status;
+	LOG_FUNCTION_START("");
+
+	status = VL6180x_WrByte(dev, I2C_SLAVE_DEVICE_ADDRESS, NewAddress / 2);
+	if (status) {
+		VL6180x_ErrLog("new i2c addr Wr fail");
+	}
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+uint16_t VL6180x_GetUpperLimit(VL6180xDev_t dev)
+{
+	uint16_t limit;
+	int scaling;
+
+	LOG_FUNCTION_START("");
+
+	scaling = _GetUpscale(dev);
+	/* FIXME we do assume here _GetUpscale is valid if  user call us prior to init we may overflow the LUT  mem area */
+	limit = UpperLimitLookUP[scaling - 1];
+
+	LOG_FUNCTION_END((int)limit);
+	return limit;
+}
+
+
+
+int VL6180x_StaticInit(VL6180xDev_t dev)
+{
+	int status = 0, init_status;
+	LOG_FUNCTION_START("");
+
+	/* TODO doc When using configurable scaling but using 1x as start condition
+	 * load tunning upscale  or not ??? */
+	if (_GetUpscale(dev) == 1 && !(VL6180x_UPSCALE_SUPPORT < 0))
+		init_status = VL6180x_RangeStaticInit(dev);
+	else
+		init_status = VL6180x_UpscaleStaticInit(dev);
+
+	if (init_status < 0) {
+		VL6180x_ErrLog("StaticInit fail");
+		goto error;
+	} else if (init_status > 0) {
+		VL6180x_ErrLog("StaticInit warning");
+	}
+
+	#if REFRESH_CACHED_DATA_AFTER_INIT
+	#ifdef VL6180x_HAVE_ALS_DATA
+	/* update cached value after tuning applied */
+	do {
+		uint8_t data;
+		status =  VL6180x_RdByte(dev, FW_ALS_RESULT_SCALER, &data);
+		if (status)
+			break;
+		VL6180xDevDataSet(dev, AlsScaler, data);
+
+		status =  VL6180x_RdByte(dev, SYSALS_ANALOGUE_GAIN, &data);
+		if (status)
+			break;
+		VL6180x_AlsSetAnalogueGain(dev, data);
+	} while (0);
+	#endif
+	#endif /* REFRESH_CACHED_DATA_AFTER_INIT */
+	if (status < 0) {
+		VL6180x_ErrLog("StaticInit fail");
+	}
+	if (!status && init_status) {
+		status = init_status;
+	}
+error:
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+
+int VL6180x_SetGroupParamHold(VL6180xDev_t dev, int Hold)
+{
+	int status;
+	uint8_t value;
+
+	LOG_FUNCTION_START("%d", Hold);
+	if (Hold)
+		value = 1;
+	else
+		value = 0;
+	status = VL6180x_WrByte(dev, SYSTEM_GROUPED_PARAMETER_HOLD, value);
+
+	LOG_FUNCTION_END(status);
+	return status;
+
+}
+
+int VL6180x_Prepare(VL6180xDev_t dev)
+{
+	int status;
+	LOG_FUNCTION_START("");
+
+	do {
+		status = VL6180x_StaticInit(dev);
+		if (status < 0)
+			break;
+
+		/* set range InterruptMode to new sample */
+		status = VL6180x_RangeConfigInterrupt(dev, CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY);
+		if (status)
+			break;
+
+		/* set default threshold */
+		status = VL6180x_RangeSetRawThresholds(dev, 10, 200);
+		if (status) {
+			VL6180x_ErrLog("VL6180x_RangeSetRawThresholds fail");
+			break;
+		}
+	#if VL6180x_ALS_SUPPORT
+		status = VL6180x_AlsSetIntegrationPeriod(dev, 100);
+		if (status)
+			break;
+		status = VL6180x_AlsSetInterMeasurementPeriod(dev,  200);
+		if (status)
+			break;
+		status = VL6180x_AlsSetAnalogueGain(dev,  0);
+		if (status)
+			break;
+		status = VL6180x_AlsSetThresholds(dev, 0, 0xFF);
+		if (status)
+			break;
+		/* set Als InterruptMode to new sample */
+		status = VL6180x_AlsConfigInterrupt(dev, CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY);
+		if (status) {
+			VL6180x_ErrLog("VL6180x_AlsConfigInterrupt fail");
+			break;
+		}
+	#endif
+	#if VL6180x_WRAP_AROUND_FILTER_SUPPORT
+		_filter_Init(dev);
+	#endif
+		/* make sure to reset any left previous condition that can hangs first poll */
+		status = VL6180x_ClearAllInterrupt(dev);
+	} while (0);
+	LOG_FUNCTION_END(status);
+
+	return status;
+}
+
+#if VL6180x_ALS_SUPPORT
+int VL6180x_AlsGetLux(VL6180xDev_t dev, lux_t *pLux)
+{
+	int status;
+	uint16_t RawAls;
+	uint32_t luxValue = 0;
+	uint32_t IntPeriod;
+	uint32_t AlsAnGain;
+	uint32_t GainFix;
+	uint32_t AlsScaler;
+
+	#if LUXRES_FIX_PREC !=  GAIN_FIX_PREC
+	#error "LUXRES_FIX_PREC != GAIN_FIX_PREC  review these code to be correct"
+	#endif
+	const uint32_t LuxResxIntIme = (uint32_t)(0.56f * DEF_INT_PEFRIOD * (1 << LUXRES_FIX_PREC));
+
+	LOG_FUNCTION_START("%p", pLux);
+
+	status = VL6180x_RdWord(dev, RESULT_ALS_VAL, &RawAls);
+	if (!status) {
+		/* wer are yet here at no fix point */
+		IntPeriod = VL6180xDevDataGet(dev, IntegrationPeriod);
+		AlsScaler = VL6180xDevDataGet(dev, AlsScaler);
+		IntPeriod++; /* what stored is real time  ms -1 and it can be 0 for or 0 or 1ms */
+		luxValue = (uint32_t)RawAls * LuxResxIntIme; /* max # 16+8bits + 6bit (0.56*100)  */
+		luxValue /= IntPeriod;                         /* max # 16+8bits + 6bit 16+8+1 to 9 bit */
+		/* between  29 - 21 bit */
+		AlsAnGain = VL6180xDevDataGet(dev, AlsGainCode);
+		GainFix = AlsGainLookUp[AlsAnGain];
+		luxValue = luxValue / (AlsScaler * GainFix);
+		*pLux = luxValue;
+	}
+
+	LOG_FUNCTION_END_FMT(status, "%x", (int)*pLux);
+	return status;
+}
+
+int VL6180x_AlsGetMeasurement(VL6180xDev_t dev, VL6180x_AlsData_t *pAlsData)
+{
+	int status;
+	uint8_t ErrStatus;
+
+	LOG_FUNCTION_START("%p", pAlsData);
+
+	status = VL6180x_AlsGetLux(dev, &pAlsData->lux);
+	if (!status) {
+		status = VL6180x_RdByte(dev, RESULT_ALS_STATUS, &ErrStatus);
+		pAlsData->errorStatus = ErrStatus >> 4;
+	}
+	LOG_FUNCTION_END_FMT(status, "%d %d", (int)pAlsData->lux,  (int)pAlsData->errorStatus);
+
+	return status;
+}
+
+
+int VL6180x_AlsPollMeasurement(VL6180xDev_t dev, VL6180x_AlsData_t *pAlsData)
+{
+	int status;
+	int ClrStatus;
+	uint8_t IntStatus;
+
+	LOG_FUNCTION_START("%p", pAlsData);
+	#if VL6180X_SAFE_POLLING_ENTER
+	/* if device get stopped with left interrupt uncleared , it is required to clear them now or poll for new condition will never occur*/
+	status = VL6180x_AlsClearInterrupt(dev);
+	if (status) {
+		VL6180x_ErrLog("VL6180x_AlsClearInterrupt fail");
+		goto over;
+	}
+	#endif
+
+	status = VL6180x_AlsSetSystemMode(dev, MODE_START_STOP | MODE_SINGLESHOT);
+	if (status) {
+		VL6180x_ErrLog("VL6180x_AlsSetSystemMode fail");
+		goto over;
+	}
+
+	/* poll for new sample ready */
+	while (1) {
+		status = VL6180x_AlsGetInterruptStatus(dev, &IntStatus);
+		if (status) {
+			break;
+		}
+		if (IntStatus == RES_INT_STAT_GPIO_NEW_SAMPLE_READY) {
+			break; /* break on new data (status is 0)  */
+		}
+
+		VL6180x_PollDelay(dev);
+	};
+
+	if (!status) {
+		status = VL6180x_AlsGetMeasurement(dev, pAlsData);
+	}
+
+	ClrStatus = VL6180x_AlsClearInterrupt(dev);
+	if (ClrStatus) {
+		VL6180x_ErrLog("VL6180x_AlsClearInterrupt fail");
+		if (!status) {
+		    status = ClrStatus; /* leave previous if already on error */
+		}
+	}
+over:
+	LOG_FUNCTION_END(status);
+
+	return status;
+}
+
+int VL6180x_AlsGetInterruptStatus(VL6180xDev_t dev, uint8_t *pIntStatus)
+{
+	int status;
+	uint8_t IntStatus;
+	LOG_FUNCTION_START("%p", pIntStatus);
+
+	status = VL6180x_RdByte(dev, RESULT_INTERRUPT_STATUS_GPIO, &IntStatus);
+	*pIntStatus = (IntStatus >> 3) & 0x07;
+
+	LOG_FUNCTION_END_FMT(status, "%d", (int)*pIntStatus);
+	return status;
+}
+
+int VL6180x_AlsWaitDeviceReady(VL6180xDev_t dev, int MaxLoop)
+{
+	int status;
+	int  n;
+	uint8_t u8;
+	LOG_FUNCTION_START("%d", (int)MaxLoop);
+	if (MaxLoop < 1) {
+		status = INVALID_PARAMS;
+	} else {
+		for (n = 0; n < MaxLoop; n++) {
+			status = VL6180x_RdByte(dev, RESULT_ALS_STATUS, &u8);
+			if (status)
+				break;
+			u8 = u8 & ALS_DEVICE_READY_MASK;
+			if (u8)
+				break;
+
+		}
+		if (!status && !u8) {
+			status = TIME_OUT;
+		}
+	}
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+int VL6180x_AlsSetSystemMode(VL6180xDev_t dev, uint8_t mode)
+{
+	int status;
+	LOG_FUNCTION_START("%d", (int)mode);
+	/* FIXME if we are called back to back real fast we are not checking
+	 * if previous mode "set" got absorbed => bit 0 must be 0 so that wr 1 work */
+	if (mode <= 3) {
+		status = VL6180x_WrByte(dev, SYSALS_START, mode);
+	} else {
+		status = INVALID_PARAMS;
+	}
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+int VL6180x_AlsConfigInterrupt(VL6180xDev_t dev, uint8_t ConfigGpioInt)
+{
+	int status;
+
+	if (ConfigGpioInt <= CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY) {
+		status = VL6180x_UpdateByte(dev, SYSTEM_INTERRUPT_CONFIG_GPIO, (uint8_t)(~CONFIG_GPIO_ALS_MASK), (ConfigGpioInt << 3));
+	} else {
+		VL6180x_ErrLog("Invalid config mode param %d", (int)ConfigGpioInt);
+		status = INVALID_PARAMS;
+	}
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+
+
+int VL6180x_AlsSetThresholds(VL6180xDev_t dev, uint8_t low, uint8_t high)
+{
+	int status;
+
+	LOG_FUNCTION_START("%d %d", (int)low, (int)high);
+
+	status = VL6180x_WrByte(dev, SYSALS_THRESH_LOW, low);
+	if (!status) {
+		status = VL6180x_WrByte(dev, SYSALS_THRESH_HIGH, high);
+	}
+
+	LOG_FUNCTION_END(status) ;
+	return status;
+}
+
+
+int VL6180x_AlsSetAnalogueGain(VL6180xDev_t dev, uint8_t gain)
+{
+	int status;
+	uint8_t GainTotal;
+
+	LOG_FUNCTION_START("%d", (int)gain);
+	gain &= ~0x40;
+	if (gain > 7) {
+		gain = 7;
+	}
+	GainTotal = gain | 0x40;
+
+	status = VL6180x_WrByte(dev, SYSALS_ANALOGUE_GAIN, GainTotal);
+	if (!status) {
+		VL6180xDevDataSet(dev, AlsGainCode, gain);
+	}
+
+	LOG_FUNCTION_END_FMT(status, "%d %d", (int)gain, (int)GainTotal);
+	return status;
+}
+
+int VL6180x_AlsSetInterMeasurementPeriod(VL6180xDev_t dev,  uint16_t intermeasurement_period_ms)
+{
+	int status;
+
+	LOG_FUNCTION_START("%d", (int)intermeasurement_period_ms);
+	/* clipping: range is 0-2550ms */
+	if (intermeasurement_period_ms >= 255 * 10)
+		intermeasurement_period_ms = 255 * 10;
+	status = VL6180x_WrByte(dev, SYSALS_INTERMEASUREMENT_PERIOD, (uint8_t)(intermeasurement_period_ms / 10));
+
+	LOG_FUNCTION_END_FMT(status, "%d", (int)intermeasurement_period_ms);
+	return status;
+}
+
+
+int VL6180x_AlsSetIntegrationPeriod(VL6180xDev_t dev, uint16_t period_ms)
+{
+	int status;
+	uint16_t SetIntegrationPeriod;
+
+	LOG_FUNCTION_START("%d", (int)period_ms);
+
+	if (period_ms >= 1)
+		SetIntegrationPeriod = period_ms - 1;
+	else
+		SetIntegrationPeriod = period_ms;
+
+	if (SetIntegrationPeriod > 464) {
+		SetIntegrationPeriod = 464;
+	} else if (SetIntegrationPeriod == 255)   {
+		SetIntegrationPeriod++; /* can't write 255 since this causes the device to lock out.*/
+	}
+
+	status = VL6180x_WrWord(dev, SYSALS_INTEGRATION_PERIOD, SetIntegrationPeriod);
+	if (!status) {
+		VL6180xDevDataSet(dev, IntegrationPeriod, SetIntegrationPeriod) ;
+	}
+	LOG_FUNCTION_END_FMT(status, "%d", (int)SetIntegrationPeriod);
+	return status;
+}
+
+#endif /* HAVE_ALS_SUPPORT */
+
+
+int VL6180x_RangePollMeasurement(VL6180xDev_t dev, VL6180x_RangeData_t *pRangeData)
+{
+	int status;
+	int ClrStatus;
+	IntrStatus_t IntStatus;
+
+	LOG_FUNCTION_START("");
+	/* start single range measurement */
+
+
+	#if VL6180X_SAFE_POLLING_ENTER
+	/* if device get stopped with left interrupt uncleared , it is required to clear them now or poll for new condition will never occur*/
+	status = VL6180x_RangeClearInterrupt(dev);
+	if (status) {
+		VL6180x_ErrLog("VL6180x_RangeClearInterrupt fail");
+		goto done;
+	}
+	#endif
+	/* //![single_shot_snipet] */
+	status = VL6180x_RangeSetSystemMode(dev, MODE_START_STOP | MODE_SINGLESHOT);
+	if (status) {
+		VL6180x_ErrLog("VL6180x_RangeSetSystemMode fail");
+		goto done;
+	}
+
+
+	/* poll for new sample ready */
+	while (1) {
+		status = VL6180x_RangeGetInterruptStatus(dev, &IntStatus.val);
+		if (status) {
+			break;
+		}
+		if (IntStatus.status.Range == RES_INT_STAT_GPIO_NEW_SAMPLE_READY || IntStatus.status.Error != 0) {
+			break;
+		}
+
+		VL6180x_PollDelay(dev);
+	}
+	/* //![single_shot_snipet] */
+
+	if (!status) {
+		status = VL6180x_RangeGetMeasurement(dev, pRangeData);
+	}
+
+	/*  clear range interrupt source */
+	ClrStatus = VL6180x_RangeClearInterrupt(dev);
+	if (ClrStatus) {
+		VL6180x_ErrLog("VL6180x_RangeClearInterrupt fail");
+		/*  leave initial status if already in error  */
+		if (!status) {
+			status = ClrStatus;
+		}
+	}
+done:
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+
+#if VL6180x_CACHED_REG
+
+int VL6180x_GetCachedDWord(VL6180xDev_t dev, uint16_t  index, uint32_t *pValue)
+{
+	int status;
+	uint32_t Value;
+	if (VL6180xDevDataGet(dev, CacheFilled) != 0 &&
+		index >= VL6180x_FIRST_CACHED_INDEX  &&
+		index <= (VL6180x_LAST_CACHED_INDEX - 3)) {
+		uint8_t *pBytes = &VL6180xDevDataGet(dev, CachedRegs[index - VL6180x_FIRST_CACHED_INDEX]);
+		Value = ((uint32_t)pBytes[0] << 24) |
+				((uint32_t)pBytes[1] << 16) |
+				((uint32_t)pBytes[2] << 8) |
+				(uint32_t)pBytes[3];
+		*pValue = Value;
+		status = 0;
+	} else {
+		status =  VL6180x_RdDWord(dev, index, pValue);
+	}
+	return status;
+}
+
+int VL6180x_GetCachedWord(VL6180xDev_t dev, uint16_t  index, uint16_t *pValue)
+{
+	int status;
+	uint32_t Value;
+	if (VL6180xDevDataGet(dev, CacheFilled) != 0 &&
+		index >= VL6180x_FIRST_CACHED_INDEX  &&
+		index <= (VL6180x_LAST_CACHED_INDEX - 1)) {
+		uint8_t *pBytes = &VL6180xDevDataGet(dev, CachedRegs[index - VL6180x_FIRST_CACHED_INDEX]);
+		Value = ((uint32_t)pBytes[0] << 8) | (uint32_t)pBytes[1];
+		*pValue = Value;
+		status = 0;
+	} else {
+		status =  VL6180x_RdWord(dev, index, pValue);
+	}
+	return status;
+}
+
+int VL6180x_GetCachedByte(VL6180xDev_t dev, uint16_t  index, uint8_t *pValue)
+{
+	int status;
+	uint8_t Value;
+	if (VL6180xDevDataGet(dev, CacheFilled) != 0 &&
+		index >= VL6180x_FIRST_CACHED_INDEX &&
+		index <= VL6180x_LAST_CACHED_INDEX) {
+		Value = VL6180xDevDataGet(dev, CachedRegs[index - VL6180x_FIRST_CACHED_INDEX]);
+		*pValue = Value;
+		status = 0;
+	} else {
+		status =  VL6180x_RdByte(dev, index, pValue);
+	}
+	return status;
+}
+
+
+int _CachedRegs_Fetch(VL6180xDev_t dev)
+{
+	int status;
+	uint8_t *Buffer;
+	if (VL6180xDevDataGet(dev, CacheFilled) == 0) {
+		VL6180xDevDataSet(dev, CacheFilled, 1);
+		Buffer = &VL6180xDevDataGet(dev, CachedRegs[0]);
+		status = VL6180x_RdMulti(dev, VL6180x_FIRST_CACHED_INDEX, Buffer, VL6180x_CACHED_REG_CNT);
+	} else {
+		status = 0 ;
+	}
+	return status;
+}
+
+void _CachedRegs_Flush(VL6180xDev_t dev)
+{
+	VL6180xDevDataSet(dev, CacheFilled, 0);
+}
+
+#else
+#   define _CachedRegs_Fetch(...) 0
+#   define _CachedRegs_Flush(...) (void)0
+#   define _Fetch_CachedRegs(...) 0
+#   define VL6180x_GetCachedByte(dev, index, pValue) VL6180x_RdByte(dev, index, pValue)
+#   define VL6180x_GetCachedWord(dev, index, pValue) VL6180x_RdWord(dev, index, pValue)
+#   define VL6180x_GetCachedDWord(dev, index, pValue) VL6180x_RdDWord(dev, index, pValue)
+#endif /* VL6180x_CACHED_REG */
+
+
+
+int VL6180x_RangeGetMeasurement(VL6180xDev_t dev, VL6180x_RangeData_t *pRangeData)
+{
+	int status;
+	uint16_t RawRate;
+	uint8_t RawStatus;
+
+	LOG_FUNCTION_START("");
+
+	status = _CachedRegs_Fetch(dev);
+	if (status) {
+		VL6180x_ErrLog("Cache register read fail");
+		goto error;
+	}
+	status = VL6180x_RangeGetResult(dev, &pRangeData->range_mm);
+	if (!status) {
+		status = VL6180x_GetCachedWord(dev, RESULT_RANGE_SIGNAL_RATE, &RawRate);
+		if (!status) {
+			pRangeData->signalRate_mcps = VL6180x_9to7Conv(RawRate);
+			status = VL6180x_GetCachedByte(dev, RESULT_RANGE_STATUS, &RawStatus);
+			if (!status) {
+				pRangeData->errorStatus = RawStatus >> 4;
+			} else {
+				VL6180x_ErrLog("Rd RESULT_RANGE_STATUS fail");
+			}
+	#if VL6180x_WRAP_AROUND_FILTER_SUPPORT || VL6180x_HAVE_DMAX_RANGING
+			status = _GetRateResult(dev, pRangeData);
+			if (status)
+				goto error;
+	#endif
+	#if VL6180x_WRAP_AROUND_FILTER_SUPPORT
+			/* if enabled run filter */
+			if (_IsWrapArroundActive(dev)) {
+				status = _filter_GetResult(dev, pRangeData);
+				if (!status) {
+					/* patch the range status and measure if it is filtered */
+					if(pRangeData->FilteredData.filterError != NoError) {
+						pRangeData->errorStatus = pRangeData->FilteredData.filterError;
+						pRangeData->range_mm = pRangeData->FilteredData.range_mm;
+					}
+				}
+			}
+	#endif
+
+	#if VL6180x_HAVE_DMAX_RANGING
+			if (_IsDMaxActive(dev)) {
+				_DMax_Compute(dev, pRangeData);
+			}
+	#endif
+		} else {
+		    VL6180x_ErrLog("Rd RESULT_RANGE_SIGNAL_RATE fail");
+		}
+	} else {
+		VL6180x_ErrLog("VL6180x_GetRangeResult fail");
+	}
+error:
+	_CachedRegs_Flush(dev);
+	LOG_FUNCTION_END_FMT(status, "%d %d %d", (int)pRangeData->range_mm, (int)pRangeData->signalRate_mcps,  (int)pRangeData->errorStatus) ;
+	return status;
+}
+
+
+int VL6180x_RangeGetMeasurementIfReady(VL6180xDev_t dev, VL6180x_RangeData_t *pRangeData)
+{
+	int status;
+	IntrStatus_t IntStatus;
+
+	LOG_FUNCTION_START();
+	status = VL6180x_RangeGetInterruptStatus(dev, &IntStatus.val);
+	if (status == 0) {
+		if (IntStatus.status.Range == RES_INT_STAT_GPIO_NEW_SAMPLE_READY ||
+			IntStatus.status.Error != 0) {
+			status = VL6180x_RangeGetMeasurement(dev, pRangeData);
+			if (status == 0) {
+				/*  clear range interrupt source */
+				status = VL6180x_RangeClearInterrupt(dev);
+				if (status) {
+					VL6180x_ErrLog("VL6180x_RangeClearInterrupt fail");
+				}
+			}
+		} else {
+			pRangeData->errorStatus = DataNotReady;
+		}
+	} else {
+		VL6180x_ErrLog("fail to get interrupt status");
+	}
+	LOG_FUNCTION_END(status) ;
+	return status;
+}
+
+int VL6180x_FilterSetState(VL6180xDev_t dev, int state)
+{
+	int status;
+	LOG_FUNCTION_START("%d", state);
+	#if VL6180x_WRAP_AROUND_FILTER_SUPPORT
+	VL6180xDevDataSet(dev, WrapAroundFilterActive, state);
+	status = 0;
+	#else
+	status =  NOT_SUPPORTED;
+	#endif
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+int VL6180x_FilterGetState(VL6180xDev_t dev)
+{
+	int status;
+	LOG_FUNCTION_START("");
+	#if VL6180x_WRAP_AROUND_FILTER_SUPPORT
+	status = VL6180xDevDataGet(dev, WrapAroundFilterActive);
+	#else
+	status = 0;
+	#endif
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+int VL6180x_RangeGetResult(VL6180xDev_t dev, int32_t *pRange_mm)
+{
+	int status;
+	uint8_t RawRange;
+	int32_t Upscale;
+
+	LOG_FUNCTION_START("%p", pRange_mm);
+
+	status = VL6180x_GetCachedByte(dev, RESULT_RANGE_VAL, &RawRange);
+	if (!status) {
+		Upscale = _GetUpscale(dev);
+		*pRange_mm = Upscale * (int32_t)RawRange;
+	}
+	LOG_FUNCTION_END_FMT(status, "%d", (int)*pRange_mm);
+	return status;
+}
+
+int VL6180x_RangeSetRawThresholds(VL6180xDev_t dev, uint8_t low, uint8_t high)
+{
+	int status;
+	LOG_FUNCTION_START("%d %d", (int) low, (int)high);
+	/* TODO we can optimize here grouping high/low in a word but that's cpu endianness dependent */
+	status = VL6180x_WrByte(dev, SYSRANGE_THRESH_HIGH, high);
+	if (!status) {
+		status = VL6180x_WrByte(dev, SYSRANGE_THRESH_LOW, low);
+	}
+
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+int VL6180x_RangeSetThresholds(VL6180xDev_t dev, uint16_t low, uint16_t high, int UseSafeParamHold)
+{
+	int status;
+	int scale;
+	LOG_FUNCTION_START("%d %d", (int) low, (int)high);
+	scale = _GetUpscale(dev, UpscaleFactor);
+	if (low > scale * 255 || high > scale * 255) {
+		status = INVALID_PARAMS;
+	} else {
+		do {
+			if (UseSafeParamHold) {
+				status = VL6180x_SetGroupParamHold(dev, 1);
+				if (status)
+					break;
+		    }
+		    status = VL6180x_RangeSetRawThresholds(dev, (uint8_t)(low / scale), (uint8_t)(high / scale));
+		    if (status) {
+				VL6180x_ErrLog("VL6180x_RangeSetRawThresholds fail");
+		    }
+		    if (UseSafeParamHold) {
+				int HoldStatus;
+				/* tryt to unset param hold vene if previous fail */
+				HoldStatus = VL6180x_SetGroupParamHold(dev, 0);
+				if (!status)
+					status = HoldStatus;
+		    }
+		} while (0);
+	}
+
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+
+int VL6180x_RangeGetThresholds(VL6180xDev_t dev, uint16_t *low, uint16_t *high)
+{
+	int status = 0;
+	uint8_t RawLow, RawHigh;
+	int scale;
+
+	LOG_FUNCTION_START("%p %p", low , high);
+
+	scale = _GetUpscale(dev, UpscaleFactor);
+	do {
+		if (high != NULL) {
+			status = VL6180x_RdByte(dev, SYSRANGE_THRESH_HIGH, &RawHigh);
+			if (status) {
+				VL6180x_ErrLog("rd SYSRANGE_THRESH_HIGH fail");
+				break;
+			}
+			*high = (uint16_t)RawHigh * scale;
+		}
+		if (low != NULL) {
+		    status = VL6180x_RdByte(dev, SYSRANGE_THRESH_LOW, &RawLow);
+			if (status) {
+				VL6180x_ErrLog("rd SYSRANGE_THRESH_LOW fail");
+				break;
+		    }
+		    *low = (uint16_t)RawLow * scale;
+		}
+	} while (0);
+	LOG_FUNCTION_END_FMT(status, "%d %d", (int)*low , (int)*high);
+	return status;
+}
+
+
+int VL6180x_RangeGetInterruptStatus(VL6180xDev_t dev, uint8_t *pIntStatus)
+{
+	int status;
+	uint8_t IntStatus;
+	LOG_FUNCTION_START("%p", pIntStatus);
+	/* FIXME we are grouping "error" with over status the user must check implicitly for it
+	 * not just new sample or over status , that will nevr show up in case of error*/
+	status = VL6180x_GetCachedByte(dev, RESULT_INTERRUPT_STATUS_GPIO, &IntStatus);
+	*pIntStatus = IntStatus & 0xC7;
+
+	LOG_FUNCTION_END_FMT(status, "%d", (int)*pIntStatus);
+	return status;
+}
+
+
+int VL6180x_GetInterruptStatus(VL6180xDev_t dev, uint8_t *IntStatus)
+{
+	int status;
+	LOG_FUNCTION_START("%p" , IntStatus);
+	status = VL6180x_RdByte(dev, RESULT_INTERRUPT_STATUS_GPIO, IntStatus);
+	LOG_FUNCTION_END_FMT(status, "%d", (int)*IntStatus);
+	return status;
+}
+
+int VL6180x_ClearInterrupt(VL6180xDev_t dev, uint8_t IntClear)
+{
+	int status;
+	LOG_FUNCTION_START("%d", (int)IntClear);
+	if (IntClear <= 7) {
+		status = VL6180x_WrByte(dev, SYSTEM_INTERRUPT_CLEAR, IntClear);
+	} else {
+		status = INVALID_PARAMS;
+	}
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+
+static int VL6180x_RangeStaticInit(VL6180xDev_t dev)
+{
+	int status;
+	LOG_FUNCTION_START("");
+
+	/* REGISTER_TUNING_SR03_270514_CustomerView.txt */
+	VL6180x_WrByte(dev, 0x0207, 0x01);
+	VL6180x_WrByte(dev, 0x0208, 0x01);
+	VL6180x_WrByte(dev, 0x0096, 0x00);
+	VL6180x_WrByte(dev, 0x0097, 0xfd);
+	VL6180x_WrByte(dev, 0x00e3, 0x01);
+	VL6180x_WrByte(dev, 0x00e4, 0x03);
+	VL6180x_WrByte(dev, 0x00e5, 0x02);
+	VL6180x_WrByte(dev, 0x00e6, 0x01);
+	VL6180x_WrByte(dev, 0x00e7, 0x03);
+	VL6180x_WrByte(dev, 0x00f5, 0x02);
+	VL6180x_WrByte(dev, 0x00d9, 0x05);
+	VL6180x_WrByte(dev, 0x00db, 0xce);
+	VL6180x_WrByte(dev, 0x00dc, 0x03);
+	VL6180x_WrByte(dev, 0x00dd, 0xf8);
+	VL6180x_WrByte(dev, 0x009f, 0x00);
+	VL6180x_WrByte(dev, 0x00a3, 0x3c);
+	VL6180x_WrByte(dev, 0x00b7, 0x00);
+	VL6180x_WrByte(dev, 0x00bb, 0x3c); /*Recommended value = 0x28 in case very fast ranging frequency (~ 100 Hz)*/
+	VL6180x_WrByte(dev, 0x00b2, 0x09);
+	VL6180x_WrByte(dev, 0x00ca, 0x09);
+	VL6180x_WrByte(dev, 0x0198, 0x01);
+	VL6180x_WrByte(dev, 0x01b0, 0x17);
+	VL6180x_WrByte(dev, 0x01ad, 0x00);
+	VL6180x_WrByte(dev, 0x00ff, 0x05);
+	VL6180x_WrByte(dev, 0x0100, 0x05);
+	VL6180x_WrByte(dev, 0x0199, 0x05);
+	VL6180x_WrByte(dev, 0x01a6, 0x1b);
+	VL6180x_WrByte(dev, 0x01ac, 0x3e);
+	VL6180x_WrByte(dev, 0x01a7, 0x1f);
+	VL6180x_WrByte(dev, 0x0030, 0x00);
+
+	/* Recommended : Public registers - See data sheet for more detail */
+	VL6180x_WrByte(dev, 0x0011, 0x10); /* Enables polling for New Sample ready when measurement completes */
+	VL6180x_WrByte(dev, 0x010a, 0x30); /* Set the averaging sample period (compromise between lower noise and increased execution time) */
+	VL6180x_WrByte(dev, 0x003f, 0x46); /* Sets the light and dark gain (upper nibble). Dark gain should not be changed.*/
+	VL6180x_WrByte(dev, 0x0031, 0xFF); /* sets the # of range measurements after which auto calibration of system is performed */
+	VL6180x_WrByte(dev, 0x0040, 0x63); /* Set ALS integration time to 100ms */
+	VL6180x_WrByte(dev, 0x002e, 0x01); /* perform a single temperature calibration of the ranging sensor */
+
+	/* Optional: Public registers - See data sheet for more detail */
+	VL6180x_WrByte(dev, 0x001b, 0x09); /* Set default ranging inter-measurement period to 100ms */
+	VL6180x_WrByte(dev, 0x003e, 0x31); /* Set default ALS inter-measurement period to 500ms */
+	VL6180x_WrByte(dev, 0x0014, 0x24); /* Configures interrupt on New sample ready */
+
+
+	status = VL6180x_RangeSetMaxConvergenceTime(dev, 50); /*  Calculate ece value on initialization (use max conv) */
+	LOG_FUNCTION_END(status);
+
+	return status;
+}
+
+#if VL6180x_UPSCALE_SUPPORT != 1
+
+static int _UpscaleInitPatch0(VL6180xDev_t dev)
+{
+	int status;
+	uint32_t CalValue = 0;
+	CalValue = VL6180xDevDataGet(dev, Part2PartAmbNVM);
+	status = VL6180x_WrDWord(dev, 0xDA, CalValue);
+	return status;
+}
+
+/* only include up-scaling register setting when up-scale support is configured in */
+int VL6180x_UpscaleRegInit(VL6180xDev_t dev)
+{
+	/*  apply REGISTER_TUNING_ER02_100614_CustomerView.txt */
+	VL6180x_WrByte(dev, 0x0207, 0x01);
+	VL6180x_WrByte(dev, 0x0208, 0x01);
+	VL6180x_WrByte(dev, 0x0096, 0x00);
+	VL6180x_WrByte(dev, 0x0097, 0x54);
+	VL6180x_WrByte(dev, 0x00e3, 0x00);
+	VL6180x_WrByte(dev, 0x00e4, 0x04);
+	VL6180x_WrByte(dev, 0x00e5, 0x02);
+	VL6180x_WrByte(dev, 0x00e6, 0x01);
+	VL6180x_WrByte(dev, 0x00e7, 0x03);
+	VL6180x_WrByte(dev, 0x00f5, 0x02);
+	VL6180x_WrByte(dev, 0x00d9, 0x05);
+
+	_UpscaleInitPatch0(dev);
+
+	VL6180x_WrByte(dev, 0x009f, 0x00);
+	VL6180x_WrByte(dev, 0x00a3, 0x28);
+	VL6180x_WrByte(dev, 0x00b7, 0x00);
+	VL6180x_WrByte(dev, 0x00bb, 0x28);
+	VL6180x_WrByte(dev, 0x00b2, 0x09);
+	VL6180x_WrByte(dev, 0x00ca, 0x09);
+	VL6180x_WrByte(dev, 0x0198, 0x01);
+	VL6180x_WrByte(dev, 0x01b0, 0x17);
+	VL6180x_WrByte(dev, 0x01ad, 0x00);
+	VL6180x_WrByte(dev, 0x00ff, 0x05);
+	VL6180x_WrByte(dev, 0x0100, 0x05);
+	VL6180x_WrByte(dev, 0x0199, 0x05);
+	VL6180x_WrByte(dev, 0x01a6, 0x1b);
+	VL6180x_WrByte(dev, 0x01ac, 0x3e);
+	VL6180x_WrByte(dev, 0x01a7, 0x1f);
+	VL6180x_WrByte(dev, 0x0030, 0x00);
+	VL6180x_WrByte(dev, 0x0011, 0x10);
+	VL6180x_WrByte(dev, 0x010a, 0x30);
+	VL6180x_WrByte(dev, 0x003f, 0x46);
+	VL6180x_WrByte(dev, 0x0031, 0xFF);
+	VL6180x_WrByte(dev, 0x0040, 0x63);
+	VL6180x_WrByte(dev, 0x002e, 0x01);
+	VL6180x_WrByte(dev, 0x002c, 0xff);
+	VL6180x_WrByte(dev, 0x001b, 0x09);
+	VL6180x_WrByte(dev, 0x003e, 0x31);
+	VL6180x_WrByte(dev, 0x0014, 0x24);
+#if VL6180x_EXTENDED_RANGE
+	VL6180x_RangeSetMaxConvergenceTime(dev, 63);
+#else
+	VL6180x_RangeSetMaxConvergenceTime(dev, 50);
+#endif
+	return 0;
+}
+#else
+#define VL6180x_UpscaleRegInit(...) -1
+#endif
+
+int VL6180x_UpscaleSetScaling(VL6180xDev_t dev, uint8_t scaling)
+{
+	int status;
+	uint16_t Scaler;
+	uint16_t ValidHeight;
+	int8_t  Offset;
+
+	LOG_FUNCTION_START("%d", (int)scaling);
+
+#ifdef VL6180x_HAVE_UPSCALE_DATA
+	#define min_scaling 1
+	#define max_scaling (sizeof(ScalerLookUP) / sizeof(ScalerLookUP[0]))
+#else
+	/* we are in fixed config so only allow configured factor */
+	#define min_scaling VL6180x_UPSCALE_SUPPORT
+	#define max_scaling VL6180x_UPSCALE_SUPPORT
+#endif
+
+	if (scaling >= min_scaling  && scaling <= max_scaling) {
+
+		Scaler = ScalerLookUP[scaling - 1];
+		status = VL6180x_WrWord(dev, RANGE_SCALER, Scaler);
+		_SetUpscale(dev, scaling);
+
+		/* Apply scaling on  part-2-part offset */
+		Offset = VL6180xDevDataGet(dev, Part2PartOffsetNVM) / scaling;
+		status = VL6180x_WrByte(dev, SYSRANGE_PART_TO_PART_RANGE_OFFSET, Offset);
+
+		/* Apply scaling on CrossTalkValidHeight */
+		if (status == 0) {
+			status = VL6180x_WrByte(dev, SYSRANGE_CROSSTALK_VALID_HEIGHT,
+									DEF_CROSS_TALK_VALID_HEIGHT_VALUE /  scaling);
+		}
+		/* Apply scaling on RangeIgnore ValidHeight if enabled */
+		if( status == 0){
+			if(  VL6180xDevDataGet(dev, RangeIgnore.Enabled) !=0 ){
+				ValidHeight = VL6180xDevDataGet(dev, RangeIgnore.ValidHeight);
+				ValidHeight  /= _GetUpscale(dev);
+				if( ValidHeight > 255 )
+					ValidHeight = 255;
+
+				status = VL6180x_WrByte(dev, SYSRANGE_RANGE_IGNORE_VALID_HEIGHT,
+							ValidHeight );
+			}
+		}
+
+#if !VL6180x_EXTENDED_RANGE
+		if (status == 0) {
+			status = VL6180x_RangeSetEceState(dev, scaling == 1); /* enable ece only at 1x scaling */
+		}
+		if (status == 0 && !VL6180x_EXTENDED_RANGE && scaling != 1) {
+			status = NOT_GUARANTEED ;
+		}
+#endif
+	} else {
+		status = INVALID_PARAMS;
+	}
+#undef min_scaling
+#undef max_scaling
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+
+int VL6180x_UpscaleGetScaling(VL6180xDev_t dev)
+{
+	int status;
+	LOG_FUNCTION_START("");
+	status = _GetUpscale(dev);
+	LOG_FUNCTION_END(status);
+
+	return status;
+}
+
+
+static int  VL6180x_UpscaleStaticInit(VL6180xDev_t dev)
+{
+	/* todo make these a fail macro in case only 1x is suppoted */
+	int status;
+
+	LOG_FUNCTION_START("");
+	do {
+		status = VL6180x_UpscaleRegInit(dev);
+		if (status) {
+			VL6180x_ErrLog("regInit fail");
+			break;
+		}
+#if VL6180x_EXTENDED_RANGE
+		status = VL6180x_RangeSetEceState(dev, 0);
+		if (status) {
+			VL6180x_ErrLog("VL6180x_RangeSetEceState fail");
+			break;
+		}
+#endif
+	} while (0);
+	if (!status) {
+		/*  must write the scaler at least once to the device to ensure the scaler is in a known state. */
+		status = VL6180x_UpscaleSetScaling(dev, _GetUpscale(dev));
+		VL6180x_WrByte(dev, 0x016, 0x00); /* change fresh out of set status to 0 */
+	}
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+
+int VL6180x_SetGPIOxPolarity(VL6180xDev_t dev, int pin, int active_high)
+{
+	int status;
+	LOG_FUNCTION_START("%d %d", (int) pin, (int)active_high);
+
+	if (pin == 0  || pin == 1) {
+		uint16_t RegIndex;
+		uint8_t  DataSet;
+		if (pin == 0)
+			RegIndex = SYSTEM_MODE_GPIO0;
+		else
+			RegIndex = SYSTEM_MODE_GPIO1;
+
+		if (active_high)
+		   DataSet = GPIOx_POLARITY_SELECT_MASK;
+		else
+		   DataSet = 0;
+
+		status = VL6180x_UpdateByte(dev, RegIndex, (uint8_t)~GPIOx_POLARITY_SELECT_MASK, DataSet);
+	} else {
+		VL6180x_ErrLog("Invalid pin param %d", (int)pin);
+		status = INVALID_PARAMS;
+	}
+
+	LOG_FUNCTION_END(status);
+
+	return status;
+}
+
+int VL6180x_SetGPIOxFunctionality(VL6180xDev_t dev, int pin, uint8_t functionality)
+{
+	int status;
+
+	LOG_FUNCTION_START("%d %d", (int) pin, (int)functionality);
+
+	if (((pin == 0)  || (pin == 1))  && IsValidGPIOFunction(functionality)) {
+		uint16_t RegIndex;
+
+		if (pin == 0)
+			RegIndex = SYSTEM_MODE_GPIO0;
+		else
+			RegIndex = SYSTEM_MODE_GPIO1;
+
+		status = VL6180x_UpdateByte(dev, RegIndex, (uint8_t)~GPIOx_FUNCTIONALITY_SELECT_MASK,
+									functionality << GPIOx_FUNCTIONALITY_SELECT_SHIFT);
+		if (status) {
+			VL6180x_ErrLog("Update SYSTEM_MODE_GPIO%d fail", (int)pin);
+		}
+	} else {
+		VL6180x_ErrLog("Invalid pin %d  or function %d", (int)pin, (int)functionality);
+		status = INVALID_PARAMS;
+	}
+
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+
+int VL6180x_SetupGPIOx(VL6180xDev_t dev, int pin,  uint8_t IntFunction, int  ActiveHigh)
+{
+	int status;
+
+	LOG_FUNCTION_START("%d %d", (int) pin, (int)IntFunction);
+
+	if (((pin == 0) || (pin == 1))  && IsValidGPIOFunction(IntFunction)) {
+		uint16_t RegIndex;
+		uint8_t value = 0;
+
+		if (pin == 0)
+		   RegIndex = SYSTEM_MODE_GPIO0;
+		else
+		   RegIndex = SYSTEM_MODE_GPIO1;
+
+		if (ActiveHigh)
+		   value |= GPIOx_POLARITY_SELECT_MASK;
+
+		value |=  IntFunction << GPIOx_FUNCTIONALITY_SELECT_SHIFT;
+		status = VL6180x_WrByte(dev, RegIndex, value);
+		if (status) {
+		   VL6180x_ErrLog("SYSTEM_MODE_GPIO%d wr fail", (int)pin-SYSTEM_MODE_GPIO0);
+		}
+	} else {
+		VL6180x_ErrLog("Invalid pin %d or function %d", (int)pin, (int) IntFunction);
+		status = INVALID_PARAMS;
+	}
+
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+
+int VL6180x_DisableGPIOxOut(VL6180xDev_t dev, int pin)
+{
+	int status;
+
+	LOG_FUNCTION_START("%d", (int)pin);
+
+	status = VL6180x_SetGPIOxFunctionality(dev, pin, GPIOx_SELECT_OFF);
+
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+
+int VL6180x_SetupGPIO1(VL6180xDev_t dev, uint8_t IntFunction, int ActiveHigh)
+{
+	int status;
+	LOG_FUNCTION_START("%d %d", (int)IntFunction, (int)ActiveHigh);
+	status = VL6180x_SetupGPIOx(dev, 1, IntFunction, ActiveHigh);
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+int VL6180x_RangeConfigInterrupt(VL6180xDev_t dev, uint8_t ConfigGpioInt)
+{
+	int status;
+
+	if (ConfigGpioInt <= CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY) {
+		status = VL6180x_UpdateByte(dev, SYSTEM_INTERRUPT_CONFIG_GPIO,
+									(uint8_t)(~CONFIG_GPIO_RANGE_MASK),
+									ConfigGpioInt);
+	} else {
+		VL6180x_ErrLog("Invalid config mode param %d", (int)ConfigGpioInt);
+		status = INVALID_PARAMS;
+	}
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+
+int VL6180x_RangeSetEceFactor(VL6180xDev_t dev, uint16_t  FactorM, uint16_t FactorD)
+{
+	int status;
+	uint8_t u8;
+
+	LOG_FUNCTION_START("%d %d", (int)FactorM, (int)FactorD);
+	do {
+		/* D cannot be 0 M must be <=D and >= 0 */
+		if (FactorM <= FactorD  && FactorD > 0) {
+			VL6180xDevDataSet(dev, EceFactorM, FactorM);
+			VL6180xDevDataSet(dev, EceFactorD, FactorD);
+			/* read and re-apply max conv time to get new ece factor set */
+			status = VL6180x_RdByte(dev, SYSRANGE_MAX_CONVERGENCE_TIME, &u8);
+			if (status) {
+			   VL6180x_ErrLog("SYSRANGE_MAX_CONVERGENCE_TIME rd fail ");
+			   break;
+			}
+			status = VL6180x_RangeSetMaxConvergenceTime(dev, u8);
+			if (status < 0) {
+				VL6180x_ErrLog("fail to apply time after ece m/d change");
+				break;
+			}
+		} else {
+			VL6180x_ErrLog("invalid factor %d/%d", (int)FactorM, (int)FactorD);
+			status = INVALID_PARAMS;
+		}
+	} while (0);
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+int VL6180x_RangeSetEceState(VL6180xDev_t dev, int enable)
+{
+	int status;
+	uint8_t or_mask;
+
+	LOG_FUNCTION_START("%d", (int)enable);
+	if (enable)
+		or_mask = RANGE_CHECK_ECE_ENABLE_MASK;
+	else
+		or_mask = 0;
+
+	status = VL6180x_UpdateByte(dev, SYSRANGE_RANGE_CHECK_ENABLES, ~RANGE_CHECK_ECE_ENABLE_MASK, or_mask);
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+
+int VL6180x_RangeSetMaxConvergenceTime(VL6180xDev_t dev, uint8_t  MaxConTime_msec)
+{
+	int status = 0;
+	LOG_FUNCTION_START("%d", (int)MaxConTime_msec);
+	do {
+		status = VL6180x_WrByte(dev, SYSRANGE_MAX_CONVERGENCE_TIME, MaxConTime_msec);
+		if (status) {
+			break;
+		}
+		status = VL6180x_RangeSetEarlyConvergenceEestimateThreshold(dev);
+		if (status) {
+			break;
+		}
+		status = _DMax_InitData(dev);
+	} while (0);
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+int VL6180x_RangeSetInterMeasPeriod(VL6180xDev_t dev, uint32_t  InterMeasTime_msec)
+{
+	uint8_t SetTime;
+	int status;
+
+	LOG_FUNCTION_START("%d", (int)InterMeasTime_msec);
+	do {
+		if (InterMeasTime_msec > 2550) {
+			status = INVALID_PARAMS;
+			break;
+		}
+		/* doc in not 100% clear and confusing about the limit practically all value are OK but 0
+		 * that can hang device in continuous mode */
+		if (InterMeasTime_msec < 10) {
+			InterMeasTime_msec = 10;
+		}
+		SetTime = (uint8_t)(InterMeasTime_msec / 10);
+		status = VL6180x_WrByte(dev, SYSRANGE_INTERMEASUREMENT_PERIOD, SetTime);
+		if (status) {
+			VL6180x_ErrLog("SYSRANGE_INTERMEASUREMENT_PERIOD wr fail");
+		} else if (SetTime != InterMeasTime_msec / 10) {
+			status = MIN_CLIPED;  /* on success change status to clip if it did */
+		}
+	} while (0);
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+
+int VL6180x_RangeGetDeviceReady(VL6180xDev_t dev, int *Ready)
+{
+	int status;
+	uint8_t u8;
+	LOG_FUNCTION_START("%p", (int)Ready);
+	status = VL6180x_RdByte(dev, RESULT_RANGE_STATUS, &u8);
+	if (!status)
+		*Ready = u8&RANGE_DEVICE_READY_MASK;
+	LOG_FUNCTION_END_FMT(status, "%d", *Ready);
+	return status;
+}
+
+
+int VL6180x_RangeWaitDeviceReady(VL6180xDev_t dev, int MaxLoop)
+{
+	int status = 0; /* if user specify an invalid <=0 loop count we'll return error */
+	int  n;
+	uint8_t u8;
+	LOG_FUNCTION_START("%d", (int)MaxLoop);
+	if (MaxLoop < 1) {
+		status = INVALID_PARAMS;
+	} else {
+		for (n = 0; n < MaxLoop ; n++) {
+			status = VL6180x_RdByte(dev, RESULT_RANGE_STATUS, &u8);
+			if (status)
+				break;
+			u8 = u8 & RANGE_DEVICE_READY_MASK;
+			if (u8)
+				break;
+
+		}
+		if (!status && !u8) {
+			status = TIME_OUT;
+		}
+	}
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+int VL6180x_RangeSetSystemMode(VL6180xDev_t dev, uint8_t  mode)
+{
+	int status;
+	LOG_FUNCTION_START("%d", (int)mode);
+	/* FIXME we are not checking device is ready via @a VL6180x_RangeWaitDeviceReady
+	 * so if called back to back real fast we are not checking
+	 * if previous mode "set" got absorbed => bit 0 must be 0 so that it work
+	 */
+	if (mode <= 3) {
+		status = VL6180x_WrByte(dev, SYSRANGE_START, mode);
+		if (status) {
+		    VL6180x_ErrLog("SYSRANGE_START wr fail");
+		}
+	} else {
+		status = INVALID_PARAMS;
+	}
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+
+int VL6180x_RangeStartContinuousMode(VL6180xDev_t dev)
+{
+	int status;
+	LOG_FUNCTION_START("");
+	status = VL6180x_RangeSetSystemMode(dev, MODE_START_STOP | MODE_CONTINUOUS);
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+int VL6180x_RangeStartSingleShot(VL6180xDev_t dev)
+{
+	int status;
+	LOG_FUNCTION_START("");
+	status = VL6180x_RangeSetSystemMode(dev, MODE_START_STOP | MODE_SINGLESHOT);
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+
+static int VL6180x_RangeSetEarlyConvergenceEestimateThreshold(VL6180xDev_t dev)
+{
+	int status;
+
+	const uint32_t cMicroSecPerMilliSec  = 1000;
+	const uint32_t cEceSampleTime_us     = 500;
+	uint32_t ece_factor_m          = VL6180xDevDataGet(dev, EceFactorM);
+	uint32_t ece_factor_d          = VL6180xDevDataGet(dev, EceFactorD);
+	uint32_t convergTime_us;
+	uint32_t fineThresh;
+	uint32_t eceThresh;
+	uint8_t  u8;
+	uint32_t maxConv_ms;
+	int32_t AveTime;
+
+	LOG_FUNCTION_START("");
+
+	do {
+		status = VL6180x_RdByte(dev, SYSRANGE_MAX_CONVERGENCE_TIME, &u8);
+		if (status) {
+			VL6180x_ErrLog("SYSRANGE_MAX_CONVERGENCE_TIME rd fail");
+			break;
+		}
+		maxConv_ms = u8;
+		AveTime = _GetAveTotalTime(dev);
+		if (AveTime < 0) {
+			status = -1;
+			break;
+		}
+
+		convergTime_us = maxConv_ms * cMicroSecPerMilliSec - AveTime;
+		status = VL6180x_RdDWord(dev, 0xB8, &fineThresh);
+		if (status) {
+			VL6180x_ErrLog("reg 0xB8 rd fail");
+			break;
+		}
+		fineThresh *= 256;
+		eceThresh = ece_factor_m * cEceSampleTime_us * fineThresh / (convergTime_us * ece_factor_d);
+
+		status = VL6180x_WrWord(dev, SYSRANGE_EARLY_CONVERGENCE_ESTIMATE, (uint16_t)eceThresh);
+	} while (0);
+
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+
+static int _RangeIgnore_UpdateDevice(VL6180xDev_t dev){
+	int status;
+	int enable;
+	int threshold;
+	int range;
+	int or_mask;
+	enable= VL6180xDevDataGet(dev, RangeIgnore.Enabled);
+	if( enable ){
+		// if to be nabled program first range value and threshold
+		range = VL6180xDevDataGet(dev, RangeIgnore.ValidHeight);
+		range /= _GetUpscale(dev);
+		if( range > 255 )
+			range = 255;
+
+		status = VL6180x_WrByte(dev, SYSRANGE_RANGE_IGNORE_VALID_HEIGHT,  range);
+		if( status ){
+			goto done;
+		}
+
+		threshold = VL6180xDevDataGet(dev, RangeIgnore.IgnoreThreshold);
+		status = VL6180x_WrWord(dev, SYSRANGE_RANGE_IGNORE_THRESHOLD,  threshold);
+		if( status ){
+			goto done;
+		}
+		or_mask = RANGE_CHECK_RANGE_ENABLE_MASK;
+	}
+	else{
+		or_mask = 0;
+	}
+	status = VL6180x_UpdateByte(dev, SYSRANGE_RANGE_CHECK_ENABLES, ~RANGE_CHECK_RANGE_ENABLE_MASK, or_mask);
+	_DMax_InitData(dev);
+done:
+	return status;
+}
+
+int VL6180x_RangeIgnoreSetEnable(VL6180xDev_t dev, int EnableState){
+	int CurEnable;
+	int status;
+	LOG_FUNCTION_START("enable %d", EnableState);
+
+	if( EnableState )
+		EnableState = 1;
+
+	CurEnable = VL6180xDevDataGet(dev, RangeIgnore.Enabled);
+	if( EnableState != CurEnable  ){
+		VL6180xDevDataSet(dev, RangeIgnore.Enabled, EnableState);
+		status = _RangeIgnore_UpdateDevice(dev);
+	}
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+int VL6180x_RangeIgnoreConfigure(VL6180xDev_t dev, uint16_t ValidHeight_mm, uint16_t IgnoreThreshold){
+	int status;
+	int enabled;
+
+	LOG_FUNCTION_START("height= %d Threshold=%d", (int)ValidHeight_mm, (int)Threshold);
+
+	enabled = VL6180xDevDataGet(dev, RangeIgnore.Enabled);
+	VL6180xDevDataSet(dev, RangeIgnore.ValidHeight, ValidHeight_mm);
+	VL6180xDevDataSet(dev, RangeIgnore.IgnoreThreshold, IgnoreThreshold);
+	if(  enabled ){
+		status = _RangeIgnore_UpdateDevice(dev);
+	}
+	else{
+		status = 0;
+	}
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+/*
+ * Return >0 = time
+ *       <0 1 if fail to get read data from device to compute time
+ */
+static int32_t _GetAveTotalTime(VL6180xDev_t dev)
+{
+	uint32_t cFwOverhead_us = 24;
+	uint32_t cVcpSetupTime_us = 70;
+	uint32_t cPLL2_StartupDelay_us = 200;
+	uint8_t cMeasMask = 0x07;
+	uint32_t Samples;
+	uint32_t SamplePeriod;
+	uint32_t SingleTime_us;
+	int32_t TotalAveTime_us;
+	uint8_t u8;
+	int status;
+
+	LOG_FUNCTION_START("");
+
+	status = VL6180x_RdByte(dev, 0x109, &u8);
+	if (status) {
+		VL6180x_ErrLog("rd 0x109 fail");
+		return -1;
+	}
+	Samples = u8 & cMeasMask;
+	status = VL6180x_RdByte(dev, READOUT_AVERAGING_SAMPLE_PERIOD, &u8);
+	if (status) {
+		VL6180x_ErrLog("i2c READOUT_AVERAGING_SAMPLE_PERIOD fail");
+		return -1;
+	}
+	SamplePeriod = u8;
+	SingleTime_us = cFwOverhead_us + cVcpSetupTime_us + (SamplePeriod * 10);
+	TotalAveTime_us = (Samples + 1) * SingleTime_us + cPLL2_StartupDelay_us;
+
+	LOG_FUNCTION_END(TotalAveTime_us);
+	return TotalAveTime_us;
+}
+
+#if VL6180x_HAVE_DMAX_RANGING
+#define _GetDMaxDataRetSignalAt400mm(dev) VL6180xDevDataGet(dev, DMaxData.retSignalAt400mm)
+#else
+#define _GetDMaxDataRetSignalAt400mm(dev) 375 /* Use a default high value */
+#endif
+
+
+#if VL6180x_WRAP_AROUND_FILTER_SUPPORT
+
+#define PRESERVE_DEVICE_ERROR_CODE		/* If uncommented, device error code will be preserved on top of wraparound error code, but this may lead to some error code instability like overflow error <==> RangingFilteringOnGoing error oscillations */
+#define SENSITIVE_FILTERING_ON_GOING	/* If uncommented, filter will go back to RangingFilteringOnGoing if it must go through the std dev testing */
+
+#define FILTER_STDDEV_SAMPLES           6
+#define MIN_FILTER_STDDEV_SAMPLES       3
+#define MIN_FILTER_STDDEV_SAMPLES_AFTER_FLUSH_OR_BYPASS 5
+#define STDDEV_BASE_VALUE               150
+
+#define FILTER_INVALID_DISTANCE     65535
+
+#define _FilterData(field) VL6180xDevDataGet(dev, FilterData.field)
+/*
+ * One time init
+ */
+int _filter_Init(VL6180xDev_t dev)
+{
+	int i;
+	_FilterData(MeasurementIndex) = 0;
+
+	_FilterData(Default_ZeroVal) = 0;
+	_FilterData(Default_VAVGVal) = 0;
+	_FilterData(NoDelay_ZeroVal) = 0;
+	_FilterData(NoDelay_VAVGVal) = 0;
+	_FilterData(Previous_VAVGDiff) = 0;
+
+	_FilterData(StdFilteredReads) = 0;
+	_FilterData(FilteringOnGoingConsecutiveStates) = 0;
+
+	for (i = 0; i < FILTER_NBOF_SAMPLES; i++) {
+		_FilterData(LastTrueRange)[i] = FILTER_INVALID_DISTANCE;
+		_FilterData(LastReturnRates)[i] = 0;
+	}
+	_FilterData(MeasurementsSinceLastFlush)=0;
+	return 0;
+}
+
+
+static uint32_t _filter_StdDevDamper(uint32_t AmbientRate,
+									uint32_t SignalRate,
+									const uint32_t StdDevLimitLowLight,
+									const uint32_t StdDevLimitLowLightSNR,
+									const uint32_t StdDevLimitHighLight,
+									const uint32_t StdDevLimitHighLightSNR)
+{
+	uint32_t newStdDev;
+	uint16_t SNR;
+
+	if (AmbientRate > 0)
+		SNR = (uint16_t) ((100 * SignalRate) / AmbientRate);
+	else
+		SNR = 9999;
+
+	if (SNR >= StdDevLimitLowLightSNR) {
+		newStdDev = StdDevLimitLowLight;
+	} else {
+		if (SNR <= StdDevLimitHighLightSNR)
+			newStdDev = StdDevLimitHighLight;
+		else {
+			newStdDev = (uint32_t)(StdDevLimitHighLight -
+									(SNR - StdDevLimitHighLightSNR) *
+									(StdDevLimitHighLight - StdDevLimitLowLight) /
+									(StdDevLimitLowLightSNR - StdDevLimitHighLightSNR));
+		}
+	}
+
+	return newStdDev;
+}
+
+
+/*
+ * Return <0 on error
+ */
+static int32_t _filter_Start(VL6180xDev_t dev,
+								uint16_t m_trueRange_mm,
+								uint16_t m_rawRange_mm,
+								uint32_t m_rtnSignalRate,
+								uint32_t m_rtnAmbientRate,
+								uint16_t errorCode)
+{
+	int status;
+	uint16_t m_newTrueRange_mm = 0;
+	#if VL6180x_HAVE_MULTI_READ
+	uint8_t MultiReadBuf[8];
+	#endif
+	uint16_t i;
+	uint16_t bypassFilter = 0;
+	uint16_t resetVAVGData = 1;
+
+	uint16_t filterErrorCode = NoError;
+	uint16_t filterErrorCodeOnRangingErrorCode = NoError;
+
+	uint16_t registerValue;
+
+	uint32_t register32BitsValue1;
+	uint32_t register32BitsValue2;
+
+	uint16_t ValidDistance = 0;
+	uint16_t SuspicuousRangingZone = 0;
+
+	uint16_t WrapAroundFlag = 0;
+	uint16_t NoWrapAroundFlag = 0;
+	uint16_t NoWrapAroundHighConfidenceFlag = 0;
+
+	uint16_t FlushFilter = 0;
+	uint32_t RateChange = 0;
+
+	uint16_t StdDevSamplesMinNeeded = 0;
+	uint16_t StdDevSamples = 0;
+	uint32_t StdDevDistanceSum = 0;
+	uint32_t StdDevDistanceMean = 0;
+	uint32_t StdDevDistance = 0;
+	uint32_t StdDevRateSum = 0;
+	uint32_t StdDevRateMean = 0;
+	uint32_t StdDevRate = 0;
+	uint32_t StdDevLimitWithTargetMove = 0;
+
+	uint32_t VAVGDiff;
+	uint32_t IdealVAVGDiff;
+	uint32_t MinVAVGDiff;
+	uint32_t MaxVAVGDiff;
+
+	/* Filter Parameters */
+	static const uint16_t ROMABLE_DATA WrapAroundLowRawRangeLimit = 60;
+	static const uint32_t ROMABLE_DATA WrapAroundLowReturnRateLimit_ROM = 800;
+	/* Shall be adapted depending on crossTalk */
+	static const uint16_t ROMABLE_DATA WrapAroundLowRawRangeLimit2 = 165;
+	static const uint32_t ROMABLE_DATA WrapAroundLowReturnRateLimit2_ROM = 180;
+	/* Shall be adapted depending on crossTalk and device sensitivity*/
+	static const uint32_t ROMABLE_DATA WrapAroundLowRawRangeLimit2SuspicuousAddedSignalRate = 150;
+
+
+	static const uint32_t ROMABLE_DATA WrapAroundLowReturnRateFilterLimit_ROM = 850;
+	/* Shall be adapted depending on crossTalk and device sensitivity*/
+	static const uint16_t ROMABLE_DATA WrapAroundHighRawRangeFilterLimit = 350;
+	static const uint32_t ROMABLE_DATA WrapAroundHighReturnRateFilterLimit_ROM = 1400;
+	/* Shall be adapted depending on crossTalk and device sensitivity*/
+
+	static const uint32_t ROMABLE_DATA WrapAroundMaximumAmbientRateFilterLimit = 15000;
+
+	/*  Temporal filter data and flush values */
+	static const uint32_t ROMABLE_DATA MinReturnRateFilterFlush = 75;
+	static const uint32_t ROMABLE_DATA MaxReturnRateChangeFilterFlush = 50;
+
+	/* STDDEV values and damper values */
+	static const uint32_t ROMABLE_DATA StdDevLimitLowLight = STDDEV_BASE_VALUE;
+	static const uint32_t ROMABLE_DATA StdDevLimitLowLightSNR = 30; /* 0.3 */
+	static const uint32_t ROMABLE_DATA StdDevLimitHighLight = STDDEV_BASE_VALUE*6;
+	static const uint32_t ROMABLE_DATA StdDevLimitHighLightSNR = 5; /* 0.05 */
+
+	static const uint32_t ROMABLE_DATA StdDevHighConfidenceSNRLimit = 8;
+	static const uint32_t ROMABLE_DATA StdDevNoWrapDetectedMultiplier = 4;
+
+	static const uint32_t ROMABLE_DATA StdDevMovingTargetStdDevLimit = 90000;
+
+	static const uint32_t ROMABLE_DATA StdDevMovingTargetReturnRateLimit = 3500;
+	static const uint32_t ROMABLE_DATA StdDevMovingTargetStdDevForReturnRateLimit = STDDEV_BASE_VALUE*25;
+
+	static const uint32_t ROMABLE_DATA MAX_VAVGDiff_ROM = 1800;
+	static const uint32_t ROMABLE_DATA SuspicuousMAX_VAVGDiffRatio = 2;
+
+	/* WrapAroundDetection variables */
+	static const uint16_t ROMABLE_DATA WrapAroundNoDelayCheckPeriod = 2;
+	static const uint16_t ROMABLE_DATA StdFilteredReadsIncrement = 2;
+	static const uint16_t ROMABLE_DATA StdFilteredReadsDecrement = 1;
+	static const uint16_t ROMABLE_DATA StdMaxFilteredReads = 4;
+
+	uint32_t SignalRateDMax;
+	uint32_t WrapAroundLowReturnRateLimit;
+	uint32_t WrapAroundLowReturnRateLimit2;
+	uint32_t WrapAroundLowReturnRateFilterLimit;
+	uint32_t WrapAroundHighReturnRateFilterLimit;
+
+	uint32_t MAX_VAVGDiff = 1800;
+
+	uint8_t u8;//, u8_2;
+	uint32_t XTalkCompRate_KCps;
+	uint32_t StdDevLimit = 300;
+	uint32_t MaxOrInvalidDistance =   255*_GetUpscale(dev);
+	/* #define MaxOrInvalidDistance  (uint16_t) (255 * 3) */
+
+	/* Check if distance is Valid or not */
+	switch (errorCode) {
+	case Raw_Ranging_Algo_Underflow:
+	case Ranging_Algo_Underflow:
+		filterErrorCodeOnRangingErrorCode = RangingFiltered; /* If we have to go through filter, mean we have here a wraparound case */
+		ValidDistance = 0;
+		break;
+	case Raw_Ranging_Algo_Overflow:
+	case Ranging_Algo_Overflow:
+		filterErrorCodeOnRangingErrorCode = RangingFiltered; /* If we have to go through filter, mean we have here a wraparound case */
+		//m_trueRange_mm = MaxOrInvalidDistance;
+		m_trueRange_mm = 200*_GetUpscale(dev);
+		ValidDistance = 1;
+		break;
+	default:
+		if (m_rawRange_mm >= MaxOrInvalidDistance) {
+			ValidDistance = 0;
+			bypassFilter = 1; /* Bypass the filter in this case as produced distance is not usable (and also the VAVGVal and ZeroVal values) */
+		} else {
+			ValidDistance = 1;
+		}
+		break;
+	}
+	m_newTrueRange_mm = m_trueRange_mm;
+
+	XTalkCompRate_KCps = VL6180xDevDataGet(dev, XTalkCompRate_KCps);
+
+	/* Update signal rate limits depending on crosstalk */
+	SignalRateDMax = (uint32_t)_GetDMaxDataRetSignalAt400mm(dev) ;
+	WrapAroundLowReturnRateLimit = WrapAroundLowReturnRateLimit_ROM  + XTalkCompRate_KCps;
+	WrapAroundLowReturnRateLimit2 = ((WrapAroundLowReturnRateLimit2_ROM *
+									SignalRateDMax) / 312) +
+									XTalkCompRate_KCps;
+	WrapAroundLowReturnRateFilterLimit = ((WrapAroundLowReturnRateFilterLimit_ROM *
+									SignalRateDMax) / 312) + XTalkCompRate_KCps;
+	WrapAroundHighReturnRateFilterLimit = ((WrapAroundHighReturnRateFilterLimit_ROM *
+									SignalRateDMax) / 312) + XTalkCompRate_KCps;
+
+
+	/* Checks on low range data */
+	if ((m_rawRange_mm < WrapAroundLowRawRangeLimit) && (m_rtnSignalRate < WrapAroundLowReturnRateLimit)) {
+		filterErrorCode = RangingFiltered; /* On this condition, wraparound case is ensured */
+		bypassFilter = 1;
+	}
+	if ((m_rawRange_mm < WrapAroundLowRawRangeLimit2) && (m_rtnSignalRate < WrapAroundLowReturnRateLimit2)) {
+		filterErrorCode = RangingFiltered; /* On this condition, wraparound case is ensured */
+		bypassFilter = 1;
+	}
+	if ((m_rawRange_mm < WrapAroundLowRawRangeLimit2) && (m_rtnSignalRate < (WrapAroundLowReturnRateLimit2 + WrapAroundLowRawRangeLimit2SuspicuousAddedSignalRate))) {
+		SuspicuousRangingZone = 1; /* On this area, we are in an highly suspicuous wraparound ares, filter parameter will be stengthen */
+	}
+
+
+	/* Checks on Ambient rate level */
+	if (m_rtnAmbientRate > WrapAroundMaximumAmbientRateFilterLimit) {
+		/* Too high ambient rate */
+		FlushFilter = 1;
+		bypassFilter = 1;
+	}
+    
+	/*  Checks on Filter flush */
+	if (m_rtnSignalRate < MinReturnRateFilterFlush) {
+		/* Completely lost target, so flush the filter */
+		FlushFilter = 1;
+		bypassFilter = 1;
+	}
+	if (_FilterData(LastReturnRates)[0] != 0) {
+		if (m_rtnSignalRate > _FilterData(LastReturnRates)[0])
+			RateChange = (100 *
+						(m_rtnSignalRate - _FilterData(LastReturnRates)[0])) /
+						_FilterData(LastReturnRates)[0];
+		else
+			RateChange = (100 *
+						(_FilterData(LastReturnRates)[0] - m_rtnSignalRate)) /
+						_FilterData(LastReturnRates)[0];
+	} else
+		RateChange = 0;
+	if (RateChange > MaxReturnRateChangeFilterFlush) {
+		FlushFilter = 1;
+	}
+	/* TODO optimize filter  using circular buffer */
+	if (FlushFilter == 1) {
+		_FilterData(MeasurementIndex) = 0;
+		for (i = 0; i < FILTER_NBOF_SAMPLES; i++) {
+			_FilterData(LastTrueRange)[i] = FILTER_INVALID_DISTANCE;
+			_FilterData(LastReturnRates)[i] = 0;
+		}
+		_FilterData(MeasurementsSinceLastFlush)=0;
+	} else {
+		for (i = (uint16_t) (FILTER_NBOF_SAMPLES - 1); i > 0; i--) {
+			_FilterData(LastTrueRange)[i] = _FilterData(LastTrueRange)[i - 1];
+			_FilterData(LastReturnRates)[i] = _FilterData(LastReturnRates)[i - 1];
+		}
+	}
+
+	if (ValidDistance == 1)
+		_FilterData(LastTrueRange)[0] = m_trueRange_mm;
+	else
+		_FilterData(LastTrueRange)[0] = FILTER_INVALID_DISTANCE;
+	_FilterData(LastReturnRates)[0] = m_rtnSignalRate;
+	_FilterData(MeasurementsSinceLastFlush)++;
+
+	/* Check if we need to go through the filter or not */
+	if (!(((m_rawRange_mm < WrapAroundHighRawRangeFilterLimit) &&
+		(m_rtnSignalRate < WrapAroundLowReturnRateFilterLimit)) ||
+		((m_rawRange_mm >= WrapAroundHighRawRangeFilterLimit) &&
+		(m_rtnSignalRate < WrapAroundHighReturnRateFilterLimit))))
+		bypassFilter = 1;
+	else {
+		/* if some wraparound filtering due to some ranging error code has been detected, update the filter status and bypass the filter */
+		if(filterErrorCodeOnRangingErrorCode!=NoError){
+#ifndef PRESERVE_DEVICE_ERROR_CODE
+			filterErrorCode = filterErrorCodeOnRangingErrorCode;
+#else
+			if((errorCode==Raw_Ranging_Algo_Underflow) || (errorCode==Ranging_Algo_Underflow)) {
+				/* Preserves the error codes except for Raw_Ranging_Algo_Underflow and Ranging_Algo_Underflow */
+				filterErrorCode = filterErrorCodeOnRangingErrorCode;
+			}
+#endif
+			bypassFilter = 1;
+			resetVAVGData = 0;
+		}
+	}
+
+	/* Check which kind of measurement has been made */
+	status = VL6180x_RdByte(dev, 0x01AC, &u8);
+	if (status) {
+		VL6180x_ErrLog("0x01AC rd fail");
+		goto done_err;
+	}
+	registerValue = u8;
+
+	/* Read data for filtering */
+#if VL6180x_HAVE_MULTI_READ
+	status = VL6180x_RdMulti(dev, 0x10C, MultiReadBuf, 8); /* read only 8 lsb bits */
+	if (status) {
+		VL6180x_ErrLog("0x10C multi rd fail");
+		goto done_err;
+	}
+	register32BitsValue1 = ((uint32_t) MultiReadBuf[0] << 24)
+			+ ((uint32_t) MultiReadBuf[1] << 16)
+			+ ((uint32_t) MultiReadBuf[2] << 8)
+			+ ((uint32_t) MultiReadBuf[3] << 0);
+	register32BitsValue2 = ((uint32_t) MultiReadBuf[4] << 24)
+			+ ((uint32_t) MultiReadBuf[5] << 16)
+			+ ((uint32_t) MultiReadBuf[6] << 8)
+			+ ((uint32_t) MultiReadBuf[7] << 0);
+#else
+	status = VL6180x_RdDWord(dev, 0x10C, &register32BitsValue1); /* read 32 bits, lower 17 bits are the one useful */
+	if (status) {
+		VL6180x_ErrLog("0x010C rd fail");
+		goto done_err;
+	}
+	status = VL6180x_RdDWord(dev, 0x0110, &	register32BitsValue2); /* read 32 bits, lower 17 bits are the one useful */
+	if (status) {
+		VL6180x_ErrLog("0x0110 rd fail");
+		goto done_err;
+	}
+#endif
+
+
+	if ((FlushFilter == 1) || ((bypassFilter == 1) && (resetVAVGData == 1))) {
+		if (registerValue != 0x3E) {
+			status = VL6180x_WrByte(dev, 0x1AC, 0x3E);
+			if (status) {
+				VL6180x_ErrLog("0x01AC bypass wr fail");
+				goto done_err;
+			}
+			//status = VL6180x_WrByte(dev, 0x0F2, 0x01);
+			//if (status) {
+			//	VL6180x_ErrLog("0x0F2 bypass wr fail");
+			//	goto done_err;
+			//}
+		}
+		/* Set both Default and NoDelay To same value */
+		_FilterData(Default_ZeroVal) = register32BitsValue1;
+		_FilterData(Default_VAVGVal) = register32BitsValue2;
+		_FilterData(NoDelay_ZeroVal) = register32BitsValue1;
+		_FilterData(NoDelay_VAVGVal) = register32BitsValue2;
+
+		_FilterData(MeasurementIndex) = 0;
+	} else {
+		if (registerValue == 0x3E) {
+			_FilterData(Default_ZeroVal) = register32BitsValue1;
+			_FilterData(Default_VAVGVal) = register32BitsValue2;
+		} else {
+			_FilterData(NoDelay_ZeroVal) = register32BitsValue1;
+			_FilterData(NoDelay_VAVGVal) = register32BitsValue2;
+		}
+
+		if (_FilterData(MeasurementIndex) % WrapAroundNoDelayCheckPeriod == 0) {
+			u8 = 0x3C;
+			//u8_2 = 0x05;
+		} else {
+			u8 = 0x3E;
+			//u8_2 = 0x01;
+		}
+		status = VL6180x_WrByte(dev, 0x01AC, u8);
+		if (status) {
+			VL6180x_ErrLog("0x01AC wr fail");
+			goto done_err;
+		}
+		//status = VL6180x_WrByte(dev, 0x0F2, u8_2);
+		//if (status) {
+		//	VL6180x_ErrLog("0x0F2  wr fail");
+		//	goto done_err;
+		//}
+		_FilterData(MeasurementIndex)++;
+	}
+
+	if (bypassFilter == 1) {
+		/* Do not go through the filter */
+
+		/* Update filter error code */
+		_FilterData(filterError) = filterErrorCode;
+
+		/* Update reported range */
+		if(filterErrorCode==RangingFiltered)
+			m_newTrueRange_mm = MaxOrInvalidDistance; /* Set to invalid distance */
+
+		return m_newTrueRange_mm;
+	}
+
+	/* Computes current VAVGDiff */
+	if (_FilterData(Default_VAVGVal) > _FilterData(NoDelay_VAVGVal))
+		VAVGDiff = _FilterData(Default_VAVGVal) - _FilterData(NoDelay_VAVGVal);
+	else
+		VAVGDiff = 0;
+	_FilterData(Previous_VAVGDiff) = VAVGDiff;
+
+	if(SuspicuousRangingZone==0)
+		MAX_VAVGDiff = MAX_VAVGDiff_ROM;
+	else
+		/* In suspicuous area, strengthen the filter */
+		MAX_VAVGDiff = MAX_VAVGDiff_ROM / SuspicuousMAX_VAVGDiffRatio;
+
+	/* Check the VAVGDiff */
+	if (_FilterData(Default_ZeroVal) > _FilterData(NoDelay_ZeroVal))
+		IdealVAVGDiff = _FilterData(Default_ZeroVal) - _FilterData(NoDelay_ZeroVal);
+	else
+		IdealVAVGDiff = _FilterData(NoDelay_ZeroVal) - _FilterData(Default_ZeroVal);
+	if (IdealVAVGDiff > MAX_VAVGDiff)
+		MinVAVGDiff = IdealVAVGDiff - MAX_VAVGDiff;
+	else
+		MinVAVGDiff = 0;
+	MaxVAVGDiff = IdealVAVGDiff + MAX_VAVGDiff;
+	if (VAVGDiff < MinVAVGDiff || VAVGDiff > MaxVAVGDiff) {
+		WrapAroundFlag = 1;
+		filterErrorCode = RangingFiltered;
+	} else {
+		/* Go through filtering check */
+
+		if(_FilterData(MeasurementIndex)<=1)
+			/* On measurement after a bypass, uses an increase number of samples */
+			StdDevSamplesMinNeeded = MIN_FILTER_STDDEV_SAMPLES_AFTER_FLUSH_OR_BYPASS;
+		else
+			StdDevSamplesMinNeeded = MIN_FILTER_STDDEV_SAMPLES;
+
+		/* StdDevLimit Damper on SNR */
+		StdDevLimit = _filter_StdDevDamper(m_rtnAmbientRate, m_rtnSignalRate, StdDevLimitLowLight, StdDevLimitLowLightSNR, StdDevLimitHighLight, StdDevLimitHighLightSNR);
+
+		/* Standard deviations computations */
+		StdDevSamples = 0;
+		StdDevDistanceSum = 0;
+		StdDevDistanceMean = 0;
+		StdDevDistance = 0;
+		StdDevRateSum = 0;
+		StdDevRateMean = 0;
+		StdDevRate = 0;
+		for (i = 0; (i < FILTER_NBOF_SAMPLES) && (StdDevSamples < FILTER_STDDEV_SAMPLES); i++) {
+			if (_FilterData(LastTrueRange)[i] != FILTER_INVALID_DISTANCE) {
+				StdDevSamples = (uint16_t) (StdDevSamples + 1);
+				StdDevDistanceSum = (uint32_t) (StdDevDistanceSum + _FilterData(LastTrueRange)[i]);
+				StdDevRateSum = (uint32_t) (StdDevRateSum + _FilterData(LastReturnRates)[i]);
+			}
+		}
+		if (StdDevSamples > 0) {
+			StdDevDistanceMean = (uint32_t) (StdDevDistanceSum / StdDevSamples);
+			StdDevRateMean = (uint32_t) (StdDevRateSum / StdDevSamples);
+		}
+		/* TODO optimize shorten Std dev in aisngle loop computation using sum of x2 - (sum of x)2 */
+		StdDevSamples = 0;
+		StdDevDistanceSum = 0;
+		StdDevRateSum = 0;
+		for (i = 0; (i < FILTER_NBOF_SAMPLES) && (StdDevSamples < FILTER_STDDEV_SAMPLES); i++) {
+			if (_FilterData(LastTrueRange)[i] != FILTER_INVALID_DISTANCE) {
+				StdDevSamples = (uint16_t) (StdDevSamples + 1);
+				StdDevDistanceSum = (uint32_t) (StdDevDistanceSum +
+									(int)(_FilterData(LastTrueRange)[i] -
+											StdDevDistanceMean) *
+											(int) (_FilterData(LastTrueRange)[i] -
+													StdDevDistanceMean));
+				StdDevRateSum = (uint32_t) (StdDevRateSum +
+									(int) (_FilterData(LastReturnRates)[i] -
+											StdDevRateMean) *
+											(int) (_FilterData(LastReturnRates)[i] -
+													StdDevRateMean));
+			}
+		}
+		if (StdDevSamples >= StdDevSamplesMinNeeded) {
+			StdDevDistance = (uint16_t) (StdDevDistanceSum / StdDevSamples);
+			StdDevRate = (uint16_t) (StdDevRateSum / StdDevSamples);
+		} else {
+			StdDevDistance = 0;
+			StdDevRate = 0;
+		}
+
+		/* Check Return rate standard deviation */
+		if (StdDevRate < StdDevMovingTargetStdDevLimit) {
+			if (StdDevSamples < StdDevSamplesMinNeeded) {
+				//m_newTrueRange_mm = MaxOrInvalidDistance;
+				filterErrorCode = RangingFiltered;
+			} else {
+				/* Check distance standard deviation */
+				if (StdDevRate < StdDevMovingTargetReturnRateLimit)
+					StdDevLimitWithTargetMove = StdDevLimit +
+						(((StdDevMovingTargetStdDevForReturnRateLimit -
+							StdDevLimit) * StdDevRate) /
+							StdDevMovingTargetReturnRateLimit);
+				else
+					StdDevLimitWithTargetMove = StdDevMovingTargetStdDevForReturnRateLimit;
+
+				if(_FilterData(filterError)==NoError){
+					/* No wrapAround detected yet, so relax constraints on the std dev */
+					StdDevLimitWithTargetMove = StdDevLimitWithTargetMove * StdDevNoWrapDetectedMultiplier;
+				}
+
+				if (((StdDevDistance * StdDevHighConfidenceSNRLimit) < StdDevLimit) && (StdDevSamples>=FILTER_STDDEV_SAMPLES)) {
+					NoWrapAroundHighConfidenceFlag = 1;
+				} else {
+					if (StdDevDistance < StdDevLimitWithTargetMove) {
+							NoWrapAroundFlag = 1;
+						} else {
+						WrapAroundFlag = 1;
+						filterErrorCode = RangingFiltered;
+					}
+				}
+			}
+		} else {
+			/* Target moving too fast */
+			WrapAroundFlag = 1;
+			filterErrorCode = RangingFiltered;
+		}
+	}
+
+	if (ValidDistance == 0) {
+		/* In case of invalid distance */
+		if (_FilterData(StdFilteredReads) > 0)
+			_FilterData(StdFilteredReads) = (uint16_t) (_FilterData(StdFilteredReads) - 1);
+	} else {
+		if (WrapAroundFlag == 1) {
+			_FilterData(StdFilteredReads) = (uint16_t) (_FilterData(StdFilteredReads) +
+											StdFilteredReadsIncrement);
+			if (_FilterData(StdFilteredReads) > StdMaxFilteredReads)
+				_FilterData(StdFilteredReads) = StdMaxFilteredReads;
+		} else {
+			if (NoWrapAroundFlag == 1) {
+				if (_FilterData(StdFilteredReads) > 0) {
+					filterErrorCode = RangingFiltered;
+					if (_FilterData(StdFilteredReads) > StdFilteredReadsDecrement)
+						_FilterData(StdFilteredReads) = (uint16_t) (_FilterData(StdFilteredReads) -
+														StdFilteredReadsDecrement);
+					else
+						_FilterData(StdFilteredReads) = 0;
+				}
+			} else {
+				if (NoWrapAroundHighConfidenceFlag == 1) {
+					_FilterData(StdFilteredReads) = 0;
+				}
+			}
+		}
+	}
+
+	/* If we detect a change from no Error to RangingFilteringOnGoing, then it means that
+	 * the filter detected a change in te scene, so discard all previous measurements.
+	 */
+	if((_FilterData(filterError) == NoError) && (filterErrorCode!=NoError)) {
+		for (i = 1; i < FILTER_NBOF_SAMPLES; i++) {
+			_FilterData(LastTrueRange)[i] = FILTER_INVALID_DISTANCE;
+			_FilterData(LastReturnRates)[i] = 0;
+		}
+	}
+
+	/* Update filter error code */
+	_FilterData(filterError) = filterErrorCode;
+
+	/* Update reported range */
+	if(filterErrorCode==RangingFiltered)
+		m_newTrueRange_mm = MaxOrInvalidDistance; /* Set to invalid distance */
+
+	return m_newTrueRange_mm;
+done_err:
+	return -1;
+
+#undef MaxOrInvalidDistance
+}
+
+
+static int _filter_GetResult(VL6180xDev_t dev, VL6180x_RangeData_t *pRangeData)
+{
+	uint32_t m_rawRange_mm = 0;
+	int32_t  FilteredRange;
+	const uint8_t scaler = _GetUpscale(dev);
+	uint8_t u8;
+	int status;
+
+	do {
+		status = VL6180x_GetCachedByte(dev, RESULT_RANGE_RAW, &u8);
+		if (status) {
+		    VL6180x_ErrLog("RESULT_RANGE_RAW rd fail");
+		    break;
+		}
+		m_rawRange_mm = u8;
+
+		FilteredRange = _filter_Start(dev, pRangeData->range_mm, (m_rawRange_mm * scaler), pRangeData->rtnRate, pRangeData->rtnAmbRate, pRangeData->errorStatus);
+		if (FilteredRange < 0) {
+		    status = -1;
+		    break;
+		}
+		pRangeData->FilteredData.range_mm = FilteredRange;
+		pRangeData->FilteredData.rawRange_mm = m_rawRange_mm * scaler;
+		pRangeData->FilteredData.filterError= _FilterData(filterError);
+	} while (0);
+	return status;
+}
+
+#undef _FilterData
+#ifdef PRESERVE_DEVICE_ERROR_CODE
+#undef PRESERVE_DEVICE_ERROR_CODE
+#endif
+#ifdef SENSITIVE_FILTERING_ON_GOING
+#undef SENSITIVE_FILTERING_ON_GOING
+#endif
+#undef FILTER_STDDEV_SAMPLES
+#undef MIN_FILTER_STDDEV_SAMPLES
+#undef MIN_FILTER_STDDEV_SAMPLES_AFTER_FLUSH_OR_BYPASS
+#undef STDDEV_BASE_VALUE
+#undef FILTER_INVALID_DISTANCE
+
+#endif /* VL6180x_WRAP_AROUND_FILTER_SUPPORT */
+
+#ifdef VL6180x_HAVE_RATE_DATA
+
+static int _GetRateResult(VL6180xDev_t dev, VL6180x_RangeData_t *pRangeData)
+{
+	uint32_t m_rtnConvTime = 0;
+	uint32_t m_rtnSignalRate = 0;
+	uint32_t m_rtnAmbientRate = 0;
+	uint32_t m_rtnSignalCount = 0;
+	uint32_t m_rtnAmbientCount = 0;
+	uint32_t m_refConvTime = 0;
+	uint32_t cRtnSignalCountMax = 0x7FFFFFFF;
+	uint32_t cDllPeriods = 6;
+	uint32_t calcConvTime = 0;
+
+	int status;
+
+	do {
+		status = VL6180x_GetCachedDWord(dev, RESULT_RANGE_RETURN_SIGNAL_COUNT, &m_rtnSignalCount);
+		if (status) {
+			VL6180x_ErrLog("RESULT_RANGE_RETURN_SIGNAL_COUNT rd fail");
+			break;
+		}
+		if (m_rtnSignalCount > cRtnSignalCountMax) {
+			m_rtnSignalCount = 0;
+		}
+
+		status = VL6180x_GetCachedDWord(dev, RESULT_RANGE_RETURN_AMB_COUNT, &m_rtnAmbientCount);
+		if (status) {
+			VL6180x_ErrLog("RESULT_RANGE_RETURN_AMB_COUNTrd fail");
+			break;
+		}
+
+
+		status = VL6180x_GetCachedDWord(dev, RESULT_RANGE_RETURN_CONV_TIME, &m_rtnConvTime);
+		if (status) {
+			VL6180x_ErrLog("RESULT_RANGE_RETURN_CONV_TIME rd fail");
+			break;
+		}
+
+		status = VL6180x_GetCachedDWord(dev, RESULT_RANGE_REFERENCE_CONV_TIME, &m_refConvTime);
+		if (status) {
+			VL6180x_ErrLog("RESULT_RANGE_REFERENCE_CONV_TIME rd fail");
+			break;
+		}
+
+		pRangeData->rtnConvTime = m_rtnConvTime;
+		pRangeData->refConvTime = m_refConvTime;
+
+		calcConvTime = m_refConvTime;
+		if (m_rtnConvTime > m_refConvTime) {
+			calcConvTime = m_rtnConvTime;
+		}
+		if (calcConvTime == 0)
+			calcConvTime = 63000;
+
+		m_rtnSignalRate = (m_rtnSignalCount * 1000) / calcConvTime;
+		m_rtnAmbientRate = (m_rtnAmbientCount * cDllPeriods * 1000) / calcConvTime;
+
+		pRangeData->rtnRate = m_rtnSignalRate;
+		pRangeData->rtnAmbRate = m_rtnAmbientRate;
+
+
+	} while (0);
+	return status;
+}
+#endif /* VL6180x_HAVE_RATE_DATA */
+
+
+int VL6180x_DMaxSetState(VL6180xDev_t dev, int state)
+{
+	int status;
+	LOG_FUNCTION_START("%d", state);
+#if VL6180x_HAVE_DMAX_RANGING
+	VL6180xDevDataSet(dev, DMaxEnable, state);
+	if (state) {
+		status = _DMax_InitData(dev);
+	} else {
+		status = 0;
+	}
+#else
+	status =  NOT_SUPPORTED;
+#endif
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+int VL6180x_DMaxGetState(VL6180xDev_t dev)
+{
+	int status;
+	LOG_FUNCTION_START("");
+#if VL6180x_HAVE_DMAX_RANGING
+	status = VL6180xDevDataGet(dev, DMaxEnable);
+#else
+	status = 0;
+#endif
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+
+#if VL6180x_HAVE_DMAX_RANGING
+
+#define _DMaxData(field) VL6180xDevDataGet(dev, DMaxData.field)
+/*
+ * Convert fix point  x.7 to KCpount per sec
+ */
+
+#ifndef VL6180x_PLATFORM_PROVIDE_SQRT
+
+/*
+ * 32 bit integer square root with not so bad precision (integer result) and is quite fast
+ * see http://en.wikipedia.org/wiki/Methods_of_computing_square_roots
+ */
+uint32_t VL6180x_SqrtUint32(uint32_t num)
+{
+	uint32_t res = 0;
+	uint32_t bit = 1 << 30; /* The second-to-top bit is set: 1 << 30 for 32 bits */
+
+	/* "bit" starts at the highest power of four <= the argument. */
+	while (bit > num)
+		bit >>= 2;
+
+	while (bit != 0) {
+		if (num >= res + bit) {
+		    num -= res + bit;
+		    res = (res >> 1) + bit;
+		} else
+		    res >>= 1;
+		bit >>= 2;
+	}
+	return res;
+}
+#endif
+
+
+/* DMax one time init */
+void _DMax_OneTimeInit(VL6180xDev_t dev)
+{
+	_DMaxData(ambTuningWindowFactor_K) = DEF_AMBIENT_TUNING;
+}
+
+
+static uint32_t _DMax_RawValueAtRateKCps(VL6180xDev_t dev, int32_t rate)
+{
+	uint32_t snrLimit_K;
+	int32_t DMaxSq;
+	uint32_t RawDMax;
+	DMaxFix_t retSignalAt400mm;
+	uint32_t ambTuningWindowFactor_K;
+
+
+	ambTuningWindowFactor_K = _DMaxData(ambTuningWindowFactor_K);
+	snrLimit_K              = _DMaxData(snrLimit_K);
+	retSignalAt400mm        = _DMaxData(retSignalAt400mm);
+	/* 12 to 18 bits Kcps */
+	if (rate > 0) {
+		DMaxSq = 400 * 400 * 1000 / rate - (400 * 400 / 330);
+		/* K of (1/RtnAmb -1/330 )=> 30bit- (12-18)bit  => 12-18 bits*/
+		if (DMaxSq <= 0) {
+		    RawDMax = 0;
+		} else {
+		    /* value can be more 32 bit so base on raneg apply
+			 * retSignalAt400mm before or after division to presevr accuracy */
+		    if (DMaxSq < (2 << 12)) {
+				DMaxSq = DMaxSq * retSignalAt400mm /
+							(snrLimit_K + ambTuningWindowFactor_K);
+				/* max 12 + 12 to 18 -10 => 12-26 bit */
+		    } else {
+				DMaxSq = DMaxSq / (snrLimit_K + ambTuningWindowFactor_K) * retSignalAt400mm;
+				/* 12 to 18 -10 + 12 to 18 *=> 12-26 bit */
+		    }
+		    RawDMax = VL6180x_SqrtUint32(DMaxSq);
+		}
+	} else {
+		RawDMax = 0x7FFFFFFF; /* bigest possibmle 32bit signed value */
+	}
+	return RawDMax;
+}
+
+/*
+ * fetch static data from register to avoid re-read
+ * precompute all intermediate constant and cliipings
+ *
+ * to be re-used/call on  changes of :
+ *  0x2A
+ *  SYSRANGE_MAX_AMBIENT_LEVEL_MULT
+ *  Dev Data XtalkComRate_KCPs
+ *  SYSRANGE_MAX_CONVERGENCE_TIME
+ *  SYSRANGE_RANGE_CHECK_ENABLES    mask RANGE_CHECK_RANGE_ENABLE_MASK
+ *  range 0xb8-0xbb (0xbb)
+ */
+static int _DMax_InitData(VL6180xDev_t dev)
+{
+	int status, warning;
+	uint8_t u8;
+	uint16_t u16;
+	uint32_t u32;
+	uint32_t Reg2A_KCps;
+	uint32_t RegB8;
+	uint8_t  MaxConvTime;
+	uint32_t XTalkCompRate_KCps;
+	uint32_t RangeIgnoreThreshold;
+	int32_t minSignalNeeded;
+	uint8_t SysRangeCheckEn;
+	uint8_t snrLimit;
+	static const int ROMABLE_DATA MaxConvTimeAdjust = -4;
+
+	warning = 0;
+
+	LOG_FUNCTION_START("");
+	do {
+		status = VL6180x_RdByte(dev, 0x02A, &u8);
+		if (status) {
+		    VL6180x_ErrLog("Reg 0x02A rd fail");
+		    break;
+		}
+
+		if (u8 == 0) {
+		    warning = CALIBRATION_WARNING;
+		    u8 = 40; /* use a default average value */
+		}
+		Reg2A_KCps = Fix7_2_KCPs(u8); /* convert to KCPs */
+
+		status = VL6180x_RdByte(dev, SYSRANGE_RANGE_CHECK_ENABLES, &SysRangeCheckEn);
+		if (status) {
+		    VL6180x_ErrLog("SYSRANGE_RANGE_CHECK_ENABLES rd fail ");
+		    break;
+		}
+
+		status = VL6180x_RdByte(dev, SYSRANGE_MAX_CONVERGENCE_TIME, &MaxConvTime);
+		if (status) {
+		    VL6180x_ErrLog("SYSRANGE_MAX_CONVERGENCE_TIME rd fail ");
+			break;
+		}
+
+		status = VL6180x_RdDWord(dev, 0x0B8, &RegB8);
+		if (status) {
+		    VL6180x_ErrLog("reg 0x0B8 rd fail ");
+		    break;
+		}
+
+		status = VL6180x_RdByte(dev, SYSRANGE_MAX_AMBIENT_LEVEL_MULT, &snrLimit);
+		if (status) {
+		    VL6180x_ErrLog("SYSRANGE_MAX_AMBIENT_LEVEL_MULT rd fail ");
+		    break;
+		}
+		_DMaxData(snrLimit_K) = (int32_t)16 * 1000 / snrLimit;
+		XTalkCompRate_KCps =   VL6180xDevDataGet(dev, XTalkCompRate_KCps);
+
+		if (Reg2A_KCps >= XTalkCompRate_KCps) {
+		    _DMaxData(retSignalAt400mm) = Reg2A_KCps;
+		} else{
+		    _DMaxData(retSignalAt400mm) = 0;
+			/* Reg2A_K - XTalkCompRate_KCp <0 is invalid */
+		}
+
+		/* if xtalk range check is off omit it in snr clipping */
+		if (SysRangeCheckEn&RANGE_CHECK_RANGE_ENABLE_MASK) {
+		    status = VL6180x_RdWord(dev, SYSRANGE_RANGE_IGNORE_THRESHOLD, &u16);
+		    if (status) {
+				VL6180x_ErrLog("SYSRANGE_RANGE_IGNORE_THRESHOLD rd fail ");
+				break;
+		    }
+		    RangeIgnoreThreshold = Fix7_2_KCPs(u16);
+		} else{
+		    RangeIgnoreThreshold  = 0;
+		}
+
+		minSignalNeeded = (RegB8 * 256) / ((int32_t)MaxConvTime + (int32_t)MaxConvTimeAdjust);
+		/* KCps 8+8 bit -(1 to 6 bit) => 15-10 bit */
+		/* minSignalNeeded = max ( minSignalNeeded,  RangeIgnoreThreshold - XTalkCompRate_KCps) */
+		if (minSignalNeeded  <= (int32_t)RangeIgnoreThreshold - (int32_t)XTalkCompRate_KCps)
+		    minSignalNeeded  =  RangeIgnoreThreshold - XTalkCompRate_KCps;
+
+		u32 = (minSignalNeeded*(uint32_t)snrLimit) / 16;
+		_DMaxData(ClipSnrLimit) = _DMax_RawValueAtRateKCps(dev, u32);
+		/* clip to dmax to min signal snr limit rate*/
+	} while (0);
+	if (!status)
+		status = warning;
+	LOG_FUNCTION_END(status);
+	return status;
+}
+
+static int _DMax_Compute(VL6180xDev_t dev, VL6180x_RangeData_t *pRange)
+{
+	uint32_t rtnAmbRate;
+	int32_t DMax;
+	int scaling;
+	uint16_t HwLimitAtScale;
+	static const int ROMABLE_DATA rtnAmbLowLimit_KCps = 330 * 1000;
+
+	rtnAmbRate = pRange->rtnAmbRate;
+	if (rtnAmbRate  < rtnAmbLowLimit_KCps) {
+		DMax = _DMax_RawValueAtRateKCps(dev, rtnAmbRate);
+		scaling = _GetUpscale(dev);
+		HwLimitAtScale = UpperLimitLookUP[scaling - 1];
+
+		if (DMax > _DMaxData(ClipSnrLimit)) {
+		    DMax = _DMaxData(ClipSnrLimit);
+		}
+		if (DMax > HwLimitAtScale) {
+		    DMax = HwLimitAtScale;
+		}
+		pRange->DMax = DMax;
+	} else {
+		pRange->DMax = 0;
+	}
+	return 0;
+}
+
+#undef _DMaxData
+#undef Fix7_2_KCPs
+
+#endif /* VL6180x_HAVE_DMAX_RANGING */
+
+
+

+ 1019 - 0
modules/vl6180x/vl6180x_api.h

@@ -0,0 +1,1019 @@
+/*******************************************************************************
+Copyright © 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 VL6180x_api.h
+ * $Date: 2018-07-04 16:49:57 +0200 (Wed, 04 Jul 2018) $
+ * $Revision: 2768 $
+ */
+
+
+
+#ifndef VL6180x_API_H_
+#define VL6180x_API_H_
+
+#include "vl6180x_platform.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup api_ll API Low Level Functions
+ *  @brief    API Low level functions
+ */
+
+/** @defgroup api_hl API High Level Functions
+ *  @brief    API High level functions
+ */
+
+
+/*
+ * Check and set default platform dependent configuration
+ */
+#ifndef VL6180x_SINGLE_DEVICE_DRIVER
+#error "VL6180x_SINGLE_DEVICE_DRIVER not defined"
+/* TODO you may remove or comment these #error but it is best you update your vl6180x_platform.h file to define it*/
+#endif
+
+
+#ifndef VL6180x_RANGE_STATUS_ERRSTRING
+#warning "VL6180x_RANGE_STATUS_ERRSTRING not defined ?"
+/* TODO you may remove or comment these #warning and keep the default below to keep compatibility
+   or update your vl6180x_platform.h file */
+/**
+ * force VL6180x_RANGE_STATUS_ERRSTRING to not supported when not part of any cfg file
+ */
+#define VL6180x_RANGE_STATUS_ERRSTRING  0
+#endif
+
+#ifndef VL6180X_SAFE_POLLING_ENTER
+#warning "VL6180X_SAFE_POLLING_ENTER not defined, likely old vl6180x_cfg.h file ?"
+/* TODO you may remove or comment these #warning and keep the default below to keep compatibility
+   or update your vl6180x_platform.h file */
+/**
+ * force VL6180X_SAFE_POLLING_ENTER to off when not in cfg file
+ */
+#define VL6180X_SAFE_POLLING_ENTER 0 /* off by default as in api 2.0 */
+#endif
+
+#ifndef VL6180X_LOG_ENABLE
+/**
+ * Force VL6180X_LOG_ENABLE to none as default
+ */
+#define VL6180X_LOG_ENABLE  0
+#endif
+
+#if VL6180x_RANGE_STATUS_ERRSTRING
+/**@def VL6180x_HAVE_RANGE_STATUS_ERRSTRING
+ * @brief is defined when @a #VL6180x_RANGE_STATUS_ERRSTRING is enable
+ */
+#define  VL6180x_HAVE_RANGE_STATUS_ERRSTRING
+#endif
+
+
+/** @brief Get API version as "hex integer" 0xMMnnss
+ */
+#define VL6180x_ApiRevInt  ((VL6180x_API_REV_MAJOR<<24)+(VL6180x_API_REV_MINOR<<16)+VL6180x_API_REV_SUB)
+
+/** Get API version as string for exe "2.1.12" "
+ */
+#define VL6180x_ApiRevStr  VL6180X_STR(VL6180x_API_REV_MAJOR) "." VL6180X_STR(VL6180x_API_REV_MINOR) "." VL6180X_STR(VL6180x_API_REV_SUB)
+
+/** @defgroup api_init Init functions
+ *  @brief    API init functions
+ *  @ingroup api_hl
+ *  @{
+ */
+/**
+ * @brief Wait for device booted after chip enable (hardware standby)
+ * @par Function Description
+ * After Chip enable Application you can also simply wait at least 1ms to ensure device is ready
+ * @warning After device chip enable (gpio0) de-asserted  user must wait gpio1 to get asserted (hardware standby).
+ * or wait at least 400usec prior to do any low level access or api call .
+ *
+ * This function implements polling for standby but you must ensure 400usec from chip enable passed\n
+ * @warning Calling this function if device is not fresh out of reset will  result in an indefinite loop\n
+ *
+ * @param dev  The device
+ * @return     0 on success
+ */
+int VL6180x_WaitDeviceBooted(VL6180xDev_t dev);
+
+/**
+ *
+ * @brief One time device initialization
+ *
+ * To be called once and only once after device is brought out of reset (Chip enable) and booted see @a VL6180x_WaitDeviceBooted()
+ *
+ * @par Function Description
+ * When not used after a fresh device "power up" or reset, it may return @a #CALIBRATION_WARNING
+ * meaning wrong calibration data may have been fetched from device that can result in unpredictable and wrong ranging values\n
+ *
+ * @param dev  The device
+ * @return     0 on success,  @a #CALIBRATION_WARNING if failed
+ */
+int VL6180x_InitData(VL6180xDev_t dev);
+
+/**
+ * @brief Configure GPIO1 function and set polarity.
+ * @par Function Description
+ * To be used prior to arm single shot measure or start  continuous mode.
+ *
+ * The function uses @a VL6180x_SetupGPIOx() for setting gpio 1.
+ * @warning  changing polarity can generate a spurious interrupt on pins.
+ * It sets an interrupt flags condition that must be cleared to avoid polling hangs. \n
+ * It is safe to run VL6180x_ClearAllInterrupt() just after.
+ *
+ * @param dev           The device
+ * @param IntFunction   The interrupt functionality to use one of :\n
+ *  @a #GPIOx_SELECT_OFF \n
+ *  @a #GPIOx_SELECT_GPIO_INTERRUPT_OUTPUT
+ * @param ActiveHigh  The interrupt line polarity see ::IntrPol_e
+ *      use @a #INTR_POL_LOW (falling edge) or @a #INTR_POL_HIGH (rising edge)
+ * @return 0 on success
+ */
+int VL6180x_SetupGPIO1(VL6180xDev_t dev, uint8_t IntFunction, int ActiveHigh);
+
+ /**
+  * @brief  Prepare device for operation
+  * @par Function Description
+  * Does static initialization and reprogram common default settings \n
+  * Device is prepared for new measure, ready single shot ranging or ALS typical polling operation\n
+  * After prepare user can : \n
+  * @li Call other API function to set other settings\n
+  * @li Configure the interrupt pins, etc... \n
+  * @li Then start ranging or ALS operations in single shot or continuous mode
+  *
+  * @param dev   The device
+  * @return      0 on success
+  */
+int VL6180x_Prepare(VL6180xDev_t dev);
+
+ /** @}  */
+
+
+/** @defgroup api_hl_range Ranging functions
+ *  @brief    Ranging functions
+ *  @ingroup api_hl
+ *  @{
+ */
+
+/**
+ * @brief Start continuous ranging mode
+ *
+ * @details End user should ensure device is in idle state and not already running
+ */
+int VL6180x_RangeStartContinuousMode(VL6180xDev_t dev);
+
+/**
+ * @brief Start single shot ranging measure
+ *
+ * @details End user should ensure device is in idle state and not already running
+ */
+int VL6180x_RangeStartSingleShot(VL6180xDev_t dev);
+
+/**
+ * @brief Set maximum convergence time
+ *
+ * @par Function Description
+ * Setting a low convergence time can impact maximal detectable distance.
+ * Refer to VL6180x Datasheet Table 7 : Typical range convergence time.
+ * A typical value for up to x3 scaling is 50 ms
+ *
+ * @param dev
+ * @param MaxConTime_msec
+ * @return 0 on success. <0 on error. >0 for calibration warning status
+ */
+int VL6180x_RangeSetMaxConvergenceTime(VL6180xDev_t dev, uint8_t  MaxConTime_msec);
+
+/**
+  * @brief Single shot Range measurement in polling mode.
+  *
+  * @par Function Description
+  * Kick off a new single shot range  then wait for ready to retrieve it by polling interrupt status \n
+  * Ranging must be prepared by a first call to  @a VL6180x_Prepare() and it is safer to clear  very first poll call \n
+  * This function reference VL6180x_PollDelay(dev) porting macro/call on each polling loop,
+  * but PollDelay(dev) may never be called if measure in ready on first poll loop \n
+  * Should not be use in continuous mode operation as it will stop it and cause stop/start misbehaviour \n
+  * VL6180x_PollDelay() is platform depending, the user has to implement this function accordingly \n
+  * 1 ms of wait is the recommended value to avoid excessive I2C requests for data ready check loop \n
+  * \n This function clears Range Interrupt status , but not error one. For that uses  @a VL6180x_ClearErrorInterrupt() \n
+  * This range error is not related VL6180x_RangeData_t::errorStatus that refer measure status \n
+  *
+  * @param dev          The device
+  * @param pRangeData   Will be populated with the result ranging data @a  VL6180x_RangeData_t
+  * @return 0 on success , @a #RANGE_ERROR if device reports an error case in it status (not cleared) use
+  *
+  * \sa ::VL6180x_RangeData_t
+  */
+int VL6180x_RangePollMeasurement(VL6180xDev_t dev, VL6180x_RangeData_t *pRangeData);
+
+/**
+ * @brief Check for measure readiness and get it if ready
+ *
+ * @par Function Description
+ * Using this function is an alternative to @a VL6180x_RangePollMeasurement() to avoid polling operation. This is suitable for applications
+ * where host CPU is triggered on a interrupt (not from VL6180X) to perform ranging operation. In this scenario, we assume that the very first ranging
+ * operation is triggered by a call to @a VL6180x_RangeStartSingleShot(). Then, host CPU regularly calls @a VL6180x_RangeGetMeasurementIfReady() to
+ * get a distance measure if ready. In case the distance is not ready, host may get it at the next call.\n
+ *
+ * @warning
+ * This function does not re-start a new measurement : this is up to the host CPU to do it.\n
+ * This function clears Range Interrupt for measure ready , but not error interrupts. For that, uses  @a VL6180x_ClearErrorInterrupt() \n
+ *
+ * @param dev  The device
+ * @param pRangeData  Will be populated with the result ranging data if available
+ * @return  0 on success and <0 in case of error. Please check pRangeData.errorStatus to check is new measurement is ready or not.
+ */
+int VL6180x_RangeGetMeasurementIfReady(VL6180xDev_t dev, VL6180x_RangeData_t *pRangeData);
+
+/**
+ * @brief Retrieve range measurements set  from device
+ *
+ * @par Function Description
+ * The measurement is made of range_mm status and error code @a VL6180x_RangeData_t \n
+ * Based on configuration selected extra measures are included.
+ *
+ * @warning should not be used in continuous if wrap around filter is active \n
+ * Does not perform any wait nor check for result availability or validity.
+ *\sa VL6180x_RangeGetResult for "range only" measurement
+ *
+ * @param dev         The device
+ * @param pRangeData  Pointer to the data structure to fill up
+ * @return            0 on success
+ */
+int VL6180x_RangeGetMeasurement(VL6180xDev_t dev, VL6180x_RangeData_t *pRangeData);
+
+/**
+ * @brief Get ranging result and only that
+ *
+ * @par Function Description
+ * Unlike @a VL6180x_RangeGetMeasurement() this function only retrieves the range in millimeter \n
+ * It does any required up-scale translation\n
+ * It can be called after success status polling or in interrupt mode \n
+ * @warning these function is not doing wrap around filtering \n
+ * This function doesn't perform any data ready check!
+ *
+ * @param dev        The device
+ * @param pRange_mm  Pointer to range distance
+ * @return           0 on success
+ */
+int VL6180x_RangeGetResult(VL6180xDev_t dev, int32_t *pRange_mm);
+
+/**
+ * @brief Configure ranging interrupt reported to application
+ *
+ * @param dev            The device
+ * @param ConfigGpioInt  Select ranging report\n select one (and only one) of:\n
+ *   @a #CONFIG_GPIO_INTERRUPT_DISABLED \n
+ *   @a #CONFIG_GPIO_INTERRUPT_LEVEL_LOW \n
+ *   @a #CONFIG_GPIO_INTERRUPT_LEVEL_HIGH \n
+ *   @a #CONFIG_GPIO_INTERRUPT_OUT_OF_WINDOW \n
+ *   @a #CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY
+ * @return   0 on success
+ */
+int VL6180x_RangeConfigInterrupt(VL6180xDev_t dev, uint8_t ConfigGpioInt);
+
+
+/**
+ * @brief Clear range interrupt
+ *
+ * @param dev    The device
+ * @return  0    On success
+ */
+#define VL6180x_RangeClearInterrupt(dev) VL6180x_ClearInterrupt(dev, INTERRUPT_CLEAR_RANGING)
+
+/**
+ * @brief Return ranging error interrupt status
+ *
+ * @par Function Description
+ * Appropriate Interrupt report must have been selected first by @a VL6180x_RangeConfigInterrupt() or @a  VL6180x_Prepare() \n
+ *
+ * Can be used in polling loop to wait for a given ranging event or in interrupt to read the trigger \n
+ * Events triggers are : \n
+ * @a #RES_INT_STAT_GPIO_LOW_LEVEL_THRESHOLD \n
+ * @a #RES_INT_STAT_GPIO_HIGH_LEVEL_THRESHOLD \n
+ * @a #RES_INT_STAT_GPIO_OUT_OF_WINDOW \n (RES_INT_STAT_GPIO_LOW_LEVEL_THRESHOLD|RES_INT_STAT_GPIO_HIGH_LEVEL_THRESHOLD)
+ * @a #RES_INT_STAT_GPIO_NEW_SAMPLE_READY \n
+ *
+ * @sa IntrStatus_t
+ * @param dev        The device
+ * @param pIntStatus Pointer to status variable to update
+ * @return           0 on success
+ */
+int VL6180x_RangeGetInterruptStatus(VL6180xDev_t dev, uint8_t *pIntStatus);
+
+#if VL6180x_RANGE_STATUS_ERRSTRING
+
+extern const char *ROMABLE_DATA VL6180x_RangeStatusErrString[];
+/**
+ * @brief Human readable error string for range error status
+ *
+ * @param RangeErrCode  The error code as stored on @a VL6180x_RangeData_t::errorStatus
+ * @return  error string , NULL for invalid RangeErrCode
+ * @sa ::RangeError_u
+ */
+const char *VL6180x_RangeGetStatusErrString(uint8_t RangeErrCode);
+#else
+#define VL6180x_RangeGetStatusErrString(...) NULL
+#endif
+
+/** @}  */
+
+#if VL6180x_ALS_SUPPORT
+
+/** @defgroup api_hl_als ALS functions
+ *  @brief    ALS functions
+ *  @ingroup api_hl
+ *  @{
+ */
+
+/**
+ * @brief   Run a single ALS measurement in single shot polling mode
+ *
+ * @par Function Description
+ * Kick off a new single shot ALS then wait new measurement ready to retrieve it ( polling system interrupt status register for als) \n
+ * ALS must be prepared by a first call to @a VL6180x_Prepare() \n
+ * \n Should not be used in continuous or interrupt mode it will break it and create hazard in start/stop \n
+ *
+ * @param dev          The device
+ * @param pAlsData     Als data structure to fill up @a VL6180x_AlsData_t
+ * @return             0 on success
+ */
+int VL6180x_AlsPollMeasurement(VL6180xDev_t dev, VL6180x_AlsData_t *pAlsData);
+
+
+/**
+ * @brief  Get actual ALS measurement
+ *
+ * @par Function Description
+ * Can be called after success status polling or in interrupt mode to retrieve ALS measurement from device \n
+ * This function doesn't perform any data ready check !
+ *
+ * @param dev        The device
+ * @param pAlsData   Pointer to measurement struct @a VL6180x_AlsData_t
+ * @return  0 on success
+ */
+int VL6180x_AlsGetMeasurement(VL6180xDev_t dev, VL6180x_AlsData_t *pAlsData);
+
+/**
+ * @brief  Configure ALS interrupts provide to application
+ *
+ * @param dev            The Device
+ * @param ConfigGpioInt  Select one (and only one) of : \n
+ *   @a #CONFIG_GPIO_INTERRUPT_DISABLED \n
+ *   @a #CONFIG_GPIO_INTERRUPT_LEVEL_LOW \n
+ *   @a #CONFIG_GPIO_INTERRUPT_LEVEL_HIGH \n
+ *   @a #CONFIG_GPIO_INTERRUPT_OUT_OF_WINDOW \n
+ *   @a #CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY
+ * @return               0 on success may return #INVALID_PARAMS for invalid mode
+ */
+int VL6180x_AlsConfigInterrupt(VL6180xDev_t dev, uint8_t ConfigGpioInt);
+
+
+/**
+ * @brief Set ALS integration period
+ *
+ * @param dev        The device
+ * @param period_ms  Integration period in msec. Value in between 50 to 100 msec is recommended\n
+ * @return           0 on success
+ */
+int VL6180x_AlsSetIntegrationPeriod(VL6180xDev_t dev, uint16_t period_ms);
+
+/**
+ * @brief Set ALS "inter-measurement period"
+ *
+ * @par Function Description
+ * The so call data-sheet "inter measurement period" is actually an extra inter-measurement delay
+ *
+ * @param dev        The device
+ * @param intermeasurement_period_ms Inter measurement time in milli second\n
+ *        @warning applied value is clipped to 2550 ms\n
+ * @return           0 on success if value is
+ */
+int VL6180x_AlsSetInterMeasurementPeriod(VL6180xDev_t dev,  uint16_t intermeasurement_period_ms);
+
+/**
+ * @brief Set ALS analog gain code
+ *
+ * @par Function Description
+ * ALS gain code value programmed in @a SYSALS_ANALOGUE_GAIN .
+ * @param dev   The device
+ * @param gain  Gain code see datasheet or AlsGainLookUp for real value. Value is clipped to 7.
+ * @return  0 on success
+ */
+
+int VL6180x_AlsSetAnalogueGain(VL6180xDev_t dev, uint8_t gain);
+/**
+ * @brief Set thresholds for ALS continuous mode
+ * @warning Threshold are raw device value not lux!
+ *
+ * @par Function Description
+ * Basically value programmed in @a SYSALS_THRESH_LOW and @a SYSALS_THRESH_HIGH registers
+ * @param dev   The device
+ * @param low   ALS low raw threshold for @a SYSALS_THRESH_LOW
+ * @param high  ALS high raw threshold for  @a SYSALS_THRESH_HIGH
+ * @return  0 on success
+ */
+int VL6180x_AlsSetThresholds(VL6180xDev_t dev, uint8_t low, uint8_t high);
+
+/**
+ * @brief  Clear ALS interrupt
+ *
+ * @param dev    The device
+ * @return  0    On success
+ */
+ #define VL6180x_AlsClearInterrupt(dev) VL6180x_ClearInterrupt(dev, INTERRUPT_CLEAR_ALS)
+
+/**
+ * Read ALS interrupt status
+ * @param dev         Device
+ * @param pIntStatus  Pointer to status
+ * @return            0 on success
+ */
+int VL6180x_AlsGetInterruptStatus(VL6180xDev_t dev, uint8_t *pIntStatus);
+
+/** @}  */
+#endif
+
+/** @defgroup api_ll_init Init functions
+ *  @brief    Init functions
+ *  @ingroup api_ll
+ *  @{
+ */
+
+/**
+ * @brief Low level ranging and ALS register static settings (you should call @a VL6180x_Prepare() function instead)
+ *
+ * @param dev
+ * @return 0 on success
+ */
+int VL6180x_StaticInit(VL6180xDev_t dev);
+
+ /** @}  */
+
+/** @defgroup api_ll_range Ranging functions
+ *  @brief    Ranging Low Level functions
+ *  @ingroup api_ll
+ *  @{
+ */
+
+/**
+ * @brief Wait for device to be ready (before a new ranging command can be issued by application)
+ * @param dev        The device
+ * @param MaxLoop    Max Number of i2c polling loop see @a #msec_2_i2cloop
+ * @return           0 on success. <0 when fail \n
+ *                   @ref VL6180x_ErrCode_t::TIME_OUT for time out \n
+ *                   @ref VL6180x_ErrCode_t::INVALID_PARAMS if MaxLop<1
+ */
+int VL6180x_RangeWaitDeviceReady(VL6180xDev_t dev, int MaxLoop);
+
+/**
+ * @brief Program Inter measurement period (used only in continuous mode)
+ *
+ * @par Function Description
+ * When trying to set too long time, it returns #INVALID_PARAMS
+ *
+ * @param dev     The device
+ * @param InterMeasTime_msec Requires inter-measurement time in msec
+ * @return 0 on success
+ */
+int VL6180x_RangeSetInterMeasPeriod(VL6180xDev_t dev, uint32_t  InterMeasTime_msec);
+
+
+/**
+ * @brief Set device ranging scaling factor
+ *
+ * @par Function Description
+ * The ranging scaling factor is applied on the raw distance measured by the device to increase operating ranging at the price of the precision.
+ * Changing the scaling factor when device is not in f/w standby state (free running) is not safe.
+ * It can be source of spurious interrupt, wrongly scaled range etc ...
+ * @warning __This  function doesns't update high/low threshold and other programmed settings linked to scaling factor__.
+ *  To ensure proper operation, threshold and scaling changes should be done following this procedure: \n
+ *  @li Set Group hold  : @a VL6180x_SetGroupParamHold() \n
+ *  @li Get Threshold @a VL6180x_RangeGetThresholds() \n
+ *  @li Change scaling : @a VL6180x_UpscaleSetScaling() \n
+ *  @li Set Threshold : @a VL6180x_RangeSetThresholds() \n
+ *  @li Unset Group Hold : @a VL6180x_SetGroupParamHold()
+ *
+ * @param dev      The device
+ * @param scaling  Scaling factor to apply (1,2 or 3)
+ * @return          0 on success when up-scale support is not configured it fail for any
+ *                  scaling than the one statically configured.
+ */
+int VL6180x_UpscaleSetScaling(VL6180xDev_t dev, uint8_t scaling);
+
+/**
+ * @brief Get current ranging scaling factor
+ *
+ * @param dev The device
+ * @return    The current scaling factor
+ */
+int VL6180x_UpscaleGetScaling(VL6180xDev_t dev);
+
+
+/**
+ * @brief Give filtered state (wrap-around filter) of a range measurement
+ * @param pRangeData  Range measurement data
+ * @return  0 means measure was not filtered,  when not 0 range from device got filtered by filter post processing
+ */
+#define VL6180x_RangeIsFilteredMeasurement(pRangeData) ((pRangeData)->errorStatus == RangingFiltered)
+
+/**
+ * @brief Get the maximal distance for actual scaling
+ * @par Function Description
+ * Do not use prior to @a VL6180x_Prepare() or at least @a VL6180x_InitData()
+ *
+ * Any range value more than the value returned by this function is to be considered as "no target detected"
+ * or "no target in detectable range"
+ * @warning The maximal distance depends on the scaling
+ *
+ * @param dev The device
+ * @return    The maximal range limit for actual mode and scaling
+ */
+uint16_t VL6180x_GetUpperLimit(VL6180xDev_t dev);
+
+/**
+ * @brief Apply low and high ranging thresholds that are considered only in continuous mode
+ *
+ * @par Function Description
+ * This function programs low and high ranging thresholds that are considered in continuous mode :
+ * interrupt will be raised only when an object is detected at a distance inside this [low:high] range.
+ * The function takes care of applying current scaling factor if any.\n
+ * To be safe, in continuous operation, thresholds must be changed under "group parameter hold" cover.
+ * Group hold can be activated/deactivated directly in the function or externally (then set 0)
+ * using /a VL6180x_SetGroupParamHold() function.
+ *
+ * @param dev      The device
+ * @param low      Low threshold in mm
+ * @param high     High threshold in mm
+ * @param SafeHold  Use of group parameters hold to surround threshold programming.
+ * @return  0 On success
+ */
+int VL6180x_RangeSetThresholds(VL6180xDev_t dev, uint16_t low, uint16_t high, int SafeHold);
+
+/**
+ * @brief  Get scaled high and low threshold from device
+ *
+ * @par Function Description
+ * Due to scaling factor, the returned value may be different from what has been programmed first (precision lost).
+ * For instance VL6180x_RangeSetThresholds(dev,11,22) with scale 3
+ * will read back 9 ((11/3)x3) and 21 ((22/3)x3).
+
+ * @param dev  The device
+ * @param low  scaled low Threshold ptr  can be NULL if not needed
+ * @param high scaled High Threshold ptr can be NULL if not needed
+ * @return 0 on success, return value is undefined if both low and high are NULL
+ * @warning return value is undefined if both low and high are NULL
+ */
+int VL6180x_RangeGetThresholds(VL6180xDev_t dev, uint16_t *low, uint16_t *high);
+
+/**
+ * @brief Set ranging raw thresholds (scaling not considered so not recommended to use it)
+ *
+ * @param dev  The device
+ * @param low  raw low threshold set to raw register
+ * @param high raw high threshold set to raw  register
+ * @return 0 on success
+ */
+int VL6180x_RangeSetRawThresholds(VL6180xDev_t dev, uint8_t low, uint8_t high);
+
+/**
+ * @brief Set Early Convergence Estimate ratio
+ * @par Function Description
+ * For more information on ECE check datasheet
+ * @warning May return a calibration warning in some use cases
+ *
+ * @param dev        The device
+ * @param FactorM    ECE factor M in M/D
+ * @param FactorD    ECE factor D in M/D
+ * @return           0 on success. <0 on error. >0 on warning
+ */
+int VL6180x_RangeSetEceFactor(VL6180xDev_t dev, uint16_t  FactorM, uint16_t FactorD);
+
+/**
+ * @brief Set Early Convergence Estimate state (See #SYSRANGE_RANGE_CHECK_ENABLES register)
+ * @param dev       The device
+ * @param enable    State to be set 0=disabled, otherwise enabled
+ * @return          0 on success
+ */
+int VL6180x_RangeSetEceState(VL6180xDev_t dev, int enable);
+
+/**
+ * @brief Set activation state of the wrap around filter
+ * @param dev   The device
+ * @param state New activation state (0=off,  otherwise on)
+ * @return      0 on success
+ */
+int VL6180x_FilterSetState(VL6180xDev_t dev, int state);
+
+/**
+ * Get activation state of the wrap around filter
+ * @param dev  The device
+ * @return     Filter enabled or not, when filter is not supported it always returns 0S
+ */
+int VL6180x_FilterGetState(VL6180xDev_t dev);
+
+
+/**
+ * @brief Set activation state of  DMax computation
+ * @param dev   The device
+ * @param state New activation state (0=off,  otherwise on)
+ * @return      0 on success
+ */
+int VL6180x_DMaxSetState(VL6180xDev_t dev, int state);
+
+/**
+ * Get activation state of DMax computation
+ * @param dev  The device
+ * @return     Filter enabled or not, when filter is not supported it always returns 0S
+ */
+int VL6180x_DMaxGetState(VL6180xDev_t dev);
+
+
+/**
+ * @brief Set ranging mode and start/stop measure (use high level functions instead : @a VL6180x_RangeStartSingleShot() or @a VL6180x_RangeStartContinuousMode())
+ *
+ * @par Function Description
+ * When used outside scope of known polling single shot stopped state, \n
+ * user must ensure the device state is "idle" before to issue a new command.
+ *
+ * @param dev   The device
+ * @param mode  A combination of working mode (#MODE_SINGLESHOT or #MODE_CONTINUOUS) and start/stop condition (#MODE_START_STOP) \n
+ * @return      0 on success
+ */
+int VL6180x_RangeSetSystemMode(VL6180xDev_t dev, uint8_t mode);
+
+/**
+ * @brief Enable/disable range ignore feature
+ *
+ * @par  Function Description
+ * Enable range ignore feature to ensure that the device does not range on the cover glass because of cross-talk. 
+ * @a VL6180x_RangeIgnoreConfigure() should be run first to configure feature prior to enable it.
+ *
+ * @param dev             The Device
+ * @param EnableState     Feature state to set 0= off else =on
+ * @return                0 on success
+ */
+int VL6180x_RangeIgnoreSetEnable(VL6180xDev_t dev, int EnableState);
+
+/**
+ * @brief Configure Range ignore feature
+ *
+ * @par  Function Description
+ * When return signal rate is below the IgnoreThreshold and return distance is below the ValidHeight, the distance will be ignored 
+ * @warning It is recommended to enable range ignore feature and configure it only when device is in stop or idle state
+ * @warning Once this function is called, next call to @a VL6180x_InitData() function without reseting the device will result in wrong ranging operation
+ * @param dev				The Device
+ * @param ValidHeight_mm    Valid height in mm (unscaled ie not raw  value before scaling)
+ * @param IgnoreThreshold	Ignore threshold in fixpoint 9.7 MegaCount/sec
+ * @return
+ */
+int VL6180x_RangeIgnoreConfigure(VL6180xDev_t dev, uint16_t ValidHeight_mm, uint16_t IgnoreThreshold);
+/** @}  */
+
+/** @defgroup api_ll_range_calibration Ranging calibration functions
+ *  @brief    Ranging calibration functions
+ *  @ingroup api_ll
+ *  @{
+ */
+/**
+ * @brief Get part to part calibration offset
+ *
+ * @par Function Description
+ * Should only be used after a successful call to @a VL6180x_InitData to backup device nvm value
+ *
+ * @param dev  The device
+ * @return part to part calibration offset from device
+ */
+int8_t VL6180x_GetOffsetCalibrationData(VL6180xDev_t dev);
+
+/**
+ * Set or over-write part to part calibration offset and apply it immediately
+ * \sa VL6180x_InitData(), VL6180x_GetOffsetCalibrationData()
+ * @param dev     The device
+ * @param offset   Offset
+ * @return  0 on success
+ */
+int  VL6180x_SetOffsetCalibrationData(VL6180xDev_t dev, int8_t offset);
+
+/**
+ * @brief Set Cross talk compensation rate
+ *
+ * @par Function Description
+ * It programs register @a #SYSRANGE_CROSSTALK_COMPENSATION_RATE
+ *
+ * @param dev  The device
+ * @param Rate Compensation rate (9.7 fix point) see datasheet for details
+ * @return     0 on success
+ */
+int  VL6180x_SetXTalkCompensationRate(VL6180xDev_t dev, FixPoint97_t Rate);
+
+/** @}  */
+
+
+
+#if VL6180x_ALS_SUPPORT
+/** @defgroup api_ll_als ALS functions
+ *  @brief    ALS functions
+ *  @ingroup api_ll
+ *  @{
+ */
+
+/**
+ * @brief Wait for device to be ready for new als operation or max pollign loop (time out)
+ * @param dev        The device
+ * @param MaxLoop    Max Number of i2c polling loop see @a #msec_2_i2cloop
+ * @return           0 on success. <0 when @a VL6180x_ErrCode_t::TIME_OUT if timed out
+ */
+int VL6180x_AlsWaitDeviceReady(VL6180xDev_t dev, int MaxLoop);
+
+/**
+ * @brief Set ALS system mode and start/stop measure
+ *
+ * @warning When used outside after single shot polling, \n
+ * User must ensure  the device state is ready before issuing a new command (using @a VL6180x_AlsWaitDeviceReady()). \n
+ * Non respect of this, can cause loss of interrupt or device hanging.
+ *
+ * @param dev   The device
+ * @param mode  A combination of working mode (#MODE_SINGLESHOT or #MODE_CONTINUOUS) and start condition (#MODE_START_STOP) \n
+ * @return      0 on success
+ */
+int VL6180x_AlsSetSystemMode(VL6180xDev_t dev, uint8_t mode);
+
+/** @}  */
+#endif
+
+/** @defgroup api_ll_misc Misc functions
+ *  @brief    Misc functions
+ *  @ingroup api_ll
+ *  @{
+ */
+
+/**
+ * Set Group parameter Hold state
+ *
+ * @par Function Description
+ * Group parameter holds @a #SYSTEM_GROUPED_PARAMETER_HOLD enable safe update (non atomic across multiple measure) by host
+ * \n The critical register group is composed of: \n
+ * #SYSTEM_INTERRUPT_CONFIG_GPIO \n
+ * #SYSRANGE_THRESH_HIGH \n
+ * #SYSRANGE_THRESH_LOW \n
+ * #SYSALS_INTEGRATION_PERIOD \n
+ * #SYSALS_ANALOGUE_GAIN \n
+ * #SYSALS_THRESH_HIGH \n
+ * #SYSALS_THRESH_LOW
+ *
+ *
+ * @param dev   The device
+ * @param Hold  Group parameter Hold state to be set (on/off)
+ * @return      0 on success
+ */
+int VL6180x_SetGroupParamHold(VL6180xDev_t dev, int Hold);
+
+/**
+ * @brief Set new device i2c address
+ *
+ * After completion the device will answer to the new address programmed.
+ *
+ * @sa AN4478: Using multiple VL6180X's in a single design
+ * @param dev       The device
+ * @param NewAddr   The new i2c address (8 bits)
+ * @return          0 on success
+ */
+int VL6180x_SetI2CAddress(VL6180xDev_t dev, uint8_t NewAddr);
+
+/**
+ * @brief Fully configure gpio 0/1 pin : polarity and functionality
+ *
+ * @param dev          The device
+ * @param pin          gpio pin 0 or 1
+ * @param IntFunction  Pin functionality : either #GPIOx_SELECT_OFF or #GPIOx_SELECT_GPIO_INTERRUPT_OUTPUT (refer to #SYSTEM_MODE_GPIO1 register definition)
+ * @param ActiveHigh   Set active high polarity, or active low see @a ::IntrPol_e
+ * @return             0 on success
+ */
+int VL6180x_SetupGPIOx(VL6180xDev_t dev, int pin, uint8_t IntFunction, int ActiveHigh);
+
+
+/**
+ * @brief Set interrupt pin polarity for the given GPIO
+ *
+ * @param dev          The device
+ * @param pin          Pin 0 or 1
+ * @param active_high  select active high or low polarity using @ref IntrPol_e
+ * @return             0 on success
+ */
+int VL6180x_SetGPIOxPolarity(VL6180xDev_t dev, int pin, int active_high);
+
+/**
+ * Select interrupt functionality for the given GPIO
+ *
+ * @par Function Description
+ * Functionality refer to @a SYSTEM_MODE_GPIO0
+ *
+ * @param dev            The device
+ * @param pin            Pin to configure 0 or 1 (gpio0 or gpio1)\nNote that gpio0 is chip enable at power up !
+ * @param functionality  Pin functionality : either #GPIOx_SELECT_OFF or #GPIOx_SELECT_GPIO_INTERRUPT_OUTPUT (refer to #SYSTEM_MODE_GPIO1 register definition)
+ * @return              0 on success
+ */
+int VL6180x_SetGPIOxFunctionality(VL6180xDev_t dev, int pin, uint8_t functionality);
+
+/**
+ * #brief Disable and turn to Hi-Z gpio output pin
+ *
+ * @param dev  The device
+ * @param pin  The pin number to disable 0 or 1
+ * @return     0 on success
+ */
+int VL6180x_DisableGPIOxOut(VL6180xDev_t dev, int pin);
+
+/**
+ * @def msec_2_i2cloop
+ * @brief  Number of I2C polling loop (an 8 bit register) to run for maximal wait time.
+ *
+ * @par Function Description
+ * When polling via I2C the overall time is mainly the I2C transaction time because it is a slow bus
+ *   one 8 bit register poll on I2C bus timing is shown below: \n
+ *   start + addr_w(a)  + 2x8bit index(a)  + stop  + start  + addr_rd(a)  + 1x8bit data_rd(a) + stop \n
+ *   1        8   1        2*(8+1)           1       1          8     1        8           1    1 \n
+ *  so 49 serial bits
+ *
+ * @param  time_ms  Time to wait in milli second 10
+ * @param  i2c_khz  I2C bus frequencies in KHz  for instance 400
+ * @return The number of loops (at least 1)
+ */
+#define msec_2_i2cloop(time_ms, i2c_khz) (((time_ms) * (i2c_khz) / 49) + 1)
+
+/** @}  */
+
+
+
+/**
+ * polarity use in @a VL6180x_SetupGPIOx() , @a VL6180x_SetupGPIO1()
+ */
+typedef enum {
+	INTR_POL_LOW = 0, /*!< set active low polarity best setup for falling edge */
+	INTR_POL_HIGH = 1, /*!< set active high polarity best setup for rising edge */
+} IntrPol_e;
+
+/** @defgroup api_ll_intr Interrupts management functions
+ *  @brief    Interrupts management functions
+ *  @ingroup api_ll
+ *  @{
+ */
+
+/**
+ * @brief     Get all interrupts cause
+ *
+ * @param dev    The device
+ * @param status Ptr to interrupt status. You can use @a IntrStatus_t::val
+ * @return 0 on success
+ */
+int VL6180x_GetInterruptStatus(VL6180xDev_t dev, uint8_t *status);
+
+/**
+ * @brief Clear given system interrupt condition
+ *
+ * @par Function Description
+ * Clear given interrupt cause by writing into register #SYSTEM_INTERRUPT_CLEAR register.
+ * @param dev       The device
+ * @param IntClear  Which interrupt source to clear. Use any combinations of #INTERRUPT_CLEAR_RANGING , #INTERRUPT_CLEAR_ALS , #INTERRUPT_CLEAR_ERROR.
+ * @return  0       On success
+ */
+int VL6180x_ClearInterrupt(VL6180xDev_t dev, uint8_t IntClear);
+
+/**
+ * @brief Clear error interrupt
+ *
+ * @param dev    The device
+ * @return  0    On success
+ */
+ #define VL6180x_ClearErrorInterrupt(dev) VL6180x_ClearInterrupt(dev, INTERRUPT_CLEAR_ERROR)
+
+/**
+ * @brief Clear All interrupt causes (als+range+error)
+ *
+ * @param dev    The device
+ * @return  0    On success
+ */
+#define VL6180x_ClearAllInterrupt(dev) VL6180x_ClearInterrupt(dev, INTERRUPT_CLEAR_ERROR|INTERRUPT_CLEAR_RANGING|INTERRUPT_CLEAR_ALS)
+
+/** @}  */
+
+
+/** @defgroup api_reg API Register access functions
+ *  @brief    Registers access functions called by API core functions
+ *  @ingroup api_ll
+ *  @{
+ */
+
+/**
+ * Write VL6180x single byte register
+ * @param dev   The device
+ * @param index The register index
+ * @param data  8 bit register data
+ * @return success
+ */
+int VL6180x_WrByte(VL6180xDev_t dev, uint16_t index, uint8_t data);
+/**
+ * Thread safe VL6180x Update (rd/modify/write) single byte register
+ *
+ * Final_reg = (Initial_reg & and_data) |or_data
+ *
+ * @param dev   The device
+ * @param index The register index
+ * @param AndData  8 bit and data
+ * @param OrData   8 bit or data
+ * @return 0 on success
+ */
+int VL6180x_UpdateByte(VL6180xDev_t dev, uint16_t index, uint8_t AndData, uint8_t OrData);
+/**
+ * Write VL6180x word register
+ * @param dev   The device
+ * @param index The register index
+ * @param data  16 bit register data
+ * @return  0 on success
+ */
+int VL6180x_WrWord(VL6180xDev_t dev, uint16_t index, uint16_t data);
+/**
+ * Write VL6180x double word (4 byte) register
+ * @param dev   The device
+ * @param index The register index
+ * @param data  32 bit register data
+ * @return  0 on success
+ */
+int VL6180x_WrDWord(VL6180xDev_t dev, uint16_t index, uint32_t data);
+
+/**
+ * Read VL6180x single byte register
+ * @param dev   The device
+ * @param index The register index
+ * @param data  pointer to 8 bit data
+ * @return 0 on success
+ */
+int VL6180x_RdByte(VL6180xDev_t dev, uint16_t index, uint8_t *data);
+
+/**
+ * Read VL6180x word (2byte) register
+ * @param dev   The device
+ * @param index The register index
+ * @param data  pointer to 16 bit data
+ * @return 0 on success
+ */
+int VL6180x_RdWord(VL6180xDev_t dev, uint16_t index, uint16_t *data);
+
+/**
+ * Read VL6180x dword (4byte) register
+ * @param dev   The device
+ * @param index The register index
+ * @param data  pointer to 32 bit data
+ * @return 0 on success
+ */
+int VL6180x_RdDWord(VL6180xDev_t dev, uint16_t index, uint32_t *data);
+
+
+/**
+ * Read VL6180x multiple bytes
+ * @note required only if #VL6180x_HAVE_MULTI_READ is set
+ * @param dev   The device
+ * @param index The register index
+ * @param data  pointer to 8 bit data
+ * @param nData number of data bytes to read
+ * @return 0 on success
+ */
+int VL6180x_RdMulti(VL6180xDev_t dev, uint16_t index, uint8_t *data, int nData);
+
+/** @}  */
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* VL6180x_API_H_ */

+ 119 - 0
modules/vl6180x/vl6180x_cfg.h

@@ -0,0 +1,119 @@
+/*******************************************************************************
+Copyright © 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.
+********************************************************************************/
+/*
+ * $Date: 2015-07-07 10:05:35 +0200 (Tue, 07 Jul 2015) $
+ * $Revision: 2438 $
+ */
+ 
+/**
+ * @file VL6180x_cfg.h
+ *
+ * Proximity and ALS configuration
+ */
+
+#ifndef VL6180x_CFG_H_
+#define VL6180x_CFG_H_
+
+/** @defgroup api_config Configuration
+ *  @brief API static configuration
+ */
+
+
+
+/** @ingroup api_config
+ * @{*/
+
+
+/**
+ * @def VL6180x_UPSCALE_SUPPORT
+ * @brief Configure up-scale capabilities and default up-scale factor for ranging operations
+ * 
+ * @li 1 : Fixed scaling by 1 (no up-scaling support)
+ * @li 2 : Fixed scaling by 2
+ * @li 3 : Fixed scaling by 3
+ * @li  -1 -2 -3 : Run time programmable through @a VL6180x_UpscaleSetScaling(). Default scaling factore is -VL6180x_UPSCALE_SUPPORT \n
+ */
+#define VL6180x_UPSCALE_SUPPORT -1
+
+/**
+ * @def VL6180x_ALS_SUPPORT
+ * @brief Enable ALS support
+ *
+ * Set to 0 if ALS is not used in application. This can help reducing code size if it is a concern.
+ */
+#define VL6180x_ALS_SUPPORT      1
+
+/**
+ * @def VL6180x_HAVE_DMAX_RANGING
+ * @brief Enable DMax calculation for ranging applications.
+ *  
+ * When set to 1, __Dmax__ is returned by API typically when  @a VL6180x_RangePollMeasurement() high level
+ * function is called (this is returned in @a VL6180x_RangeData_t structure).
+ * __Dmax__ is an estimation of the maximum distance (in mm) the product can report a valid distance of a 17% target for 
+ * the current ambient light conditions (__Dmax__ decreases when ambient light increases). __Dmax__ should be used only
+ * when the product is not able to return a valid distance (no object or object is too far from the ranging sensor).
+ * Typically, this is done by checking the __errorStatus__ field of the @a VL6180x_RangeData_t structure returned by 
+ * the @a VL6180x_RangePollMeasurement() function.
+ * You may refer to ::RangeError_u to get full list of supported error codes.
+ * @warning Dmax is estimated for a 17% grey target. If the real target has a reflectance lower than 17%, report Dmax could be over-estimated 
+ */
+#define VL6180x_HAVE_DMAX_RANGING   1
+
+/**
+ * @def VL6180x_WRAP_AROUND_FILTER_SUPPORT
+ * @brief Enable wrap around filter (WAF) feature
+ *  
+ * In specific conditions, when targeting a mirror or a very reflective metal, a __wrap around__ effect can occur internally to the
+ * ranging product which results in returning a wrong distance (under-estimated). Goal of the WAF is to detect this wrap arround effect
+ * and to filter it by returning a non-valid distance : __errorStatus__ set to 16 (see ::RangeError_u)
+ * @warning Wrap-around filter can not be used when device is running in continuous mode 
+ * 
+ * @li 0 : Filter is not supported, no filtering code is included in API
+ * @li 1 : Filter is supported and active by default
+ * @li -1 : Filter is supported but is not active by default @a VL6180x_FilterSetState() can turn it on and off at any time
+ */
+#define VL6180x_WRAP_AROUND_FILTER_SUPPORT   1
+
+/**
+ * @def VL6180x_EXTENDED_RANGE
+ * @brief Enable extended ranging support
+ *
+ * Device that do not formally support extended ranging should only be used with a scaling factor of 1.
+ * Correct operation with scaling factor other than 1 (>200mm ) is not granted by ST.
+ */
+#define VL6180x_EXTENDED_RANGE 0
+
+
+#if (VL6180x_EXTENDED_RANGE) && (VL6180x_ALS_SUPPORT)
+#warning "Als support should be OFF for extended range"
+#endif
+
+#endif
+/** @} */ // end of api_config
+
+/* VL6180x_CFG_H_ */

+ 773 - 0
modules/vl6180x/vl6180x_def.h

@@ -0,0 +1,773 @@
+/*******************************************************************************
+Copyright © 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.
+********************************************************************************/
+
+/*
+ * $Date: 2018-07-04 16:49:57 +0200 (Wed, 04 Jul 2018) $
+ * $Revision: 2768 $
+ */
+
+/**
+ * @file VL6180x_def.h
+ *
+ * @brief Type definitions for vl6180x api.
+ *
+ */
+
+
+#ifndef _VL6180x_DEF
+#define _VL6180x_DEF
+
+/** API major version */
+#define VL6180x_API_REV_MAJOR   3
+/** API minor version */
+#define VL6180x_API_REV_MINOR   2
+/** API sub version */
+#define VL6180x_API_REV_SUB     1
+
+#define VL6180X_STR_HELPER(x) #x
+#define VL6180X_STR(x) VL6180X_STR_HELPER(x)
+
+#include "vl6180x_cfg.h"
+#include "vl6180x_types.h"
+
+/*
+ * check configuration macro raise error or warning and suggest a default value
+ */
+
+#ifndef VL6180x_UPSCALE_SUPPORT
+#error "VL6180x_UPSCALE_SUPPORT not defined"
+/* TODO you must define value for  upscale support in your vl6180x_cfg.h  */
+#endif
+
+#ifndef VL6180x_ALS_SUPPORT
+#error "VL6180x_ALS_SUPPORT not defined"
+/* TODO you must define VL6180x_ALS_SUPPORT  with a value in your vl6180x_cfg.h  set to 0 do disable*/
+#endif
+
+#ifndef VL6180x_HAVE_DMAX_RANGING
+#error "VL6180x_HAVE_DMAX_RANGING not defined"
+/* TODO you may remove or comment these #error and keep the default below  or update your vl6180x_cfg.h .h file */
+/**
+ * force VL6180x_HAVE_DMAX_RANGING to not supported when not part of cfg file
+ */
+#define VL6180x_HAVE_DMAX_RANGING   0
+#endif
+
+#ifndef VL6180x_EXTENDED_RANGE
+#define VL6180x_EXTENDED_RANGE   0
+#endif
+
+#ifndef VL6180x_WRAP_AROUND_FILTER_SUPPORT
+#error "VL6180x_WRAP_AROUND_FILTER_SUPPORT not defined ?"
+/* TODO you may remove or comment these #error and keep the default below  or update vl6180x_cfg.h file */
+/**
+ * force VL6180x_WRAP_AROUND_FILTER_SUPPORT to not supported when not part of cfg file
+ */
+#define VL6180x_WRAP_AROUND_FILTER_SUPPORT 0
+#endif
+
+
+
+#ifndef VL6180x_HAVE_MULTI_READ
+#   define VL6180x_HAVE_MULTI_READ  0
+#endif
+
+/**
+ * Force VL6180x_CACHED_REG to default 0 when not defined
+ */
+#ifndef VL6180x_CACHED_REG
+#   define VL6180x_CACHED_REG  0
+#else
+#   define VL6180x_FIRST_CACHED_INDEX      0x04D
+#   define VL6180x_LAST_CACHED_INDEX       (VL6180x_FIRST_CACHED_INDEX+55)
+#   define VL6180x_CACHED_REG_CNT           (VL6180x_LAST_CACHED_INDEX-VL6180x_FIRST_CACHED_INDEX+1)
+#endif
+
+/****************************************
+ * PRIVATE define do not edit
+ ****************************************/
+
+/** Maximal buffer size ever use in i2c */
+#define VL6180x_MAX_I2C_XFER_SIZE   8 /* At present time it 6 byte max but that can change */
+
+#if VL6180x_UPSCALE_SUPPORT < 0
+/**
+ * @def VL6180x_HAVE_UPSCALE_DATA
+ * @brief  is defined if device data structure has data so when user configurable up-scale is active
+ */
+#define VL6180x_HAVE_UPSCALE_DATA /* have data only for user configurable up-scale config */
+#endif
+
+#if VL6180x_WRAP_AROUND_FILTER_SUPPORT
+/**
+ * @def VL6180x_HAVE_WRAP_AROUND_DATA
+ * @brief  is defined if device data structure has filter data so when active in cfg file
+ */
+#define  VL6180x_HAVE_WRAP_AROUND_DATA
+#endif
+
+#if VL6180x_ALS_SUPPORT != 0
+/**
+ * @def  VL6180x_HAVE_ALS_DATA
+ * @brief is defined when als data are include in device data structure so when als suport if configured
+ */
+#define VL6180x_HAVE_ALS_DATA
+#endif
+
+
+#if VL6180x_WRAP_AROUND_FILTER_SUPPORT || VL6180x_HAVE_DMAX_RANGING
+	#define	VL6180x_HAVE_RATE_DATA
+#endif
+
+/** Error and warning code returned by API
+ *
+ * negative value are true error mostly fatal\n
+ * positive value  are warning most of time it's ok to continue\n
+ */
+enum VL6180x_ErrCode_t {
+	API_NO_ERROR        = 0,
+	CALIBRATION_WARNING = 1,  /*!< warning invalid calibration data may be in used \a  VL6180x_InitData() \a VL6180x_GetOffsetCalibrationData \a VL6180x_SetOffsetCalibrationData*/
+	MIN_CLIPED          = 2,  /*!< warning parameter passed was clipped to min before to be applied */
+	NOT_GUARANTEED      = 3,  /*!< Correct operation is not guaranteed typically using extended ranging on vl6180x */
+
+	API_ERROR      = -1,    /*!< Unqualified error */
+	INVALID_PARAMS = -2,    /*!< parameter passed is invalid or out of range */
+	NOT_SUPPORTED  = -3,    /*!< function is not supported in current mode or configuration */
+	RANGE_ERROR    = -4,    /*!< device report a ranging error interrupt status */
+	TIME_OUT       = -5,    /*!< aborted due to time out */
+};
+
+/**
+ * Filtered result data structure  range data is to be used
+ */
+typedef struct RangeFilterResult_tag {
+	uint16_t range_mm;      /*!< Filtered ranging value */
+	uint16_t rawRange_mm;   /*!< raw range value (scaled) */
+	uint32_t filterError;   /*!< current filter error code */
+} RangeFilterResult_t;
+
+/**
+ * "small" unsigned data type used in filter
+ *
+ * if data space saving is not a concern it can be change to platform native unsigned int
+ */
+typedef uint32_t  FilterType1_t;
+
+/**
+ * @def FILTER_NBOF_SAMPLES
+ * @brief sample history len used for wrap around filtering
+ */
+#define FILTER_NBOF_SAMPLES             10
+/**
+ * Wrap around filter internal data
+ */
+struct FilterData_t {
+	uint32_t MeasurementIndex;                      /*!< current measurement index */
+	uint32_t MeasurementsSinceLastFlush;            /*!< Number of measurements done since last time buffer has been flushed */
+	uint16_t LastTrueRange[FILTER_NBOF_SAMPLES];    /*!< filtered/corrected  distance history */
+	uint32_t LastReturnRates[FILTER_NBOF_SAMPLES];  /*!< Return rate history */
+	uint16_t StdFilteredReads;                      /*!< internal use */
+	FilterType1_t Default_ZeroVal;                  /*!< internal use */
+	FilterType1_t Default_VAVGVal;                  /*!< internal use */
+	FilterType1_t NoDelay_ZeroVal;                  /*!< internal use */
+	FilterType1_t NoDelay_VAVGVal;                  /*!< internal use */
+	FilterType1_t Previous_VAVGDiff;                /*!< internal use */
+	uint32_t FilteringOnGoingConsecutiveStates;    /*!< internal use */
+	uint32_t filterError;                           /*!< current filter error code */
+};
+
+#if  VL6180x_HAVE_DMAX_RANGING
+typedef int32_t DMaxFix_t;
+struct DMaxData_t {
+	uint32_t ambTuningWindowFactor_K; /*!<  internal algo tuning (*1000) */
+
+	DMaxFix_t retSignalAt400mm;  /*!< intermediate dmax computation value caching @a #SYSRANGE_CROSSTALK_COMPENSATION_RATE and private reg 0x02A */
+    /* int32_t RegB8; */             /*!< register 0xB8 cached to speed reduce i2c traffic for dmax computation */
+    /* place all word data below to optimize struct packing */
+    /* int32_t minSignalNeeded; */    /*!< optimized computation intermediate base on register cached value */
+	int32_t snrLimit_K;         /*!< cached and optimized computation intermediate from  @a #SYSRANGE_MAX_AMBIENT_LEVEL_MULT */
+	uint16_t ClipSnrLimit;      /*!< Max value for snr limit */
+    /* place all byte data below to optimize packing */
+    /* uint8_t MaxConvTime; */        /*!< cached max convergence time @a #SYSRANGE_MAX_CONVERGENCE_TIME*/
+};
+#endif
+
+struct RangeIgnoreData_t {
+	uint16_t ValidHeight;
+	uint16_t IgnoreThreshold;
+	uint8_t Enabled;
+};
+/**
+ * @struct VL6180xDevData_t
+ *
+ * @brief Per VL6180x device St private data structure \n
+ * End user should never access any of these field directly
+ *
+ * These must never access directly but only via VL6180xDev/SetData(dev, field) macro
+ */
+struct VL6180xDevData_t {
+
+	uint32_t Part2PartAmbNVM;  /*!< backed up NVM value */
+	uint32_t XTalkCompRate_KCps; /*! Cached XTlak Compensation Rate */
+
+	uint16_t EceFactorM;        /*!< Ece Factor M numerator  */
+	uint16_t EceFactorD;        /*!< Ece Factor D denominator*/
+
+	struct RangeIgnoreData_t RangeIgnore;
+
+#ifdef VL6180x_HAVE_ALS_DATA
+	uint16_t IntegrationPeriod; /*!< cached als Integration period avoid slow read from device at each measure */
+	uint16_t AlsGainCode;       /*!< cached Als gain avoid slow read from device at each measure */
+	uint16_t AlsScaler;         /*!< cached Als scaler avoid slow read from device at each measure */
+#endif
+
+#ifdef VL6180x_HAVE_UPSCALE_DATA
+	uint8_t UpscaleFactor;      /*!<  up-scaling factor*/
+#endif
+
+#ifdef VL6180x_HAVE_WRAP_AROUND_DATA
+	uint8_t WrapAroundFilterActive; /*!< Filter on/off */
+	struct FilterData_t FilterData; /*!< Filter internal data state history ... */
+#endif
+
+#if VL6180x_CACHED_REG
+	uint8_t CacheFilled;             /*!< Set if valid data got fetched use to control when to fill up register cache */
+	uint8_t CachedRegs[VL6180x_CACHED_REG_CNT];          /*!< Cache register storage */
+#endif
+#if VL6180x_HAVE_DMAX_RANGING
+	struct DMaxData_t DMaxData;
+	uint8_t DMaxEnable;
+#endif
+	int8_t  Part2PartOffsetNVM;     /*!< backed up NVM value */
+};
+
+
+/**
+ * @struct VL6180x_RangeData_t
+ * @brief Range and any optional measurement data.
+ */
+typedef struct {
+	int32_t range_mm;          /*!< range distance in mm. */
+	int32_t signalRate_mcps;   /*!< signal rate (MCPS)\n these is a 9.7 fix point value, which is effectively a measure of target reflectance.*/
+	uint32_t errorStatus;      /*!< Error status of the current measurement. \n see @a ::RangeError_u @a VL6180x_GetRangeStatusErrString() */
+
+
+#ifdef VL6180x_HAVE_RATE_DATA
+	uint32_t rtnAmbRate;    /*!< Return Ambient rate in KCount per sec related to \a RESULT_RANGE_RETURN_AMB_COUNT */
+	uint32_t rtnRate;       /*!< Return rate in KCount per sec  related to \a RESULT_RANGE_RETURN_SIGNAL_COUNT  */
+	uint32_t rtnConvTime;   /*!< Return Convergence time \a RESULT_RANGE_RETURN_CONV_TIME */
+	uint32_t refConvTime;   /*!< Reference convergence time \a RESULT_RANGE_REFERENCE_CONV_TIME */
+#endif
+
+
+#if VL6180x_HAVE_DMAX_RANGING
+	uint32_t DMax;              /*!< DMax  when applicable */
+#endif
+
+#ifdef VL6180x_HAVE_WRAP_AROUND_DATA
+	RangeFilterResult_t FilteredData; /*!< Filter result main range_mm is updated */
+#endif
+} VL6180x_RangeData_t;
+
+
+/** use where fix point 9.7 bit values are expected
+ *
+ * given a floating point value f it's .7 bit point is (int)(f*(1<<7))*/
+typedef uint16_t FixPoint97_t;
+
+/** lux data type */
+typedef uint32_t lux_t;
+
+/**
+ * @brief This data type defines als  measurement data.
+ */
+typedef struct VL6180x_AlsData_st {
+	lux_t lux;                 /**< Light measurement (Lux) */
+	uint32_t errorStatus;      /**< Error status of the current measurement. \n
+	* No Error := 0. \n
+	* Refer to product sheets for other error codes. */
+} VL6180x_AlsData_t;
+
+/**
+ * @brief Range status Error code
+ *
+ * @a VL6180x_GetRangeStatusErrString() if configured ( @a #VL6180x_RANGE_STATUS_ERRSTRING )
+ * related to register @a #RESULT_RANGE_STATUS and additional post processing
+ */
+typedef enum {
+	NoError = 0,               /*!< 0  0b0000 NoError  */
+	VCSEL_Continuity_Test,     /*!< 1  0b0001 VCSEL_Continuity_Test */
+	VCSEL_Watchdog_Test,       /*!< 2  0b0010 VCSEL_Watchdog_Test */
+	VCSEL_Watchdog,            /*!< 3  0b0011 VCSEL_Watchdog */
+	PLL1_Lock,                 /*!< 4  0b0100 PLL1_Lock */
+	PLL2_Lock,                 /*!< 5  0b0101 PLL2_Lock */
+	Early_Convergence_Estimate,/*!< 6  0b0110 Early_Convergence_Estimate */
+	Max_Convergence,           /*!< 7  0b0111 Max_Convergence */
+	No_Target_Ignore,          /*!< 8  0b1000 No_Target_Ignore */
+	Not_used_9,                /*!< 9  0b1001 Not_used */
+	Not_used_10,               /*!< 10 0b1010 Not_used_ */
+	Max_Signal_To_Noise_Ratio, /*!< 11 0b1011 Max_Signal_To_Noise_Ratio*/
+	Raw_Ranging_Algo_Underflow,/*!< 12 0b1100 Raw_Ranging_Algo_Underflow*/
+	Raw_Ranging_Algo_Overflow, /*!< 13 0b1101 Raw_Ranging_Algo_Overflow */
+	Ranging_Algo_Underflow,    /*!< 14 0b1110 Ranging_Algo_Underflow */
+	Ranging_Algo_Overflow,     /*!< 15 0b1111 Ranging_Algo_Overflow */
+
+	/* code below are addition for API/software side they are not hardware*/
+	RangingFiltered = 0x10,     /*!< 16 0b10000 filtered by post processing*/
+	DataNotReady = 0x12,             /*!< 18 0b10011 New data sample not ready */
+
+} RangeError_u;
+
+
+/** @defgroup device_regdef Device registers & masks definitions
+ *  @brief    Device registers and masks definitions
+ */
+
+
+/** @ingroup device_regdef
+ * @{*/
+
+/**
+ * The device model ID
+ */
+#define IDENTIFICATION_MODEL_ID                 0x000
+/**
+ * Revision identifier of the Device for major change.
+ */
+#define IDENTIFICATION_MODULE_REV_MAJOR         0x003
+/**
+ * Revision identifier of the Device for minor change.
+ */
+#define IDENTIFICATION_MODULE_REV_MINOR         0x004
+
+
+/**
+ * @def SYSTEM_MODE_GPIO0
+ * @brief Configures polarity and select which function gpio 0 serves.
+ *  Gpio0 is chip enable at power up ! Be aware of all h/w implication of turning it to output.
+ *  Same definition as #SYSTEM_MODE_GPIO1
+ * @ingroup device_regdef
+ */
+#define SYSTEM_MODE_GPIO0                       0x010
+/**
+ * @def SYSTEM_MODE_GPIO1
+ * @brief Configures polarity and select what als or ranging functionality gpio pin serves.
+ *
+ * Function can be #GPIOx_SELECT_OFF  #GPIOx_SELECT_GPIO_INTERRUPT_OUTPUT.\n
+ * Same definition apply to register GPIO0 that is used as chip enable at power up.
+ * @ingroup device_regdef
+ */
+#define SYSTEM_MODE_GPIO1                       0x011
+    /** gpio pad POLARITY mask in #SYSTEM_MODE_GPIO1 (and/or 0) write  1  to set active high polarity (positive edge) */
+    #define GPIOx_POLARITY_SELECT_MASK              0x20
+    /** gpio pad Function select shift in #SYSTEM_MODE_GPIO1 or 0 */
+    #define GPIOx_FUNCTIONALITY_SELECT_SHIFT          1
+    /** gpio pad Function select mask in #SYSTEM_MODE_GPIO1 or 0 */
+    #define GPIOx_FUNCTIONALITY_SELECT_MASK          (0xF<<GPIOx_FUNCTIONALITY_SELECT_SHIFT)
+    /** select no interrupt in #SYSTEM_MODE_GPIO1 pad is put in  Hi-Z*/
+    #define GPIOx_SELECT_OFF                        0x00
+    /** select gpiox as interrupt output in  #SYSTEM_MODE_GPIO1 */
+    #define GPIOx_SELECT_GPIO_INTERRUPT_OUTPUT      0x08
+    /** select range as source for interrupt on in #SYSTEM_MODE_GPIO1 */
+    #define GPIOx_MODE_SELECT_RANGING               0x00
+    /** select als as source for interrupt on in #SYSTEM_MODE_GPIO1 */
+    #define GPIOx_MODE_SELECT_ALS                   0x01
+
+
+/**
+ * @def SYSTEM_INTERRUPT_CONFIG_GPIO
+ *
+ * @brief   Configure Als and Ranging interrupt reporting
+ *
+ * Possible values for Range and ALS are\n
+ *
+ * #CONFIG_GPIO_INTERRUPT_DISABLED\n
+ * #CONFIG_GPIO_INTERRUPT_LEVEL_LOW\n
+ * #CONFIG_GPIO_INTERRUPT_LEVEL_HIGH\n
+ * #CONFIG_GPIO_INTERRUPT_OUT_OF_WINDOW\n
+ * #CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY\n
+ * Apply respective rang/als shift and mask \n
+ *  #CONFIG_GPIO_RANGE_SHIFT and full reg mask #CONFIG_GPIO_RANGE_MASK\n
+ *  #CONFIG_GPIO_ALS_SHIFT and full reg mask #CONFIG_GPIO_ALS_MASK\n
+ *
+ * \sa GPIO use for interrupt #SYSTEM_MODE_GPIO0 or #SYSTEM_MODE_GPIO1\n
+ * @ingroup device_regdef
+ */
+#define SYSTEM_INTERRUPT_CONFIG_GPIO           0x014
+    /** RANGE bits shift in #SYSTEM_INTERRUPT_CONFIG_GPIO */
+    #define CONFIG_GPIO_RANGE_SHIFT            0
+    /** RANGE bits mask in #SYSTEM_INTERRUPT_CONFIG_GPIO  (unshifted)*/
+    #define CONFIG_GPIO_RANGE_MASK             (0x7<<CONFIG_GPIO_RANGE_SHIFT)
+    /** ALS bits shift in #SYSTEM_INTERRUPT_CONFIG_GPIO */
+    #define CONFIG_GPIO_ALS_SHIFT              3
+    /** ALS bits mask in #SYSTEM_INTERRUPT_CONFIG_GPIO  (unshifted)*/
+    #define CONFIG_GPIO_ALS_MASK               (0x7<<CONFIG_GPIO_ALS_SHIFT)
+    /** interrupt is disabled */
+    #define CONFIG_GPIO_INTERRUPT_DISABLED         0x00
+    /** trigger when value < low threshold */
+    #define CONFIG_GPIO_INTERRUPT_LEVEL_LOW        0x01
+    /** trigger when value < low threshold */
+    #define CONFIG_GPIO_INTERRUPT_LEVEL_HIGH       0x02
+    /** trigger when outside range defined by high low threshold */
+    #define CONFIG_GPIO_INTERRUPT_OUT_OF_WINDOW    0x03
+    /** trigger when new sample are ready */
+    #define CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY 0x04
+
+/**
+ *  @def SYSTEM_INTERRUPT_CLEAR
+ *  @brief Writing to this register will clear interrupt source
+ *
+ *  Use or combination of any #INTERRUPT_CLEAR_RANGING , #INTERRUPT_CLEAR_ALS , #INTERRUPT_CLEAR_ERROR
+ *  @ingroup device_regdef
+ */
+#define SYSTEM_INTERRUPT_CLEAR                0x015
+    /** clear ranging interrupt in write to #SYSTEM_INTERRUPT_CLEAR */
+    #define INTERRUPT_CLEAR_RANGING                0x01
+    /** clear als interrupt  in write to #SYSTEM_INTERRUPT_CLEAR */
+    #define INTERRUPT_CLEAR_ALS                    0x02
+    /** clear error interrupt in write to #SYSTEM_INTERRUPT_CLEAR */
+    #define INTERRUPT_CLEAR_ERROR                  0x04
+
+/** After power up or reset this register will start reading 1 when device is ready */
+#define SYSTEM_FRESH_OUT_OF_RESET             0x016
+
+/**
+ * @def SYSTEM_GROUPED_PARAMETER_HOLD
+ * @brief Writing 1/0 activate/deactivate safe host update of multiple register in critical group \n
+ *        rather use \a VL6180x_SetGroupParamHold()
+ *
+ * The critical register group is made of: \n
+ * #SYSTEM_INTERRUPT_CONFIG_GPIO \n
+ * #SYSRANGE_THRESH_HIGH \n
+ * #SYSRANGE_THRESH_LOW \n
+ * #SYSALS_INTEGRATION_PERIOD \n
+ * #SYSALS_ANALOGUE_GAIN \n
+ * #SYSALS_THRESH_HIGH \n
+ * #SYSALS_THRESH_LOW
+ * @ingroup device_regdef
+ */
+#define SYSTEM_GROUPED_PARAMETER_HOLD         0x017
+
+
+/**
+ * @def SYSRANGE_START
+ * @brief Start/stop and set operating range mode
+ *
+ * Write Combination of #MODE_START_STOP  and #MODE_CONTINUOUS to select and start desired operation.
+ *
+ * @ingroup device_regdef
+ */
+#define SYSRANGE_START                        0x018
+    /** mask existing bit in #SYSRANGE_START*/
+    #define SYSRANGE_START_MODE_MASK          0x03
+    /** bit 0 in #SYSRANGE_START write 1 toggle state in continuous mode and arm next shot in single shot mode */
+    #define MODE_START_STOP                   0x01
+    /** bit 1 write 1 in #SYSRANGE_START set continuous operation mode */
+    #define MODE_CONTINUOUS                   0x02
+    /** bit 1 write 0 in #SYSRANGE_START set single shot mode */
+    #define MODE_SINGLESHOT                   0x00
+
+/**
+ * @def SYSRANGE_THRESH_HIGH
+ * High level range  threshold (must be scaled)
+ * @ingroup device_regdef
+ */
+#define SYSRANGE_THRESH_HIGH                  0x019
+
+/**
+ * @def SYSRANGE_THRESH_LOW
+ * Low level range  threshold (must be scaled)
+ * @ingroup device_regdef
+ */
+#define SYSRANGE_THRESH_LOW                   0x01A
+
+/**
+ * @def SYSRANGE_INTERMEASUREMENT_PERIOD
+ * @brief Continuous mode intermeasurement delay \a VL6180x_RangeSetInterMeasPeriod()
+ *
+ * Time delay between measurements in Ranging continuous mode.\n
+ * Range 0-254 (0 = 10ms).\n Step size = 10ms.
+ *
+ * @ingroup device_regdef
+ */
+#define SYSRANGE_INTERMEASUREMENT_PERIOD      0x01B
+
+/**
+ * @brief Maximum time to run measurement in Ranging modes.
+ * Range 1 - 63 ms (1 code = 1 ms);
+ *
+ * Measurement aborted when limit reached to aid power  reduction.\
+ * For example, 0x01 = 1ms, 0x0a = 10ms.\
+ * Note: Effective max_convergence_time depends on readout_averaging_sample_period setting.
+ *
+ * @ingroup device_regdef
+ */
+#define SYSRANGE_MAX_CONVERGENCE_TIME         0x01C
+/**@brief Cross talk compensation rate
+ * @warning  never write register directly use @a VL6180x_SetXTalkCompensationRate()
+ * refer to manual for calibration procedure and computation
+ * @ingroup device_regdef
+ */
+#define SYSRANGE_CROSSTALK_COMPENSATION_RATE  0x01E
+/**
+ * @brief Minimum range value in mm to qualify for crosstalk compensation
+ */
+#define SYSRANGE_CROSSTALK_VALID_HEIGHT       0x021
+#define SYSRANGE_EARLY_CONVERGENCE_ESTIMATE   0x022
+#define SYSRANGE_PART_TO_PART_RANGE_OFFSET    0x024
+/**
+ * @brief range ignore valid height
+ * @warning  do not program directly use @a VL6180x_RangeIgnoreConfigure() and @a VL6180x_RangeIgnoreSetEnable()
+ */
+#define SYSRANGE_RANGE_IGNORE_VALID_HEIGHT    0x025
+/**
+ * @brief range ignore threshold
+ * @warning  do not program directly use @a VL6180x_RangeIgnoreConfigure() and @a VL6180x_RangeIgnoreSetEnable()
+ */
+#define SYSRANGE_RANGE_IGNORE_THRESHOLD       0x026
+#define SYSRANGE_EMITTER_BLOCK_THRESHOLD      0x028
+#define SYSRANGE_MAX_AMBIENT_LEVEL_THRESH     0x02A
+#define SYSRANGE_MAX_AMBIENT_LEVEL_MULT       0x02C
+/** @brief  various Enable check enable register
+ *  @a VL6180x_RangeSetEceState()
+ *  @a VL6180x_RangeIgnoreConfigure() and @a VL6180x_RangeIgnoreSetEnable()
+ */
+#define SYSRANGE_RANGE_CHECK_ENABLES          0x02D
+    #define RANGE_CHECK_ECE_ENABLE_MASK      0x01
+    #define RANGE_CHECK_RANGE_ENABLE_MASK    0x02
+    #define RANGE_CHECK_SNR_ENABLE           0x10
+
+#define SYSRANGE_VHV_RECALIBRATE              0x02E
+#define SYSRANGE_VHV_REPEAT_RATE              0x031
+
+/**
+ * @def SYSALS_START
+ * @brief Start/stop and set operating als mode
+ *
+ * same bit definition as range \a #SYSRANGE_START \n
+ */
+#define SYSALS_START                          0x038
+
+/** ALS low Threshold high */
+#define SYSALS_THRESH_HIGH                    0x03A
+/** ALS low Threshold low */
+#define SYSALS_THRESH_LOW                     0x03C
+/** ALS intermeasurement period */
+#define SYSALS_INTERMEASUREMENT_PERIOD        0x03E
+/**
+ * @warning or value with 0x40 when writing to these register*/
+#define SYSALS_ANALOGUE_GAIN                  0x03F
+/** ALS integration period */
+#define SYSALS_INTEGRATION_PERIOD             0x040
+
+/**
+ * @brief Result range status
+ *
+ *  Hold the various range interrupt flags and error Specific error codes
+ */
+#define RESULT_RANGE_STATUS                   0x04D
+    /** Device ready for new command bit 0*/
+    #define RANGE_DEVICE_READY_MASK       0x01
+    /** mask for error status covers bits [7:4]  in #RESULT_RANGE_STATUS @a ::RangeError_u */
+    #define RANGE_ERROR_CODE_MASK         0xF0 /* */
+    /** range error bit position in #RESULT_RANGE_STATUS */
+    #define RANGE_ERROR_CODE_SHIFT        4
+
+/**
+ * @def RESULT_ALS_STATUS
+ * @brief Result  als status \n
+ *  Hold the various als interrupt flags and Specific error codes
+ */
+#define RESULT_ALS_STATUS                     0x4E
+    /** Device ready for new command bit 0*/
+   #define ALS_DEVICE_READY_MASK       0x01
+
+/**
+ * @def RESULT_ALS_VAL
+ * @brief 16 Bit ALS count output value.
+ *
+ * Lux value depends on Gain and integration settings and calibrated lux/count setting
+ * \a VL6180x_AlsGetLux() \a VL6180x_AlsGetMeasurement()
+ */
+#define RESULT_ALS_VAL                        0x50
+
+/**
+ * @def FW_ALS_RESULT_SCALER
+ * @brief Als scaler register  Bits [3:0] analogue gain 1 to 16x
+ * these register content is cached by API in \a VL6180xDevData_t::AlsScaler
+ * for lux computation acceleration
+ */
+#define FW_ALS_RESULT_SCALER                  0x120
+
+
+/**
+ * these union can be use as a generic bit field type for map #RESULT_INTERRUPT_STATUS_GPIO register
+ * @ingroup device_regdef
+ */
+typedef union IntrStatus_u {
+	uint8_t val;           /*!< raw 8 bit register value*/
+	struct  {
+		unsigned Range:3; /*!< Range status one of :\n  \a #RES_INT_STAT_GPIO_LOW_LEVEL_THRESHOLD  \n \a #RES_INT_STAT_GPIO_HIGH_LEVEL_THRESHOLD  \n \a #RES_INT_STAT_GPIO_OUT_OF_WINDOW \n \a #RES_INT_STAT_GPIO_NEW_SAMPLE_READY */
+		unsigned Als:3; /*!< Als status one of: \n \a #RES_INT_STAT_GPIO_LOW_LEVEL_THRESHOLD  \n \a #RES_INT_STAT_GPIO_HIGH_LEVEL_THRESHOLD  \n \a #RES_INT_STAT_GPIO_OUT_OF_WINDOW \n \a #RES_INT_STAT_GPIO_NEW_SAMPLE_READY  */
+		unsigned Error:2; /*!<  Error status of: \n \a #RES_INT_ERROR_LASER_SAFETY  \n \a #RES_INT_ERROR_PLL */
+	} status;                 /*!< interrupt status as bit field */
+} IntrStatus_t;
+
+/**
+ * @def RESULT_INTERRUPT_STATUS_GPIO
+ * @brief System interrupt status report selected interrupt for als and ranging
+ *
+ * These register can be polled even if no gpio pins is active\n
+ * What reported is selected by \a  #SYSTEM_INTERRUPT_CONFIG_GPIO \n
+ * Range mask with \a #RES_INT_RANGE_MASK and shit by \a #RES_INT_RANGE_SHIFT
+ * Als   mask with \a #RES_INT_ALS_MASK and shit by \a #RES_INT_ALS_SHIFT
+ * Result value express condition (or combination?)
+ * \a #RES_INT_STAT_GPIO_LOW_LEVEL_THRESHOLD \n
+ * \a #RES_INT_STAT_GPIO_HIGH_LEVEL_THRESHOLD \n
+ * \a #RES_INT_STAT_GPIO_OUT_OF_WINDOW \n
+ * \a #RES_INT_STAT_GPIO_NEW_SAMPLE_READY
+ *
+ * @ingroup device_regdef
+ */
+#define RESULT_INTERRUPT_STATUS_GPIO          0x4F
+    /** ranging interrupt 1st bit position in #RESULT_INTERRUPT_STATUS_GPIO */
+    #define RES_INT_RANGE_SHIFT  0
+    /** ALS interrupt 1st bit position in #RESULT_INTERRUPT_STATUS_GPIO */
+    #define RES_INT_ALS_SHIFT    3
+    /** interrupt bit position in #RESULT_INTERRUPT_STATUS_GPIO */
+    #define RES_INT_ERROR_SHIFT  6
+    /** Ranging interrupt mask in #RESULT_INTERRUPT_STATUS_GPIO (prior to shift)  \sa IntrStatus_t */
+    #define RES_INT_RANGE_MASK (0x7<<RES_INT_RANGE_SHIFT)
+    /** als interrupt mask in #RESULT_INTERRUPT_STATUS_GPIO (prior to shift)  \sa IntrStatus_t */
+    #define RES_INT_ALS_MASK   (0x7<<RES_INT_ALS_SHIFT)
+
+    /** low threshold condition in #RESULT_INTERRUPT_STATUS_GPIO for */
+    #define RES_INT_STAT_GPIO_LOW_LEVEL_THRESHOLD  0x01
+    /** high threshold condition in #RESULT_INTERRUPT_STATUS_GPIO for ALs or Rage*/
+    #define RES_INT_STAT_GPIO_HIGH_LEVEL_THRESHOLD 0x02
+    /** out of window condition in #RESULT_INTERRUPT_STATUS_GPIO */
+    #define RES_INT_STAT_GPIO_OUT_OF_WINDOW        0x03
+    /** new sample ready in #RESULT_INTERRUPT_STATUS_GPIO */
+    #define RES_INT_STAT_GPIO_NEW_SAMPLE_READY     0x04
+    /** error  in #RESULT_INTERRUPT_STATUS_GPIO */
+    #define RES_INT_ERROR_MASK (0x3<<RES_INT_ERROR_SHIFT)
+	/** laser safety error on #RES_INT_ERROR_MASK of #RESULT_INTERRUPT_STATUS_GPIO */
+	#define RES_INT_ERROR_LASER_SAFETY  1
+	/** pll 1 or 2 error on #RES_INT_ERROR_MASK of #RESULT_INTERRUPT_STATUS_GPIO*/
+	#define RES_INT_ERROR_PLL           2
+
+/**
+ * Final range result value presented to the user for use. Unit is in mm.
+ */
+#define RESULT_RANGE_VAL                        0x062
+
+/**
+ * Raw Range result value with offset applied (no cross talk compensation applied). Unit is in mm.
+ */
+#define RESULT_RANGE_RAW                        0x064
+
+/**
+ * @brief Sensor count rate of signal returns correlated to IR emitter.
+ *
+ * Computed from RETURN_SIGNAL_COUNT / RETURN_CONV_TIME. Mcps 9.7 format
+ */
+#define RESULT_RANGE_SIGNAL_RATE                0x066
+
+/**
+ * @brief Return signal count
+ *
+ *  Sensor count output value attributed to signal correlated to IR emitter on the Return array.
+ */
+#define RESULT_RANGE_RETURN_SIGNAL_COUNT        0x06C
+
+/**
+ * @brief Reference signal count
+ *
+ * sensor count output value attributed to signal correlated to IR emitter on the Reference array.
+ */
+#define RESULT_RANGE_REFERENCE_SIGNAL_COUNT     0x070
+
+/**
+ * @brief Return ambient count
+ *
+ * sensor count output value attributed to uncorrelated ambient signal on the Return array.
+ * Must be multiplied by 6 if used to calculate the ambient to signal threshold
+ */
+#define RESULT_RANGE_RETURN_AMB_COUNT           0x074
+
+/**
+ * @brief   Reference ambient count
+ *
+ * Sensor count output value attributed to uncorrelated ambient signal on the Reference array.
+ */
+#define RESULT_RANGE_REFERENCE_AMB_COUNT        0x078
+
+/**
+ * sensor count output value attributed to signal on the Return array.
+ */
+#define RESULT_RANGE_RETURN_CONV_TIME           0x07C
+
+/**
+ * sensor count output value attributed to signal on the Reference array.
+ */
+#define RESULT_RANGE_REFERENCE_CONV_TIME        0x080
+
+
+/**
+ * @def RANGE_SCALER
+ * @brief RANGE scaling register
+ *
+ * Never should  user write directly onto that register directly \a VL6180x_UpscaleSetScaling()
+ */
+#define RANGE_SCALER                            0x096
+
+/**
+ * @def READOUT_AVERAGING_SAMPLE_PERIOD
+ * @brief Readout averaging sample period register
+ *
+ *
+ * The internal readout averaging sample period can be adjusted from 0 to 255.
+ * Increasing the sampling period decreases noise but also reduces the effective
+ * max convergence time and increases power consumption
+ * Each unit sample period corresponds to around 64.5 μs additional processing time.
+ * The recommended setting is 48 which equates to around 4.3 ms.
+ *
+ * see datasheet for more detail
+ */
+#define READOUT_AVERAGING_SAMPLE_PERIOD     0x10A
+
+/**
+ * @def I2C_SLAVE_DEVICE_ADDRESS
+ * User programmable I2C address (7-bit). Device address can be re-designated after power-up.
+ * @warning What programmed in the register 7-0 are bit 8-1 of i2c address on bus (bit 0 is rd/wr)
+ * so what prohamd is commonly whar ergfer as adrerss /2
+ * @sa VL6180x_SetI2CAddress()
+ */
+#define I2C_SLAVE_DEVICE_ADDRESS               0x212
+
+#endif /* _VL6180x_DEF */

+ 245 - 0
modules/vl6180x/vl6180x_i2c.c

@@ -0,0 +1,245 @@
+
+/*******************************************************************************
+Copyright © 2014, 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.
+********************************************************************************/
+/*
+ * $Date: 2015-07-06 15:44:31 +0200 (Mon, 06 Jul 2015) $
+ * $Revision: 2430 $
+ */
+
+/**
+ * @file vl6180x_i2c.c
+ *
+ * Copyright (C) 2014 ST MicroElectronics
+ *
+ * provide variable word size byte/Word/dword VL6180x register access via i2c
+ *
+ */
+#include "vl6180x_i2c.h"
+
+#ifndef I2C_BUFFER_CONFIG
+#error "I2C_BUFFER_CONFIG not defined"
+/* TODO you must define value for  I2C_BUFFER_CONFIG in configuration or platform h */
+#endif
+
+
+#if I2C_BUFFER_CONFIG == 0
+    /* GLOBAL config buffer */
+    uint8_t i2c_global_buffer[VL6180x_MAX_I2C_XFER_SIZE];
+
+    #define DECL_I2C_BUFFER
+    #define VL6180x_GetI2cBuffer(dev, n_byte)  i2c_global_buffer
+
+#elif I2C_BUFFER_CONFIG == 1
+    /* ON STACK */
+    #define DECL_I2C_BUFFER  uint8_t LocBuffer[VL6180x_MAX_I2C_XFER_SIZE];
+    #define VL6180x_GetI2cBuffer(dev, n_byte)  LocBuffer
+#elif I2C_BUFFER_CONFIG == 2
+    /* user define buffer type declare DECL_I2C_BUFFER  as access  via VL6180x_GetI2cBuffer */
+    #define DECL_I2C_BUFFER
+#else
+#error "invalid I2C_BUFFER_CONFIG "
+#endif
+
+
+int VL6180x_WrByte(VL6180xDev_t dev, uint16_t index, uint8_t data){
+    int  status;
+    uint8_t *buffer;
+    DECL_I2C_BUFFER
+    VL6180x_I2C_USER_VAR
+
+    VL6180x_GetI2CAccess(dev);
+
+    buffer=VL6180x_GetI2cBuffer(dev,3);
+    buffer[0]=index>>8;
+    buffer[1]=index&0xFF;
+    buffer[2]=data;
+
+    status=VL6180x_I2CWrite(dev, buffer,(uint8_t)3);
+    VL6180x_DoneI2CAcces(dev);
+    return status;
+}
+
+int VL6180x_WrWord(VL6180xDev_t dev, uint16_t index, uint16_t data){
+    int  status;
+    DECL_I2C_BUFFER
+    uint8_t *buffer;
+    VL6180x_I2C_USER_VAR
+
+    VL6180x_GetI2CAccess(dev);
+
+    buffer=VL6180x_GetI2cBuffer(dev,4);
+    buffer[0]=index>>8;
+    buffer[1]=index&0xFF;
+    buffer[2]=data>>8;
+    buffer[3]=data&0xFF;
+
+    status=VL6180x_I2CWrite(dev, buffer,(uint8_t)4);
+    VL6180x_DoneI2CAcces(dev);
+    return status;
+}
+
+int VL6180x_WrDWord(VL6180xDev_t dev, uint16_t index, uint32_t data){
+    VL6180x_I2C_USER_VAR
+    DECL_I2C_BUFFER
+    int  status;
+    uint8_t *buffer;
+
+
+    VL6180x_GetI2CAccess(dev);
+    buffer=VL6180x_GetI2cBuffer(dev,6);
+    buffer[0]=index>>8;
+    buffer[1]=index&0xFF;
+    buffer[2]=data>>24;
+    buffer[3]=(data>>16)&0xFF;
+    buffer[4]=(data>>8)&0xFF;;
+    buffer[5]=data&0xFF;
+    status=VL6180x_I2CWrite(dev, buffer,(uint8_t)6);
+    VL6180x_DoneI2CAcces(dev);
+
+    return status;
+}
+
+int VL6180x_UpdateByte(VL6180xDev_t dev, uint16_t index, uint8_t AndData, uint8_t OrData){
+    VL6180x_I2C_USER_VAR
+    int  status;
+    uint8_t *buffer;
+    DECL_I2C_BUFFER
+
+    VL6180x_GetI2CAccess(dev);
+
+    buffer=VL6180x_GetI2cBuffer(dev,3);
+    buffer[0]=index>>8;
+    buffer[1]=index&0xFF;
+
+    status=VL6180x_I2CWrite(dev, (uint8_t *)buffer,(uint8_t)2);
+    if( !status ){
+        /* read data direct onto buffer */
+        status=VL6180x_I2CRead(dev, &buffer[2],1);
+        if( !status ){
+            buffer[2]=(buffer[2]&AndData)|OrData;
+            status=VL6180x_I2CWrite(dev, buffer, (uint8_t)3);
+        }
+    }
+
+    VL6180x_DoneI2CAcces(dev);
+
+    return status;
+}
+
+int VL6180x_RdByte(VL6180xDev_t dev, uint16_t index, uint8_t *data){
+    VL6180x_I2C_USER_VAR
+    int  status;
+    uint8_t *buffer;
+    DECL_I2C_BUFFER
+
+    VL6180x_GetI2CAccess(dev);
+
+    buffer=VL6180x_GetI2cBuffer(dev,2);
+    buffer[0]=index>>8;
+    buffer[1]=index&0xFF;
+
+    status=VL6180x_I2CWrite(dev, buffer, (uint8_t)2);
+    if( !status ){
+        status=VL6180x_I2CRead(dev, buffer,1);
+        if( !status ){
+            *data=buffer[0];
+        }
+    }
+    VL6180x_DoneI2CAcces(dev);
+
+    return status;
+}
+
+int VL6180x_RdWord(VL6180xDev_t dev, uint16_t index, uint16_t *data){
+    VL6180x_I2C_USER_VAR
+    int  status;
+    uint8_t *buffer;
+    DECL_I2C_BUFFER
+
+    VL6180x_GetI2CAccess(dev);
+
+    buffer=VL6180x_GetI2cBuffer(dev,2);
+    buffer[0]=index>>8;
+    buffer[1]=index&0xFF;
+
+    status=VL6180x_I2CWrite(dev, buffer, (uint8_t)2);
+    if( !status){
+        status=VL6180x_I2CRead(dev, buffer,2);
+        if( !status ){
+            /* VL6180x register are Big endian if cpu is be direct read direct into *data is possible */
+            *data=((uint16_t)buffer[0]<<8)|(uint16_t)buffer[1];
+        }
+    }
+    VL6180x_DoneI2CAcces(dev);
+    return status;
+}
+
+int  VL6180x_RdDWord(VL6180xDev_t dev, uint16_t index, uint32_t *data){
+    VL6180x_I2C_USER_VAR
+    int status;
+    uint8_t *buffer;
+    DECL_I2C_BUFFER
+
+    VL6180x_GetI2CAccess(dev);
+    buffer=VL6180x_GetI2cBuffer(dev,4);
+
+    buffer[0]=index>>8;
+    buffer[1]=index&0xFF;
+
+    status=VL6180x_I2CWrite(dev, (uint8_t *) buffer, (uint8_t)2);
+    if( !status ){
+        status=VL6180x_I2CRead(dev, buffer,4);
+        if( !status ){
+            /* VL6180x register are Big endian if cpu is be direct read direct into data is possible */
+            *data=((uint32_t)buffer[0]<<24)|((uint32_t)buffer[1]<<16)|((uint32_t)buffer[2]<<8)|((uint32_t)buffer[3]);
+        }
+    }
+    VL6180x_DoneI2CAcces(dev);
+    return status;
+}
+
+
+int  VL6180x_RdMulti(VL6180xDev_t dev, uint16_t index, uint8_t *data, int nData){
+    VL6180x_I2C_USER_VAR
+    int status;
+    uint8_t *buffer;
+    DECL_I2C_BUFFER
+
+    VL6180x_GetI2CAccess(dev);
+    buffer=VL6180x_GetI2cBuffer(dev,2);
+
+    buffer[0]=index>>8;
+    buffer[1]=index&0xFF;
+
+    status=VL6180x_I2CWrite(dev, (uint8_t *) buffer, (uint8_t)2);
+    if( !status ){
+        status=VL6180x_I2CRead(dev, data, nData);
+    }
+    VL6180x_DoneI2CAcces(dev);
+    return status;
+}

+ 166 - 0
modules/vl6180x/vl6180x_i2c.h

@@ -0,0 +1,166 @@
+/*
+ * $Date: 2015-01-08 14:30:24 +0100 (Thu, 08 Jan 2015) $
+ * $Revision: 2039 $
+ */
+ 
+/**
+ * @file vl6180x_i2c.h
+ *
+ * @brief  CCI interface to "raw i2c" translation layer
+ */
+
+#ifndef VL6180_I2C_H_
+#define VL6180_I2C_H_
+
+#include "vl6180x_platform.h"
+
+/**
+ * @defgroup cci_i2c  CCI to RAW I2C translation layer
+ *
+ * This optional tranlation layer is implemented in __platform/cci-i2c__ directory. If user uses this translation layer for his platform, only @a VL6180x_I2CRead() and
+ * @a VL6180x_I2CWrite() functions need to be implemented. Also, some code adaption (via macro) is required for multi-threading and for multiple device support.
+ *
+ * File vl6180x_i2c.c implements device register access via raw i2c access. If the targeted application and platform has no multi-thread,  no multi-cpu and uses single
+ * device, then nothing else is required than the 2 mandatory function : @a VL6180x_I2CRead() and @a VL6180x_I2CWrite().\n
+ * In other cases, review and customize @a VL6180x_GetI2CAccess() and @a VL6180x_DoneI2CAccess() functions as well as @a #VL6180x_I2C_USER_VAR macro. This should be enough
+ * to conform to a wide range of platform OS and application requirements .\n
+ *
+ * If your configured i2c for per device buffer via  @a #I2C_BUFFER_CONFIG == 2, you must implement @a VL6180x_GetI2cBuffer()
+ *
+ * __I2C Port sample__ \n
+ * A __linux kernel__ port need a "long flags" var for its spin_lock in all functions. the following code example declares a spin lock "lock" in the custom device structure. \n
+ * @code
+struct MyVL6180Dev_t {
+     struct VL6180xDevData_t StData;
+     ...
+     spinlock_t i2c_lock;
+};
+typedef struct MyVL6180Dev_t *VL6180xDev_t;
+
+#define VL6180x_I2C_USER_VAR   unsigned long flags;
+#define GetI2CAccess(dev)      spin_lock_irqsave(dev->i2c_lock, flags)
+#define DoneI2CAccess(dev)     spin_unlock_irqrestore(dev->i2c_lock,flags)
+@endcode
+
+*  __POSIX pthread__ application porting could be as follows :\n
+* @code
+struct MyVL6180Dev_t {
+    struct VL6180xDevData_t StData;
+    ...
+    pthread_mutex_t *lock;
+};
+typedef struct MyVL6180Dev_t *VL6180xDev_t;
+
+#define VL6180x_I2C_USER_VAR        //no need
+#define VL6180x_GetI2CAccess(dev)   pthread_mutex_lock(dev->lock)
+#define VL6180x_DoneI2CAcces(dev)   pthread_mutex_unlock(dev->lock)
+ * @endcode
+ */
+
+/**
+ * @def I2C_BUFFER_CONFIG
+ *
+ * @brief Configure device register I2C access
+ *
+ * @li 0 : one GLOBAL buffer \n
+ *   Use one global buffer of MAX_I2C_XFER_SIZE byte in data space \n
+ *   This solution is not multi-device compliant nor multi-thread cpu safe \n
+ *   It can be the best option for small 8/16 bit MCU without stack and limited ram  (STM8s, 80C51 ...)
+ *
+ * @li 1 : ON_STACK/local \n
+ *   Use local variable (on stack) buffer \n
+ *   This solution is multi-thread with use of i2c resource lock or mutex see @a VL6180x_GetI2CAccess() \n
+ *
+ * @li 2 : User defined \n
+ *    Per device potentially dynamic allocated. Requires @a VL6180x_GetI2cBuffer() to be implemented.
+ * @ingroup Configuration
+ */
+#define I2C_BUFFER_CONFIG 1
+
+/**
+ * @brief       Write data buffer to VL6180x device via i2c
+ * @param dev   The device to write to
+ * @param buff  The data buffer
+ * @param len   The length of the transaction in byte
+ * @return      0 on success
+ * @ingroup cci_i2c
+ */
+int  VL6180x_I2CWrite(VL6180xDev_t dev, uint8_t  *buff, uint8_t len);
+
+/**
+ *
+ * @brief       Read data buffer from VL6180x device via i2c
+ * @param dev   The device to read from
+ * @param buff  The data buffer to fill
+ * @param len   The length of the transaction in byte
+ * @return      0 on success
+ * @ingroup  cci_i2c
+ */
+int VL6180x_I2CRead(VL6180xDev_t dev, uint8_t *buff, uint8_t len);
+
+
+/**
+ * @brief Declare any required variables used by i2c lock (@a VL6180x_DoneI2CAccess() and @a VL6180x_GetI2CAccess())
+ * and buffer access : @a VL6180x_GetI2cBuffer()
+ *
+ * @ingroup cci_i2c
+ */
+#define VL6180x_I2C_USER_VAR
+
+/**
+ *  @brief Acquire lock or mutex for access to i2c data buffer and bus.\n
+ *  Delete the default VL6180x_GetI2CAccess 'do-nothing' macro below if you decide to implement this function.
+ *
+ *  This function is used to perform i2c bus level and multiple access locking required for multi thread/proccess system.\n
+ *  Multiple access (read and update) will lock once and do multiple basic i2c rd/wr to complete the overall transfer.\n
+ *  When no locking is needed this can be a void macro.\n
+ *
+ * @param dev  the device
+ * @ingroup cci_i2c
+ */
+void VL6180x_GetI2CAccess(VL6180xDev_t dev);
+
+/**
+ * @def VL6180x_GetI2CAccess
+ * @brief Default 'do-nothing' macro for @a VL6180x_GetI2CAccess(). Delete if used.
+ * @ingroup cci_i2c
+ */
+#define VL6180x_GetI2CAccess(dev) (void)0 /* TODO delete if function used */
+
+/**
+ * @brief Release acquired lock or mutex for i2c access.\n
+ * Delete default VL6180x_DoneI2CAccess 'do-nothing' macro below if implementing that function.
+ *
+ * This function is used to release the acquired lock.
+ * @param dev The device
+ * @ingroup cci_i2c
+ */
+void VL6180x_DoneI2CAccess(VL6180xDev_t dev);
+
+/** @def VL6180x_DoneI2CAcces
+ * @brief Default 'do-nothing' macro for @a VL6180x_DoneI2CAcces(). Delete if used.
+ * @ingroup cci_i2c
+ */
+#define VL6180x_DoneI2CAcces(dev) (void)0  /*TODO delete  if function used */
+
+/**
+ * @brief Provided data buffer for i2c access for at least n_byte.
+ *
+ * You must implement it when i2c @a #I2C_BUFFER_CONFIG is set to 2 (User defined).\n
+ * This is used used in the context of #VL6180x_I2C_USER_VAR
+ *
+ * @param dev     The device
+ * @param n_byte  Minimal number of byte
+ * @return        The buffer (cannot fail return not checked)
+ * @ingroup cci_i2c
+ */
+uint8_t *VL6180x_GetI2cBuffer(VL6180xDev_t dev, int n_byte);
+#if I2C_BUFFER_CONFIG == 2
+#error /* TODO add your macro of code here for VL6180x_GetI2cBuffer */
+#endif
+
+
+
+
+
+#endif /* VL6180_I2C_H_ */

Разница между файлами не показана из-за своего большого размера
+ 376 - 500
project/ewarm/lt8920.dep


+ 33 - 2
project/ewarm/lt8920.ewp

@@ -357,6 +357,7 @@
                     <state>$PROJ_DIR$/../../modules/bsp</state>
                     <state>$PROJ_DIR$/../../modules/debug</state>
                     <state>$PROJ_DIR$/../../modules/lt8920</state>
+                    <state>$PROJ_DIR$/../../modules/vl6180x</state>
                 </option>
                 <option>
                     <name>CCStdIncCheck</name>
@@ -606,7 +607,7 @@
                 </option>
                 <option>
                     <name>AOutputFile</name>
-                    <state></state>
+                    <state>$FILE_BNAME$.o</state>
                 </option>
                 <option>
                     <name>ALimitErrorsCheck</name>
@@ -656,7 +657,7 @@
                 </option>
                 <option>
                     <name>OOCOutputFile</name>
-                    <state></state>
+                    <state>lt8920.srec</state>
                 </option>
                 <option>
                     <name>OOCCommandLineProducer</name>
@@ -2285,6 +2286,18 @@
             <file>
                 <name>$PROJ_DIR$\..\..\modules\bsp\stm32l0xx_nucleo.c</name>
             </file>
+            <file>
+                <name>$PROJ_DIR$\..\..\modules\bsp\stm32xxx_hal.h</name>
+            </file>
+            <file>
+                <name>$PROJ_DIR$\..\..\modules\bsp\vl6180x_platform.h</name>
+            </file>
+            <file>
+                <name>$PROJ_DIR$\..\..\modules\bsp\vl6180x_types.h</name>
+            </file>
+            <file>
+                <name>$PROJ_DIR$\..\..\modules\bsp\x-nucleo-6180xa1.c</name>
+            </file>
         </group>
         <group>
             <name>debug</name>
@@ -2304,12 +2317,30 @@
                 <name>$PROJ_DIR$\..\..\modules\lt8920\lt8920_trs.cpp</name>
             </file>
         </group>
+        <group>
+            <name>vl6180x</name>
+            <file>
+                <name>$PROJ_DIR$\..\..\modules\vl6180x\vl6180x_api.c</name>
+            </file>
+            <file>
+                <name>$PROJ_DIR$\..\..\modules\vl6180x\vl6180x_cfg.h</name>
+            </file>
+            <file>
+                <name>$PROJ_DIR$\..\..\modules\vl6180x\vl6180x_def.h</name>
+            </file>
+            <file>
+                <name>$PROJ_DIR$\..\..\modules\vl6180x\vl6180x_i2c.c</name>
+            </file>
+        </group>
     </group>
     <group>
         <name>user</name>
         <file>
             <name>$PROJ_DIR$\..\..\user\main.cpp</name>
         </file>
+        <file>
+            <name>$PROJ_DIR$\startup_stm32l053xx.s</name>
+        </file>
         <file>
             <name>$PROJ_DIR$\..\..\user\stm32l0xx_hal_conf.h</name>
         </file>

+ 30 - 0
project/ewarm/lt8920.ewt

@@ -2544,6 +2544,18 @@
             <file>
                 <name>$PROJ_DIR$\..\..\modules\bsp\stm32l0xx_nucleo.c</name>
             </file>
+            <file>
+                <name>$PROJ_DIR$\..\..\modules\bsp\stm32xxx_hal.h</name>
+            </file>
+            <file>
+                <name>$PROJ_DIR$\..\..\modules\bsp\vl6180x_platform.h</name>
+            </file>
+            <file>
+                <name>$PROJ_DIR$\..\..\modules\bsp\vl6180x_types.h</name>
+            </file>
+            <file>
+                <name>$PROJ_DIR$\..\..\modules\bsp\x-nucleo-6180xa1.c</name>
+            </file>
         </group>
         <group>
             <name>debug</name>
@@ -2563,12 +2575,30 @@
                 <name>$PROJ_DIR$\..\..\modules\lt8920\lt8920_trs.cpp</name>
             </file>
         </group>
+        <group>
+            <name>vl6180x</name>
+            <file>
+                <name>$PROJ_DIR$\..\..\modules\vl6180x\vl6180x_api.c</name>
+            </file>
+            <file>
+                <name>$PROJ_DIR$\..\..\modules\vl6180x\vl6180x_cfg.h</name>
+            </file>
+            <file>
+                <name>$PROJ_DIR$\..\..\modules\vl6180x\vl6180x_def.h</name>
+            </file>
+            <file>
+                <name>$PROJ_DIR$\..\..\modules\vl6180x\vl6180x_i2c.c</name>
+            </file>
+        </group>
     </group>
     <group>
         <name>user</name>
         <file>
             <name>$PROJ_DIR$\..\..\user\main.cpp</name>
         </file>
+        <file>
+            <name>$PROJ_DIR$\startup_stm32l053xx.s</name>
+        </file>
         <file>
             <name>$PROJ_DIR$\..\..\user\stm32l0xx_hal_conf.h</name>
         </file>

+ 21 - 3
user/main.cpp

@@ -3,6 +3,7 @@
 #include "usart.h"
 #include "lt8920_trs.h"
 #include "lt8920_test.h"
+#include "x-nucleo-6180xa1.h"
 #include <stdio.h>
 
 void clock_hsi_init(void);
@@ -19,23 +20,40 @@ int main()
     
     BSP_LED_Init(LED2);
     
+    BSP_PB_Init(BUTTON_USER, BUTTON_MODE_EXTI);
+    
     usart_init();
     printf("Controller starting...\r\n");
     
+    XNUCLEO6180XA1_GPIO_Init();
+    
 // -------------------------------------------------------------------------- //
 // RF module
     lt_init();
-    lt_test_1();
+
+    //lt_scanner_init();
+
+    lt_sender_init();
     
     while (1)
     {
-        BSP_LED_Toggle(LED2);
-        lt_scanner_test();
+        //BSP_LED_Toggle(LED2);
+        //lt_scanner_test();
         //lt_spi_test();
         //HAL_Delay(250);
     }
 }
 
+//
+void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
+{
+    if (GPIO_Pin == KEY_BUTTON_PIN)
+    {
+        BSP_LED_Toggle(LED2);
+        lt_sender_test();
+    }
+}
+
 
 void clock_hsi_init(void)
 {

+ 1 - 1
user/stm32l0xx_hal_conf.h

@@ -41,7 +41,7 @@
 /*#define HAL_FIREWALL_MODULE_ENABLED */
 #define HAL_FLASH_MODULE_ENABLED 
 #define HAL_GPIO_MODULE_ENABLED 
-/*#define HAL_I2C_MODULE_ENABLED */
+#define HAL_I2C_MODULE_ENABLED 
 /*#define HAL_I2S_MODULE_ENABLED */ 
 /*#define HAL_IWDG_MODULE_ENABLED */
 /*#define HAL_LCD_MODULE_ENABLED */

+ 125 - 118
user/stm32l0xx_it.c

@@ -1,118 +1,125 @@
-/**
-  ******************************************************************************
-  * @file    Templates/Src/stm32l0xx_it.c 
-  * @author  MCD Application Team
-  * @brief   Main Interrupt Service Routines.
-  *          This file provides template for all exceptions handler and 
-  *          peripherals interrupt service routine.
-  ******************************************************************************
-  * @attention
-  *
-  * Copyright (c) 2016 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 "stm32l0xx_it.h"
-#include "main.h"
-
-/** @addtogroup STM32L0xx_HAL_Examples
-  * @{
-  */
-
-/** @addtogroup Templates
-  * @{
-  */
-
-/* Private typedef -----------------------------------------------------------*/
-/* Private define ------------------------------------------------------------*/
-/* Private macro -------------------------------------------------------------*/
-/* Private variables ---------------------------------------------------------*/
-
-/* Private function prototypes -----------------------------------------------*/
-/* Private functions ---------------------------------------------------------*/
-
-/******************************************************************************/
-/*            Cortex-M0+ Processor Exceptions Handlers                         */
-/******************************************************************************/
-
-/**
-  * @brief   This function handles NMI exception.
-  * @param  None
-  * @retval None
-  */
-void NMI_Handler(void)
-{
-}
-
-/**
-  * @brief  This function handles Hard Fault exception.
-  * @param  None
-  * @retval None
-  */
-void HardFault_Handler(void)
-{
-  /* Go to infinite loop when Hard Fault exception occurs */
-  while (1)
-  {
-  }
-}
-
-/**
-  * @brief  This function handles SVCall exception.
-  * @param  None
-  * @retval None
-  */
-void SVC_Handler(void)
-{
-}
-
-/**
-  * @brief  This function handles PendSVC exception.
-  * @param  None
-  * @retval None
-  */
-void PendSV_Handler(void)
-{
-}
-
-/**
-  * @brief  This function handles SysTick Handler.
-  * @param  None
-  * @retval None
-  */
-void SysTick_Handler(void)
-{
-  HAL_IncTick();
-}
-
-/******************************************************************************/
-/*                 STM32L0xx Peripherals Interrupt Handlers                   */
-/*  Add here the Interrupt Handler for the used peripheral(s) (PPP), for the  */
-/*  available peripheral interrupt handler's name please refer to the startup */
-/*  file (startup_stm32l0xx.s).                                               */
-/******************************************************************************/
-
-/**
-  * @brief  This function handles PPP interrupt request.
-  * @param  None
-  * @retval None
-  */
-/*void PPP_IRQHandler(void)
-{
-}*/
-
-
-/**
-  * @}
-  */ 
-
-/**
-  * @}
-  */
+/**
+  ******************************************************************************
+  * @file    Templates/Src/stm32l0xx_it.c 
+  * @author  MCD Application Team
+  * @brief   Main Interrupt Service Routines.
+  *          This file provides template for all exceptions handler and 
+  *          peripherals interrupt service routine.
+  ******************************************************************************
+  * @attention
+  *
+  * Copyright (c) 2016 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 "stm32l0xx_it.h"
+#include "main.h"
+
+/** @addtogroup STM32L0xx_HAL_Examples
+  * @{
+  */
+
+/** @addtogroup Templates
+  * @{
+  */
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/******************************************************************************/
+/*            Cortex-M0+ Processor Exceptions Handlers                         */
+/******************************************************************************/
+
+/**
+  * @brief   This function handles NMI exception.
+  * @param  None
+  * @retval None
+  */
+void NMI_Handler(void)
+{
+}
+
+/**
+  * @brief  This function handles Hard Fault exception.
+  * @param  None
+  * @retval None
+  */
+void HardFault_Handler(void)
+{
+  /* Go to infinite loop when Hard Fault exception occurs */
+  while (1)
+  {
+  }
+}
+
+/**
+  * @brief  This function handles SVCall exception.
+  * @param  None
+  * @retval None
+  */
+void SVC_Handler(void)
+{
+}
+
+/**
+  * @brief  This function handles PendSVC exception.
+  * @param  None
+  * @retval None
+  */
+void PendSV_Handler(void)
+{
+}
+
+/**
+  * @brief  This function handles SysTick Handler.
+  * @param  None
+  * @retval None
+  */
+void SysTick_Handler(void)
+{
+  HAL_IncTick();
+}
+
+extern "C" {
+void EXTI4_15_IRQHandler(void)
+{
+    HAL_GPIO_EXTI_IRQHandler(KEY_BUTTON_PIN);
+}
+}
+
+/******************************************************************************/
+/*                 STM32L0xx Peripherals Interrupt Handlers                   */
+/*  Add here the Interrupt Handler for the used peripheral(s) (PPP), for the  */
+/*  available peripheral interrupt handler's name please refer to the startup */
+/*  file (startup_stm32l0xx.s).                                               */
+/******************************************************************************/
+
+/**
+  * @brief  This function handles PPP interrupt request.
+  * @param  None
+  * @retval None
+  */
+/*void PPP_IRQHandler(void)
+{
+}*/
+
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */

Некоторые файлы не были показаны из-за большого количества измененных файлов