295 lines
7.7 KiB
C
295 lines
7.7 KiB
C
//
|
|
// Created by Professional on 7/31/2023.
|
|
//
|
|
#include "stdint-gcc.h"
|
|
#include "vl6180_def.h"
|
|
#include "stm32g0xx_hal.h"
|
|
#include "vl6180_api.h"
|
|
#include "main.h"
|
|
#include "i2c.h"
|
|
|
|
#define max_scale 1
|
|
uint8_t changeScale = 0;
|
|
#define ALLOW_DISABLE_WAF_FROM_BLUE_BUTTON 1
|
|
#define theVL6180Dev 0x52 // what we use as "API device
|
|
#define def_i2c_time_out 100
|
|
#if VL6180_HAVE_DMAX_RANGING
|
|
#define DMaxDispTime 0 /* Set to 1000 to display Dmax during 1 sec when no target is detected */
|
|
#else
|
|
#define DMaxDispTime 0
|
|
#endif
|
|
#define OutORangeDispfTime 800
|
|
|
|
#define g_TickCnt uwTick
|
|
|
|
enum runmode_t{
|
|
RunRangePoll=0,
|
|
RunAlsPoll,
|
|
InitErr,
|
|
ScaleSwap,
|
|
WaitForReset,
|
|
AlrmStart,
|
|
AlrmRun,
|
|
FromSwitch,
|
|
};
|
|
|
|
char buffer[10];
|
|
|
|
struct state_t {
|
|
int OutofRAnge:1;
|
|
int AutoScale:1;
|
|
int FilterEn:1;
|
|
uint8_t mode;
|
|
int8_t ScaleSwapCnt;
|
|
uint8_t InitScale;
|
|
|
|
uint8_t CurAlrm;
|
|
uint8_t AlrmFired; /* just used to keep display at least min time */
|
|
}State;
|
|
|
|
uint32_t TimeStarted; /* various display and mode delay starting time */
|
|
VL6180_RangeData_t Range; /* Range measurmeent */
|
|
|
|
int alpha =(int)(0.85*(1<<16)); /* range distance running average cofs */
|
|
uint16_t range; /* range average distance */
|
|
|
|
#define AutoThreshHigh 80 /*auto scale high thresh => AutoThreshHigh * max_raneg => scale ++ */
|
|
#define AutoThreshLow 33 /*auto scale low thresh => AutoThreshHigh * max_raneg => scale ++ */
|
|
#define ErrRangeDispTime 0 /* Set to 800 ms to display error code when no target os detected */
|
|
#if ErrRangeDispTime == 0
|
|
/* supress Warning[Pe186]: pointless comparison of unsigned integer with zero */
|
|
# ifdef __ARMCC_VERSION /* ARM/KEIL */
|
|
# pragma diag_suppress 186
|
|
# endif /* _ARMCC_VERSION */
|
|
# ifdef __ICCARM__ /* IAR */
|
|
# pragma diag_suppress=Pe186
|
|
# endif /* _ARMCC_VERSION */
|
|
#endif
|
|
|
|
#define AlrmDispTime 800
|
|
|
|
#define AlarmKeepDispTime 250 /* alarm message retain time after it fires */
|
|
volatile int IntrFired=0;
|
|
|
|
|
|
uint8_t inited = 0;
|
|
void AbortErr( const char * msg ){
|
|
State.mode= WaitForReset;
|
|
}
|
|
|
|
void DoScalingSwap(int scaling){
|
|
|
|
State.mode = ScaleSwap;
|
|
TimeStarted=g_TickCnt;
|
|
}
|
|
uint8_t allowIT = 0;
|
|
void vl6180_init (void)
|
|
{
|
|
|
|
allowIT = 0;
|
|
HAL_GPIO_WritePin(CS_PROXIMITY_GPIO_Port, CS_PROXIMITY_Pin, GPIO_PIN_RESET);
|
|
HAL_Delay(200);
|
|
HAL_GPIO_WritePin(CS_PROXIMITY_GPIO_Port, CS_PROXIMITY_Pin, GPIO_PIN_SET);
|
|
HAL_Delay(200);
|
|
if (VL6180_WaitDeviceBooted(theVL6180Dev) )
|
|
{
|
|
return;
|
|
}
|
|
inited = 1;
|
|
VL6180_InitData(theVL6180Dev);
|
|
State.InitScale=VL6180_UpscaleGetScaling(theVL6180Dev);
|
|
State.FilterEn=VL6180_FilterGetState(theVL6180Dev);
|
|
VL6180_Prepare(theVL6180Dev);
|
|
VL6180_RangeSetMaxConvergenceTime(theVL6180Dev, 20);
|
|
VL6180_RangeSetInterMeasPeriod(theVL6180Dev, 25);
|
|
//State.InitScale=VL6180_UpscaleGetScaling(theVL6180Dev);
|
|
/* Enable Dmax calculation only if value is displayed (to save computation power) */
|
|
//VL6180_DMaxSetState(theVL6180Dev, DMaxDispTime>0);
|
|
VL6180_ClearAllInterrupt(theVL6180Dev);
|
|
VL6180_RangeStartSingleShot(theVL6180Dev);
|
|
allowIT = 1;
|
|
}
|
|
|
|
|
|
int VL6180_I2CRead(VL6180Dev_t addr, uint8_t *buff, uint8_t len){
|
|
int status;
|
|
status = HAL_I2C_Master_Receive(&hi2c2, addr, buff, len , def_i2c_time_out);
|
|
if( status ){
|
|
MX_I2C2_Init();
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
int VL6180_I2CWrite(VL6180Dev_t addr, uint8_t *buff, uint8_t len){
|
|
int status;
|
|
status = HAL_I2C_Master_Transmit(&hi2c2, addr, buff, len , def_i2c_time_out);
|
|
if( status ){
|
|
MX_I2C2_Init();
|
|
}
|
|
return status;
|
|
}
|
|
|
|
|
|
void RangeState(void) {
|
|
int status;
|
|
uint16_t hlimit;
|
|
uint8_t scaling;
|
|
VL6180_RangeGetMeasurement(theVL6180Dev, &Range );
|
|
scaling = VL6180_UpscaleGetScaling(theVL6180Dev);
|
|
if (Range.errorStatus) {
|
|
AbortErr("Er r");
|
|
return;
|
|
}
|
|
|
|
hlimit = VL6180_GetUpperLimit(theVL6180Dev);
|
|
if (Range.range_mm >= (hlimit * AutoThreshHigh) / 100 && scaling < 3 && State.AutoScale) {
|
|
VL6180_UpscaleSetScaling(theVL6180Dev, scaling + 1);
|
|
}
|
|
if (Range.range_mm < (hlimit * AutoThreshLow) / 100 && scaling > 1 && State.AutoScale) {
|
|
VL6180_UpscaleSetScaling(theVL6180Dev, scaling - 1);
|
|
}
|
|
|
|
if (Range.errorStatus) {
|
|
/* no valid ranging*/
|
|
if (State.OutofRAnge) {
|
|
#if VL6180_HAVE_DMAX_RANGING
|
|
if (g_TickCnt - TimeStarted >= ErrRangeDispTime && g_TickCnt - TimeStarted < ErrRangeDispTime + DMaxDispTime ){
|
|
}
|
|
else
|
|
|
|
#endif
|
|
if(g_TickCnt - TimeStarted < ErrRangeDispTime )
|
|
{
|
|
|
|
}
|
|
else{
|
|
State.OutofRAnge=0; /* back to out of range display */
|
|
TimeStarted=g_TickCnt;
|
|
}
|
|
}
|
|
else {
|
|
int FilterEn;
|
|
#if VL6180_WRAP_AROUND_FILTER_SUPPORT
|
|
FilterEn = VL6180_FilterGetState(theVL6180Dev);
|
|
#else
|
|
#endif
|
|
if( g_TickCnt - TimeStarted > OutORangeDispfTime ) {
|
|
State.OutofRAnge = 1;
|
|
TimeStarted = g_TickCnt;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
State.OutofRAnge = 0;
|
|
TimeStarted = g_TickCnt;
|
|
range = (range * alpha + Range.range_mm * ((1 << 16) - alpha)) >> 16;
|
|
if (State.AutoScale) {
|
|
if (scaling == 1) {
|
|
buffer[0] = '_';
|
|
}
|
|
else
|
|
if (scaling == 2)
|
|
buffer[0] = '=';
|
|
else
|
|
buffer[0] = '~';
|
|
}
|
|
|
|
}
|
|
|
|
if (changeScale == 1) {
|
|
changeScale = 0;
|
|
TimeStarted = g_TickCnt;
|
|
|
|
State.ScaleSwapCnt++;
|
|
if (State.ScaleSwapCnt % (max_scale + 1) == max_scale) {
|
|
State.AutoScale = 1;
|
|
scaling = max_scale;
|
|
}
|
|
else {
|
|
#if ALLOW_DISABLE_WAF_FROM_BLUE_BUTTON
|
|
/* togle filtering every time we roll over all scaling(pass by autoscale) */
|
|
if (State.AutoScale)
|
|
State.FilterEn = !State.FilterEn;
|
|
#endif
|
|
State.AutoScale = 0;
|
|
scaling = State.InitScale + (State.ScaleSwapCnt % max_scale);
|
|
if (scaling > max_scale)
|
|
scaling = scaling - (max_scale);
|
|
}
|
|
|
|
status = VL6180_UpscaleSetScaling(theVL6180Dev, scaling);
|
|
if (status<0) {
|
|
AbortErr("ErUp");
|
|
State.mode = InitErr;
|
|
}
|
|
else {
|
|
/* do not check status may fail when filter support not active */
|
|
VL6180_FilterSetState(theVL6180Dev, State.FilterEn);
|
|
DoScalingSwap(scaling);
|
|
}
|
|
}
|
|
}
|
|
uint32_t resetPressedMs = 0;
|
|
uint8_t motionDetected = 0;
|
|
__weak void proximityMessureCompleted (void)
|
|
{
|
|
|
|
}
|
|
|
|
uint8_t getRange (VL6180_RangeData_t* range)
|
|
{
|
|
if (Range.errorStatus == 0)
|
|
{
|
|
*range = Range;
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
range->range_mm = -1;
|
|
return 1;
|
|
}
|
|
}
|
|
void HAL_GPIO_EXTI_Rising_Callback(uint16_t GPIO_Pin)
|
|
{
|
|
if (GPIO_Pin == GPIO_PIN_0 && allowIT == 1)
|
|
{
|
|
RangeState();
|
|
proximityMessureCompleted();
|
|
VL6180_ClearAllInterrupt(theVL6180Dev);
|
|
}
|
|
else if (GPIO_Pin == GPIO_PIN_1)
|
|
{
|
|
uint32_t res = uwTick - resetPressedMs;
|
|
if (res > 2000 && resetPressedMs > 0 )
|
|
HAL_NVIC_SystemReset();
|
|
resetPressedMs = 0;
|
|
}
|
|
}
|
|
|
|
void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)
|
|
{
|
|
|
|
if (GPIO_Pin == GPIO_PIN_1)
|
|
{
|
|
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_RESET)
|
|
{
|
|
resetPressedMs = uwTick;
|
|
}
|
|
}
|
|
}
|
|
/* USER CODE END 4 */
|
|
|
|
uint8_t vl6180_single_shot ()
|
|
{
|
|
VL6180_RangeStartSingleShot(theVL6180Dev);
|
|
VL6180_ClearAllInterrupt(theVL6180Dev);
|
|
|
|
}
|
|
|
|
int32_t vl6180_is_ready ()
|
|
{
|
|
if (inited < 0)
|
|
return -1;
|
|
return VL6180_RangeWaitDeviceReady(theVL6180Dev, 3);
|
|
} |