| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153 |
- /**
- * @file VL6180_ATY.c
- *
- * @param Project DEVICE_GENERAL_ATY_LIB
- *
- * @author ATY
- *
- * @copyright
- * - Copyright 2017 - 2026 MZ-ATY
- * - This code follows:
- * - MZ-ATY Various Contents Joint Statement -
- * <a href="https://mengze.top/MZ-ATY_VCJS">
- * https://mengze.top/MZ-ATY_VCJS</a>
- * - CC 4.0 BY-NC-SA -
- * <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
- * https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
- * - Your use will be deemed to have accepted the terms of this statement.
- *
- * @brief functions of VL6180 proximity and ambient light sensor for all embedded device
- *
- * @version
- * - 1_00_250101 > ATY
- * -# Initial version, support I2C communication, range and ALS measurement
- ********************************************************************************
- */
- #include "VL6180_ATY.h"
- /******************************* Private Functions *****************************/
- /**
- * @brief Check if device is initialized, auto-initialize if not
- * @param dev Pointer to VL6180 device structure
- * @return VL6180_STATUS_OK if successful
- */
- static uint8_t VL6180_CheckAndAutoInit(struct VL6180_ATY_Dev *dev)
- {
- if (!dev->initialized) {
- if (dev->debugEnable && dev->LOG) {
- dev->LOG("VL6180: Auto-initializing device...\n");
- }
- return VL6180_Init(dev);
- }
- return VL6180_STATUS_OK;
- }
- /**
- * @brief VL6180 default initialization settings
- * @param dev Pointer to VL6180 device structure
- * @return VL6180_STATUS_OK if successful
- */
- static uint8_t VL6180_ApplyDefaultSettings(struct VL6180_ATY_Dev *dev)
- {
- // Mandatory: Private registers
- VL6180_WriteRegister8(dev, 0x0207, 0x01);
- VL6180_WriteRegister8(dev, 0x0208, 0x01);
- VL6180_WriteRegister8(dev, 0x0096, 0x00);
- VL6180_WriteRegister8(dev, 0x0097, 0xfd);
- VL6180_WriteRegister8(dev, 0x00e3, 0x00);
- VL6180_WriteRegister8(dev, 0x00e4, 0x04);
- VL6180_WriteRegister8(dev, 0x00e5, 0x02);
- VL6180_WriteRegister8(dev, 0x00e6, 0x01);
- VL6180_WriteRegister8(dev, 0x00e7, 0x03);
- VL6180_WriteRegister8(dev, 0x00f5, 0x02);
- VL6180_WriteRegister8(dev, 0x00d9, 0x05);
- VL6180_WriteRegister8(dev, 0x00db, 0xce);
- VL6180_WriteRegister8(dev, 0x00dc, 0x03);
- VL6180_WriteRegister8(dev, 0x00dd, 0xf8);
- VL6180_WriteRegister8(dev, 0x009f, 0x00);
- VL6180_WriteRegister8(dev, 0x00a3, 0x3c);
- VL6180_WriteRegister8(dev, 0x00b7, 0x00);
- VL6180_WriteRegister8(dev, 0x00bb, 0x3c);
- VL6180_WriteRegister8(dev, 0x00b2, 0x09);
- VL6180_WriteRegister8(dev, 0x00ca, 0x09);
- VL6180_WriteRegister8(dev, 0x0198, 0x01);
- VL6180_WriteRegister8(dev, 0x01b0, 0x17);
- VL6180_WriteRegister8(dev, 0x01ad, 0x00);
- VL6180_WriteRegister8(dev, 0x00ff, 0x05);
- VL6180_WriteRegister8(dev, 0x0100, 0x05);
- VL6180_WriteRegister8(dev, 0x0199, 0x05);
- VL6180_WriteRegister8(dev, 0x01a6, 0x1b);
- VL6180_WriteRegister8(dev, 0x01ac, 0x3e);
- VL6180_WriteRegister8(dev, 0x01a7, 0x1f);
- VL6180_WriteRegister8(dev, 0x0030, 0x00);
- // Recommended: Public registers - See data sheet for more detail
- VL6180_WriteRegister8(dev, VL6180_REG_SYSTEM_MODE_GPIO1, 0x10); // Enables polling for 'New Sample ready'
- VL6180_WriteRegister8(dev, VL6180_REG_READOUT_AVERAGING_SAMPLE_PERIOD, 0x30); // Set the averaging sample period
- VL6180_WriteRegister8(dev, VL6180_REG_SYSALS_ANALOGUE_GAIN, 0x46); // Light sensor gain settings
- VL6180_WriteRegister8(dev, VL6180_REG_SYSRANGE_VHV_REPEAT_RATE, 0xFF); // Set auto calibration period
- VL6180_WriteRegister8(dev, VL6180_REG_SYSALS_INTEGRATION_PERIOD, 0x63); // ALS integration time
- VL6180_WriteRegister8(dev, VL6180_REG_SYSRANGE_VHV_RECALIBRATE, 0x01); // perform a single temperature calibration
- VL6180_WriteRegister8(dev, VL6180_REG_SYSRANGE_INTERMEASUREMENT_PERIOD, 0x09); // Set default ranging inter-measurement period to 100ms
- VL6180_WriteRegister8(dev, VL6180_REG_SYSALS_INTERMEASUREMENT_PERIOD, 0x31); // Set default ALS inter-measurement period to 500ms
- VL6180_WriteRegister8(dev, VL6180_REG_SYSTEM_INTERRUPT_CONFIG_GPIO, 0x24); // Configures interrupt on 'New Sample Ready threshold event'
- // Clear fresh out of reset flag
- VL6180_WriteRegister8(dev, VL6180_REG_SYSTEM_FRESH_OUT_OF_RESET, 0x00);
- return VL6180_STATUS_OK;
- }
- /******************************* Public Functions *****************************/
- /**
- * @brief Initialize VL6180 device
- * @param dev Pointer to VL6180 device structure
- * @return VL6180_STATUS_OK if successful
- */
- uint8_t VL6180_Init(struct VL6180_ATY_Dev *dev)
- {
- if (!dev) {
- return VL6180_STATUS_ERROR;
- }
- if (dev->debugEnable && dev->LOG) {
- dev->LOG("VL6180: Initializing device...\n");
- }
- // Set default I2C address if not set
- if (dev->i2cAddress == 0) {
- dev->i2cAddress = VL6180_I2C_ADDR_DEFAULT;
- }
- // Check if device is present
- uint8_t modelId;
- if (VL6180_ReadRegister8(dev, VL6180_REG_IDENTIFICATION_MODEL_ID, &modelId) != VL6180_STATUS_OK) {
- dev->devicePresent = 0;
- dev->lastStatus = VL6180_STATUS_NO_DEVICE;
- if (dev->debugEnable && dev->LOG) {
- dev->LOG("VL6180: Device not found!\n");
- }
- return VL6180_STATUS_NO_DEVICE;
- }
- if (modelId != 0xB4) {
- dev->devicePresent = 0;
- dev->lastStatus = VL6180_STATUS_NO_DEVICE;
- if (dev->debugEnable && dev->LOG) {
- dev->LOG("VL6180: Invalid model ID: 0x%02X\n", modelId);
- }
- return VL6180_STATUS_NO_DEVICE;
- }
- dev->devicePresent = 1;
- dev->modelId = modelId;
- // Read device identification
- VL6180_ReadDeviceID(dev);
- // Check if fresh out of reset
- uint8_t freshOutOfReset;
- VL6180_ReadRegister8(dev, VL6180_REG_SYSTEM_FRESH_OUT_OF_RESET, &freshOutOfReset);
- dev->freshOutOfReset = freshOutOfReset;
- if (freshOutOfReset == 0x01) {
- // Apply default settings
- VL6180_ApplyDefaultSettings(dev);
- if (dev->debugEnable && dev->LOG) {
- dev->LOG("VL6180: Applied default settings\n");
- }
- }
- // Set default configuration
- dev->alsGain = VL6180_ALS_GAIN_1;
- dev->alsIntegrationPeriod = 100;
- dev->rangeMaxConvergenceTime = 50;
- dev->rangeOffset = 0;
- dev->crosstalkCompensationRate = 0;
- dev->initialized = 1;
- dev->lastStatus = VL6180_STATUS_OK;
- if (dev->debugEnable && dev->LOG) {
- dev->LOG("VL6180: Initialization completed successfully\n");
- }
- return VL6180_STATUS_OK;
- }
- /**
- * @brief Reset VL6180 device
- * @param dev Pointer to VL6180 device structure
- * @return VL6180_STATUS_OK if successful
- */
- uint8_t VL6180_Reset(struct VL6180_ATY_Dev *dev)
- {
- if (!dev) {
- return VL6180_STATUS_ERROR;
- }
- if (dev->debugEnable && dev->LOG) {
- dev->LOG("VL6180: Resetting device...\n");
- }
- // Clear all interrupt flags
- VL6180_WriteRegister8(dev, VL6180_REG_SYSTEM_INTERRUPT_CLEAR, 0x07);
- // Reset device state
- dev->initialized = 0;
- dev->devicePresent = 0;
- dev->rangeValue = 0;
- dev->alsValue = 0;
- dev->rangeStatus = 0;
- dev->alsStatus = 0;
- dev->lastStatus = VL6180_STATUS_OK;
- return VL6180_STATUS_OK;
- }
- /**
- * @brief Read device identification information
- * @param dev Pointer to VL6180 device structure
- * @return VL6180_STATUS_OK if successful
- */
- uint8_t VL6180_ReadDeviceID(struct VL6180_ATY_Dev *dev)
- {
- if (!dev) {
- return VL6180_STATUS_ERROR;
- }
- VL6180_ReadRegister8(dev, VL6180_REG_IDENTIFICATION_MODEL_ID, &dev->modelId);
- VL6180_ReadRegister8(dev, VL6180_REG_IDENTIFICATION_MODEL_REV_MAJOR, &dev->modelRevMajor);
- VL6180_ReadRegister8(dev, VL6180_REG_IDENTIFICATION_MODEL_REV_MINOR, &dev->modelRevMinor);
- VL6180_ReadRegister8(dev, VL6180_REG_IDENTIFICATION_MODULE_REV_MAJOR, &dev->moduleRevMajor);
- VL6180_ReadRegister8(dev, VL6180_REG_IDENTIFICATION_MODULE_REV_MINOR, &dev->moduleRevMinor);
- if (dev->debugEnable && dev->LOG) {
- dev->LOG("VL6180: Model ID: 0x%02X, Rev: %d.%d, Module Rev: %d.%d\n",
- dev->modelId, dev->modelRevMajor, dev->modelRevMinor,
- dev->moduleRevMajor, dev->moduleRevMinor);
- }
- return VL6180_STATUS_OK;
- }
- /**
- * @brief Load default settings to VL6180
- * @param dev Pointer to VL6180 device structure
- * @return VL6180_STATUS_OK if successful
- */
- uint8_t VL6180_LoadDefaultSettings(struct VL6180_ATY_Dev *dev)
- {
- if (!dev) {
- return VL6180_STATUS_ERROR;
- }
- return VL6180_ApplyDefaultSettings(dev);
- }
- /******************************* Range Measurement Functions *****************/
- /**
- * @brief Start range measurement
- * @param dev Pointer to VL6180 device structure
- * @param mode Measurement mode (single shot or continuous)
- * @return VL6180_STATUS_OK if successful
- */
- uint8_t VL6180_StartRangeMeasurement(struct VL6180_ATY_Dev *dev, uint8_t mode)
- {
- if (!dev) {
- return VL6180_STATUS_ERROR;
- }
- // Auto-initialize if not initialized
- uint8_t status = VL6180_CheckAndAutoInit(dev);
- if (status != VL6180_STATUS_OK) {
- return status;
- }
- if (dev->lock) {
- if (dev->debugEnable && dev->LOG) {
- dev->LOG("VL6180: Device is locked\n");
- }
- return VL6180_STATUS_ERROR;
- }
- dev->lock = 1;
- if (dev->debugEnable && dev->LOG) {
- dev->LOG("VL6180: Starting range measurement (mode: %d)\n", mode);
- }
- // Clear any existing interrupts
- VL6180_ClearRangeInterrupt(dev);
- // Start measurement
- status = VL6180_WriteRegister8(dev, VL6180_REG_SYSRANGE_START, mode);
- dev->lock = 0;
- dev->lastStatus = status;
- return status;
- }
- /**
- * @brief Read range measurement result
- * @param dev Pointer to VL6180 device structure
- * @return VL6180_STATUS_OK if successful
- */
- uint8_t VL6180_ReadRangeResult(struct VL6180_ATY_Dev *dev)
- {
- if (!dev) {
- return VL6180_STATUS_ERROR;
- }
- // Auto-initialize if not initialized
- uint8_t status = VL6180_CheckAndAutoInit(dev);
- if (status != VL6180_STATUS_OK) {
- return status;
- }
- if (dev->lock) {
- return VL6180_STATUS_ERROR;
- }
- dev->lock = 1;
- // Read range value
- VL6180_ReadRegister8(dev, VL6180_REG_RESULT_RANGE_VAL, &dev->rangeValue);
- // Read range status
- VL6180_ReadRegister8(dev, VL6180_REG_RESULT_RANGE_STATUS, &dev->rangeStatus);
- // Read additional range data
- VL6180_ReadRegister16(dev, VL6180_REG_RESULT_RANGE_RAW, &dev->rangeRaw);
- VL6180_ReadRegister16(dev, VL6180_REG_RESULT_RANGE_RETURN_RATE, &dev->rangeRate);
- VL6180_ReadRegister32(dev, VL6180_REG_RESULT_RANGE_RETURN_SIGNAL_COUNT, &dev->rangeSignalCount);
- VL6180_ReadRegister32(dev, VL6180_REG_RESULT_RANGE_RETURN_AMB_COUNT, &dev->rangeAmbientCount);
- VL6180_ReadRegister16(dev, VL6180_REG_RESULT_RANGE_RETURN_CONV_TIME, &dev->rangeConvergenceTime);
- if (dev->debugEnable && dev->LOG) {
- dev->LOG("VL6180: Range: %dmm, Status: 0x%02X, Rate: %d\n",
- dev->rangeValue, dev->rangeStatus, dev->rangeRate);
- }
- dev->lock = 0;
- dev->lastStatus = VL6180_STATUS_OK;
- return VL6180_STATUS_OK;
- }
- /**
- * @brief Get range measurement value
- * @param dev Pointer to VL6180 device structure
- * @return Range value in millimeters
- */
- uint8_t VL6180_GetRangeValue(struct VL6180_ATY_Dev *dev)
- {
- if (!dev) {
- return 0;
- }
- return dev->rangeValue;
- }
- /**
- * @brief Check if range measurement is ready
- * @param dev Pointer to VL6180 device structure
- * @return 1 if ready, 0 if not ready
- */
- uint8_t VL6180_IsRangeReady(struct VL6180_ATY_Dev *dev)
- {
- if (!dev) {
- return 0;
- }
- uint8_t status;
- VL6180_ReadRegister8(dev, VL6180_REG_RESULT_INTERRUPT_STATUS_GPIO, &status);
- return (status & 0x04) ? 1 : 0;
- }
- /**
- * @brief Clear range interrupt
- * @param dev Pointer to VL6180 device structure
- * @return VL6180_STATUS_OK if successful
- */
- uint8_t VL6180_ClearRangeInterrupt(struct VL6180_ATY_Dev *dev)
- {
- if (!dev) {
- return VL6180_STATUS_ERROR;
- }
- return VL6180_WriteRegister8(dev, VL6180_REG_SYSTEM_INTERRUPT_CLEAR, 0x01);
- }
- /******************************* ALS Measurement Functions *******************/
- /**
- * @brief Start ALS measurement
- * @param dev Pointer to VL6180 device structure
- * @param mode Measurement mode (single shot or continuous)
- * @return VL6180_STATUS_OK if successful
- */
- uint8_t VL6180_StartALSMeasurement(struct VL6180_ATY_Dev *dev, uint8_t mode)
- {
- if (!dev) {
- return VL6180_STATUS_ERROR;
- }
- // Auto-initialize if not initialized
- uint8_t status = VL6180_CheckAndAutoInit(dev);
- if (status != VL6180_STATUS_OK) {
- return status;
- }
- if (dev->lock) {
- if (dev->debugEnable && dev->LOG) {
- dev->LOG("VL6180: Device is locked\n");
- }
- return VL6180_STATUS_ERROR;
- }
- dev->lock = 1;
- if (dev->debugEnable && dev->LOG) {
- dev->LOG("VL6180: Starting ALS measurement (mode: %d)\n", mode);
- }
- // Clear any existing interrupts
- VL6180_ClearALSInterrupt(dev);
- // Start measurement
- status = VL6180_WriteRegister8(dev, VL6180_REG_SYSALS_START, mode);
- dev->lock = 0;
- dev->lastStatus = status;
- return status;
- }
- /**
- * @brief Read ALS measurement result
- * @param dev Pointer to VL6180 device structure
- * @return VL6180_STATUS_OK if successful
- */
- uint8_t VL6180_ReadALSResult(struct VL6180_ATY_Dev *dev)
- {
- if (!dev) {
- return VL6180_STATUS_ERROR;
- }
- // Auto-initialize if not initialized
- uint8_t status = VL6180_CheckAndAutoInit(dev);
- if (status != VL6180_STATUS_OK) {
- return status;
- }
- if (dev->lock) {
- return VL6180_STATUS_ERROR;
- }
- dev->lock = 1;
- // Read ALS value
- VL6180_ReadRegister16(dev, VL6180_REG_RESULT_ALS_VAL, &dev->alsValue);
- // Read ALS status
- VL6180_ReadRegister8(dev, VL6180_REG_RESULT_ALS_STATUS, &dev->alsStatus);
- if (dev->debugEnable && dev->LOG) {
- dev->LOG("VL6180: ALS: %d counts, Status: 0x%02X\n",
- dev->alsValue, dev->alsStatus);
- }
- dev->lock = 0;
- dev->lastStatus = VL6180_STATUS_OK;
- return VL6180_STATUS_OK;
- }
- /**
- * @brief Get ALS measurement value
- * @param dev Pointer to VL6180 device structure
- * @return ALS value in counts
- */
- uint16_t VL6180_GetALSValue(struct VL6180_ATY_Dev *dev)
- {
- if (!dev) {
- return 0;
- }
- return dev->alsValue;
- }
- /**
- * @brief Check if ALS measurement is ready
- * @param dev Pointer to VL6180 device structure
- * @return 1 if ready, 0 if not ready
- */
- uint8_t VL6180_IsALSReady(struct VL6180_ATY_Dev *dev)
- {
- if (!dev) {
- return 0;
- }
- uint8_t status;
- VL6180_ReadRegister8(dev, VL6180_REG_RESULT_INTERRUPT_STATUS_GPIO, &status);
- return (status & 0x20) ? 1 : 0;
- }
- /**
- * @brief Clear ALS interrupt
- * @param dev Pointer to VL6180 device structure
- * @return VL6180_STATUS_OK if successful
- */
- uint8_t VL6180_ClearALSInterrupt(struct VL6180_ATY_Dev *dev)
- {
- if (!dev) {
- return VL6180_STATUS_ERROR;
- }
- return VL6180_WriteRegister8(dev, VL6180_REG_SYSTEM_INTERRUPT_CLEAR, 0x02);
- }
- /******************************* Configuration Functions *********************/
- /**
- * @brief Set range measurement thresholds
- * @param dev Pointer to VL6180 device structure
- * @param low Low threshold in mm
- * @param high High threshold in mm
- * @return VL6180_STATUS_OK if successful
- */
- uint8_t VL6180_SetRangeThresholds(struct VL6180_ATY_Dev *dev, uint8_t low, uint8_t high)
- {
- if (!dev) {
- return VL6180_STATUS_ERROR;
- }
- dev->rangeThresholdLow = low;
- dev->rangeThresholdHigh = high;
- VL6180_WriteRegister8(dev, VL6180_REG_SYSRANGE_THRESH_LOW, low);
- VL6180_WriteRegister8(dev, VL6180_REG_SYSRANGE_THRESH_HIGH, high);
- return VL6180_STATUS_OK;
- }
- /**
- * @brief Set ALS measurement thresholds
- * @param dev Pointer to VL6180 device structure
- * @param low Low threshold in counts
- * @param high High threshold in counts
- * @return VL6180_STATUS_OK if successful
- */
- uint8_t VL6180_SetALSThresholds(struct VL6180_ATY_Dev *dev, uint16_t low, uint16_t high)
- {
- if (!dev) {
- return VL6180_STATUS_ERROR;
- }
- dev->alsThresholdLow = low;
- dev->alsThresholdHigh = high;
- VL6180_WriteRegister16(dev, VL6180_REG_SYSALS_THRESH_LOW, low);
- VL6180_WriteRegister16(dev, VL6180_REG_SYSALS_THRESH_HIGH, high);
- return VL6180_STATUS_OK;
- }
- /**
- * @brief Set ALS gain
- * @param dev Pointer to VL6180 device structure
- * @param gain ALS gain setting
- * @return VL6180_STATUS_OK if successful
- */
- uint8_t VL6180_SetALSGain(struct VL6180_ATY_Dev *dev, uint8_t gain)
- {
- if (!dev) {
- return VL6180_STATUS_ERROR;
- }
- if (gain > VL6180_ALS_GAIN_40) {
- return VL6180_STATUS_ERROR;
- }
- dev->alsGain = gain;
- return VL6180_WriteRegister8(dev, VL6180_REG_SYSALS_ANALOGUE_GAIN, (0x40 | gain));
- }
- /**
- * @brief Set ALS integration period
- * @param dev Pointer to VL6180 device structure
- * @param period Integration period in ms (1-512ms)
- * @return VL6180_STATUS_OK if successful
- */
- uint8_t VL6180_SetALSIntegrationPeriod(struct VL6180_ATY_Dev *dev, uint16_t period)
- {
- if (!dev) {
- return VL6180_STATUS_ERROR;
- }
- if (period < 1 || period > 512) {
- return VL6180_STATUS_ERROR;
- }
- dev->alsIntegrationPeriod = period;
- return VL6180_WriteRegister16(dev, VL6180_REG_SYSALS_INTEGRATION_PERIOD, period - 1);
- }
- /**
- * @brief Set range offset calibration
- * @param dev Pointer to VL6180 device structure
- * @param offset Offset value in mm (-128 to +127)
- * @return VL6180_STATUS_OK if successful
- */
- uint8_t VL6180_SetRangeOffset(struct VL6180_ATY_Dev *dev, int8_t offset)
- {
- if (!dev) {
- return VL6180_STATUS_ERROR;
- }
- dev->rangeOffset = offset;
- return VL6180_WriteRegister8(dev, VL6180_REG_SYSRANGE_PART_TO_PART_RANGE_OFFSET, (uint8_t)offset);
- }
- /**
- * @brief Set crosstalk compensation
- * @param dev Pointer to VL6180 device structure
- * @param rate Crosstalk compensation rate
- * @return VL6180_STATUS_OK if successful
- */
- uint8_t VL6180_SetCrosstalkCompensation(struct VL6180_ATY_Dev *dev, uint16_t rate)
- {
- if (!dev) {
- return VL6180_STATUS_ERROR;
- }
- dev->crosstalkCompensationRate = rate;
- return VL6180_WriteRegister16(dev, VL6180_REG_SYSRANGE_CROSSTALK_COMPENSATION_RATE, rate);
- }
- /******************************* I2C Register Access Functions ***************/
- /**
- * @brief Write 8-bit register
- * @param dev Pointer to VL6180 device structure
- * @param reg Register address
- * @param data Data to write
- * @return VL6180_STATUS_OK if successful
- */
- uint8_t VL6180_WriteRegister8(struct VL6180_ATY_Dev *dev, uint16_t reg, uint8_t data)
- {
- if (!dev || !dev->i2cStart || !dev->i2cStop || !dev->i2cWriteByte) {
- return VL6180_STATUS_ERROR;
- }
- // Start I2C transaction
- if (dev->i2cStart() != 0) {
- return VL6180_STATUS_ERROR;
- }
- // Send device address with write bit
- if (dev->i2cWriteByte((dev->i2cAddress << 1) | 0x00) != 0) {
- dev->i2cStop();
- return VL6180_STATUS_ERROR;
- }
- // Send register address (16-bit, MSB first)
- if (dev->i2cWriteByte((reg >> 8) & 0xFF) != 0) {
- dev->i2cStop();
- return VL6180_STATUS_ERROR;
- }
- if (dev->i2cWriteByte(reg & 0xFF) != 0) {
- dev->i2cStop();
- return VL6180_STATUS_ERROR;
- }
- // Send data
- if (dev->i2cWriteByte(data) != 0) {
- dev->i2cStop();
- return VL6180_STATUS_ERROR;
- }
- // Stop I2C transaction
- dev->i2cStop();
- return VL6180_STATUS_OK;
- }
- /**
- * @brief Write 16-bit register
- * @param dev Pointer to VL6180 device structure
- * @param reg Register address
- * @param data Data to write
- * @return VL6180_STATUS_OK if successful
- */
- uint8_t VL6180_WriteRegister16(struct VL6180_ATY_Dev *dev, uint16_t reg, uint16_t data)
- {
- if (!dev || !dev->i2cStart || !dev->i2cStop || !dev->i2cWriteByte) {
- return VL6180_STATUS_ERROR;
- }
- // Start I2C transaction
- if (dev->i2cStart() != 0) {
- return VL6180_STATUS_ERROR;
- }
- // Send device address with write bit
- if (dev->i2cWriteByte((dev->i2cAddress << 1) | 0x00) != 0) {
- dev->i2cStop();
- return VL6180_STATUS_ERROR;
- }
- // Send register address (16-bit, MSB first)
- if (dev->i2cWriteByte((reg >> 8) & 0xFF) != 0) {
- dev->i2cStop();
- return VL6180_STATUS_ERROR;
- }
- if (dev->i2cWriteByte(reg & 0xFF) != 0) {
- dev->i2cStop();
- return VL6180_STATUS_ERROR;
- }
- // Send data (16-bit, MSB first)
- if (dev->i2cWriteByte((data >> 8) & 0xFF) != 0) {
- dev->i2cStop();
- return VL6180_STATUS_ERROR;
- }
- if (dev->i2cWriteByte(data & 0xFF) != 0) {
- dev->i2cStop();
- return VL6180_STATUS_ERROR;
- }
- // Stop I2C transaction
- dev->i2cStop();
- return VL6180_STATUS_OK;
- }
- /**
- * @brief Write 32-bit register
- * @param dev Pointer to VL6180 device structure
- * @param reg Register address
- * @param data Data to write
- * @return VL6180_STATUS_OK if successful
- */
- uint8_t VL6180_WriteRegister32(struct VL6180_ATY_Dev *dev, uint16_t reg, uint32_t data)
- {
- if (!dev || !dev->i2cStart || !dev->i2cStop || !dev->i2cWriteByte) {
- return VL6180_STATUS_ERROR;
- }
- // Start I2C transaction
- if (dev->i2cStart() != 0) {
- return VL6180_STATUS_ERROR;
- }
- // Send device address with write bit
- if (dev->i2cWriteByte((dev->i2cAddress << 1) | 0x00) != 0) {
- dev->i2cStop();
- return VL6180_STATUS_ERROR;
- }
- // Send register address (16-bit, MSB first)
- if (dev->i2cWriteByte((reg >> 8) & 0xFF) != 0) {
- dev->i2cStop();
- return VL6180_STATUS_ERROR;
- }
- if (dev->i2cWriteByte(reg & 0xFF) != 0) {
- dev->i2cStop();
- return VL6180_STATUS_ERROR;
- }
- // Send data (32-bit, MSB first)
- if (dev->i2cWriteByte((data >> 24) & 0xFF) != 0) {
- dev->i2cStop();
- return VL6180_STATUS_ERROR;
- }
- if (dev->i2cWriteByte((data >> 16) & 0xFF) != 0) {
- dev->i2cStop();
- return VL6180_STATUS_ERROR;
- }
- if (dev->i2cWriteByte((data >> 8) & 0xFF) != 0) {
- dev->i2cStop();
- return VL6180_STATUS_ERROR;
- }
- if (dev->i2cWriteByte(data & 0xFF) != 0) {
- dev->i2cStop();
- return VL6180_STATUS_ERROR;
- }
- // Stop I2C transaction
- dev->i2cStop();
- return VL6180_STATUS_OK;
- }
- /**
- * @brief Read 8-bit register
- * @param dev Pointer to VL6180 device structure
- * @param reg Register address
- * @param data Pointer to store read data
- * @return VL6180_STATUS_OK if successful
- */
- uint8_t VL6180_ReadRegister8(struct VL6180_ATY_Dev *dev, uint16_t reg, uint8_t *data)
- {
- if (!dev || !data || !dev->i2cStart || !dev->i2cStop || !dev->i2cWriteByte || !dev->i2cReadByte) {
- return VL6180_STATUS_ERROR;
- }
- // Start I2C transaction for write
- if (dev->i2cStart() != 0) {
- return VL6180_STATUS_ERROR;
- }
- // Send device address with write bit
- if (dev->i2cWriteByte((dev->i2cAddress << 1) | 0x00) != 0) {
- dev->i2cStop();
- return VL6180_STATUS_ERROR;
- }
- // Send register address (16-bit, MSB first)
- if (dev->i2cWriteByte((reg >> 8) & 0xFF) != 0) {
- dev->i2cStop();
- return VL6180_STATUS_ERROR;
- }
- if (dev->i2cWriteByte(reg & 0xFF) != 0) {
- dev->i2cStop();
- return VL6180_STATUS_ERROR;
- }
- // Restart for read
- if (dev->i2cStart() != 0) {
- dev->i2cStop();
- return VL6180_STATUS_ERROR;
- }
- // Send device address with read bit
- if (dev->i2cWriteByte((dev->i2cAddress << 1) | 0x01) != 0) {
- dev->i2cStop();
- return VL6180_STATUS_ERROR;
- }
- // Read data
- *data = dev->i2cReadByte(0); // NACK for last byte
- // Stop I2C transaction
- dev->i2cStop();
- return VL6180_STATUS_OK;
- }
- /**
- * @brief Read 16-bit register
- * @param dev Pointer to VL6180 device structure
- * @param reg Register address
- * @param data Pointer to store read data
- * @return VL6180_STATUS_OK if successful
- */
- uint8_t VL6180_ReadRegister16(struct VL6180_ATY_Dev *dev, uint16_t reg, uint16_t *data)
- {
- if (!dev || !data || !dev->i2cStart || !dev->i2cStop || !dev->i2cWriteByte || !dev->i2cReadByte) {
- return VL6180_STATUS_ERROR;
- }
- // Start I2C transaction for write
- if (dev->i2cStart() != 0) {
- return VL6180_STATUS_ERROR;
- }
- // Send device address with write bit
- if (dev->i2cWriteByte((dev->i2cAddress << 1) | 0x00) != 0) {
- dev->i2cStop();
- return VL6180_STATUS_ERROR;
- }
- // Send register address (16-bit, MSB first)
- if (dev->i2cWriteByte((reg >> 8) & 0xFF) != 0) {
- dev->i2cStop();
- return VL6180_STATUS_ERROR;
- }
- if (dev->i2cWriteByte(reg & 0xFF) != 0) {
- dev->i2cStop();
- return VL6180_STATUS_ERROR;
- }
- // Restart for read
- if (dev->i2cStart() != 0) {
- dev->i2cStop();
- return VL6180_STATUS_ERROR;
- }
- // Send device address with read bit
- if (dev->i2cWriteByte((dev->i2cAddress << 1) | 0x01) != 0) {
- dev->i2cStop();
- return VL6180_STATUS_ERROR;
- }
- // Read data (16-bit, MSB first)
- uint8_t msb = dev->i2cReadByte(1); // ACK for first byte
- uint8_t lsb = dev->i2cReadByte(0); // NACK for last byte
- *data = (msb << 8) | lsb;
- // Stop I2C transaction
- dev->i2cStop();
- return VL6180_STATUS_OK;
- }
- /**
- * @brief Read 32-bit register
- * @param dev Pointer to VL6180 device structure
- * @param reg Register address
- * @param data Pointer to store read data
- * @return VL6180_STATUS_OK if successful
- */
- uint8_t VL6180_ReadRegister32(struct VL6180_ATY_Dev *dev, uint16_t reg, uint32_t *data)
- {
- if (!dev || !data || !dev->i2cStart || !dev->i2cStop || !dev->i2cWriteByte || !dev->i2cReadByte) {
- return VL6180_STATUS_ERROR;
- }
- // Start I2C transaction for write
- if (dev->i2cStart() != 0) {
- return VL6180_STATUS_ERROR;
- }
- // Send device address with write bit
- if (dev->i2cWriteByte((dev->i2cAddress << 1) | 0x00) != 0) {
- dev->i2cStop();
- return VL6180_STATUS_ERROR;
- }
- // Send register address (16-bit, MSB first)
- if (dev->i2cWriteByte((reg >> 8) & 0xFF) != 0) {
- dev->i2cStop();
- return VL6180_STATUS_ERROR;
- }
- if (dev->i2cWriteByte(reg & 0xFF) != 0) {
- dev->i2cStop();
- return VL6180_STATUS_ERROR;
- }
- // Restart for read
- if (dev->i2cStart() != 0) {
- dev->i2cStop();
- return VL6180_STATUS_ERROR;
- }
- // Send device address with read bit
- if (dev->i2cWriteByte((dev->i2cAddress << 1) | 0x01) != 0) {
- dev->i2cStop();
- return VL6180_STATUS_ERROR;
- }
- // Read data (32-bit, MSB first)
- uint8_t byte3 = dev->i2cReadByte(1); // ACK
- uint8_t byte2 = dev->i2cReadByte(1); // ACK
- uint8_t byte1 = dev->i2cReadByte(1); // ACK
- uint8_t byte0 = dev->i2cReadByte(0); // NACK for last byte
- *data = (byte3 << 24) | (byte2 << 16) | (byte1 << 8) | byte0;
- // Stop I2C transaction
- dev->i2cStop();
- return VL6180_STATUS_OK;
- }
- /******************************* Utility Functions ***************************/
- /**
- * @brief Get device status
- * @param dev Pointer to VL6180 device structure
- * @return Device status
- */
- uint8_t VL6180_GetDeviceStatus(struct VL6180_ATY_Dev *dev)
- {
- if (!dev) {
- return VL6180_STATUS_ERROR;
- }
- return dev->lastStatus;
- }
- /**
- * @brief Set I2C address
- * @param dev Pointer to VL6180 device structure
- * @param address New I2C address
- */
- void VL6180_SetI2CAddress(struct VL6180_ATY_Dev *dev, uint8_t address)
- {
- if (dev) {
- dev->i2cAddress = address;
- }
- }
- /**
- * @brief Convert ALS counts to lux
- * @param dev Pointer to VL6180 device structure
- * @param alsValue ALS value in counts
- * @return Lux value
- */
- float VL6180_ConvertALSToLux(struct VL6180_ATY_Dev *dev, uint16_t alsValue)
- {
- if (!dev) {
- return 0.0f;
- }
- // Gain factors for different ALS gain settings
- float gainFactors[] = {20.0f, 10.32f, 5.21f, 2.60f, 1.72f, 1.28f, 1.01f, 40.0f};
-
- if (dev->alsGain > VL6180_ALS_GAIN_40) {
- return 0.0f;
- }
- float gain = gainFactors[dev->alsGain];
- float integrationTime = dev->alsIntegrationPeriod / 100.0f; // Convert to seconds
- // Calculate lux using the formula from datasheet
- float lux = (float)alsValue * 0.32f / (gain * integrationTime);
- return lux;
- }
- /**
- * @brief Get error string description
- * @param errorCode Error code
- * @return Error string
- */
- const char* VL6180_GetErrorString(uint8_t errorCode)
- {
- switch (errorCode) {
- case VL6180_ERROR_NONE:
- return "No error";
- case VL6180_ERROR_SYSERR_1:
- return "System error 1";
- case VL6180_ERROR_SYSERR_5:
- return "System error 5";
- case VL6180_ERROR_ECEFAIL:
- return "ECE failure";
- case VL6180_ERROR_NOCONVERGE:
- return "No convergence";
- case VL6180_ERROR_RANGEIGNORE:
- return "Range ignore";
- case VL6180_ERROR_SNR:
- return "SNR error";
- case VL6180_ERROR_RAWUFLOW:
- return "Raw underflow";
- case VL6180_ERROR_RAWOFLOW:
- return "Raw overflow";
- case VL6180_ERROR_RANGEUFLOW:
- return "Range underflow";
- case VL6180_ERROR_RANGEOFLOW:
- return "Range overflow";
- default:
- return "Unknown error";
- }
- }
- /******************************* Usage Examples ******************************/
- /*
- // Example 1: Basic VL6180 usage for range measurement
- #include "VL6180_ATY.h"
- // I2C function implementations (platform specific)
- uint8_t i2c_start(void) { // Your I2C start implementation }
- uint8_t i2c_stop(void) { // Your I2C stop implementation }
- uint8_t i2c_write_byte(uint8_t data) { // Your I2C write implementation }
- uint8_t i2c_read_byte(uint8_t ack) { // Your I2C read implementation }
- void delay_ms(uint32_t ms) { // Your delay implementation }
- void debug_log(const char* format, ...) { // Your log implementation }
- int main(void)
- {
- // Initialize VL6180 device structure
- struct VL6180_ATY_Dev vl6180_dev = {
- .i2cStart = i2c_start,
- .i2cStop = i2c_stop,
- .i2cWriteByte = i2c_write_byte,
- .i2cReadByte = i2c_read_byte,
- .delayMs = delay_ms,
- .i2cAddress = VL6180_I2C_ADDR_DEFAULT,
- .debugEnable = 1,
- .LOG = debug_log,
- .initialized = 0 // Auto-initialization will be triggered
- };
- // VL6180_Init will be called automatically in VL6180_StartRangeMeasurement
-
- while (1) {
- // Start single-shot range measurement
- if (VL6180_StartRangeMeasurement(&vl6180_dev, VL6180_MODE_RANGE_SINGLE_SHOT) == VL6180_STATUS_OK) {
- // Wait for measurement to complete
- while (!VL6180_IsRangeReady(&vl6180_dev)) {
- delay_ms(1);
- }
-
- // Read range result
- if (VL6180_ReadRangeResult(&vl6180_dev) == VL6180_STATUS_OK) {
- uint8_t range = VL6180_GetRangeValue(&vl6180_dev);
- debug_log("Range: %d mm\n", range);
- }
-
- // Clear interrupt
- VL6180_ClearRangeInterrupt(&vl6180_dev);
- }
-
- delay_ms(100);
- }
- }
- // Example 2: VL6180 ALS (Ambient Light Sensor) usage
- int als_example(void)
- {
- struct VL6180_ATY_Dev vl6180_dev = {
- .i2cStart = i2c_start,
- .i2cStop = i2c_stop,
- .i2cWriteByte = i2c_write_byte,
- .i2cReadByte = i2c_read_byte,
- .delayMs = delay_ms,
- .i2cAddress = VL6180_I2C_ADDR_DEFAULT,
- .debugEnable = 1,
- .LOG = debug_log,
- .initialized = 0 // Auto-initialization will be triggered
- };
- // Configure ALS settings
- VL6180_SetALSGain(&vl6180_dev, VL6180_ALS_GAIN_1);
- VL6180_SetALSIntegrationPeriod(&vl6180_dev, 100);
- while (1) {
- // Start single-shot ALS measurement
- if (VL6180_StartALSMeasurement(&vl6180_dev, VL6180_MODE_ALS_SINGLE_SHOT) == VL6180_STATUS_OK) {
- // Wait for measurement to complete
- while (!VL6180_IsALSReady(&vl6180_dev)) {
- delay_ms(1);
- }
-
- // Read ALS result
- if (VL6180_ReadALSResult(&vl6180_dev) == VL6180_STATUS_OK) {
- uint16_t als_counts = VL6180_GetALSValue(&vl6180_dev);
- float lux = VL6180_ConvertALSToLux(&vl6180_dev, als_counts);
- debug_log("ALS: %d counts, %.2f lux\n", als_counts, lux);
- }
-
- // Clear interrupt
- VL6180_ClearALSInterrupt(&vl6180_dev);
- }
-
- delay_ms(500);
- }
- }
- */
- /******************************** End Of File *********************************/
|