Thu, 06 Apr 2023 20:53:06 +0200
Set the new measured deep sleep current consumption. This is half of the Wemos D1 system.
/** * @file APDS-9930.cpp * @brief Library for the SparkFun APDS-9930 breakout board * @author Shawn Hymel (SparkFun Electronics) * * @copyright This code is public domain but you buy me a beer if you use * this and we meet someday (Beerware license). Davide Depau Arduino version. * * This library interfaces the Avago APDS-9930 to ESP-IDf over I2C. * * APDS-9930 current draw tests (default parameters): * Off: 1mA * Waiting for gesture: 14mA * Gesture in progress: 35mA */ #include "apds9930.h" #include <inttypes.h> #include <esp_log.h> #include <esp_idf_lib_helpers.h> #define I2C_FREQ_HZ 100000 // Max 400 KHz static const char *TAG = "apds9930"; /* Error code for returned values */ #define APDS9930_ERROR 0xFF /* Command register modes */ #define APDS9930_REPEATED_BYTE 0x80 #define APDS9930_AUTO_INCREMENT 0xA0 #define APDS9930_SPECIAL_FN 0xE0 /* APDS-9930 register addresses */ #define APDS9930_ENABLE 0x00 #define APDS9930_ATIME 0x01 #define APDS9930_PTIME 0x02 #define APDS9930_WTIME 0x03 #define APDS9930_AILTL 0x04 #define APDS9930_AILTH 0x05 #define APDS9930_AIHTL 0x06 #define APDS9930_AIHTH 0x07 #define APDS9930_PILTL 0x08 #define APDS9930_PILTH 0x09 #define APDS9930_PIHTL 0x0A #define APDS9930_PIHTH 0x0B #define APDS9930_PERS 0x0C #define APDS9930_CONFIG 0x0D #define APDS9930_PPULSE 0x0E #define APDS9930_CONTROL 0x0F #define APDS9930_ID 0x12 #define APDS9930_STATUS 0x13 #define APDS9930_Ch0DATAL 0x14 #define APDS9930_Ch0DATAH 0x15 #define APDS9930_Ch1DATAL 0x16 #define APDS9930_Ch1DATAH 0x17 #define APDS9930_PDATAL 0x18 #define APDS9930_PDATAH 0x19 #define APDS9930_POFFSET 0x1E /* Bit fields */ #define APDS9930_PON 0b00000001 #define APDS9930_AEN 0b00000010 #define APDS9930_PEN 0b00000100 #define APDS9930_WEN 0b00001000 #define APSD9930_AIEN 0b00010000 #define APDS9930_PIEN 0b00100000 #define APDS9930_SAI 0b01000000 /* On/Off definitions */ #define APDS9930_OFF 0 #define APDS9930_ON 1 /* Acceptable parameters for setMode */ #define APDS9930_MODE_POWER 0 #define APDS9930_MODE_AMBIENT_LIGHT 1 #define APDS9930_MODE_PROXIMITY 2 #define APDS9930_MODE_WAIT 3 #define APDS9930_MODE_AMBIENT_LIGHT_INT 4 #define APDS9930_MODE_PROXIMITY_INT 5 #define APDS9930_MODE_SLEEP_AFTER_INT 6 #define APDS9930_MODE_ALL 7 /* Interrupt clear values */ #define APDS9930_CLEAR_PROX_INT 0xE5 #define APDS9930_CLEAR_ALS_INT 0xE6 #define APDS9930_CLEAR_ALL_INTS 0xE7 /* ALS coefficients */ #define APDS9930_DF 52 #define APDS9930_GA 0.49 #define APDS9930_ALS_B 1.862 #define APDS9930_ALS_C 0.746 #define APDS9930_ALS_D 1.291 #define CHECK(x) do { esp_err_t __; if ((__ = x) != ESP_OK) return __; } while (0) #define CHECK_ARG(VAL) do { if (!(VAL)) return ESP_ERR_INVALID_ARG; } while (0) #define CHECK_LOGE(dev, x, msg, ...) do { \ esp_err_t __; \ if ((__ = x) != ESP_OK) { \ I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); \ ESP_LOGE(TAG, msg, ## __VA_ARGS__); \ return __; \ } \ } while (0) static inline esp_err_t read_reg_8_nolock(apds9930_t *dev, uint8_t reg, uint8_t *data) { return i2c_dev_read_reg(&dev->i2c_dev, reg, data, 1); } static inline esp_err_t write_reg_8_nolock(apds9930_t *dev, uint8_t reg, uint8_t data) { return i2c_dev_write_reg(&dev->i2c_dev, reg, &data, 1); } static esp_err_t read_reg_8(apds9930_t *dev, uint8_t reg, uint8_t *data) { I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); I2C_DEV_CHECK(&dev->i2c_dev, read_reg_8_nolock(dev, reg, data)); I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); return ESP_OK; } inline static esp_err_t write_register8(i2c_dev_t *dev, uint8_t addr, uint8_t value) { return i2c_dev_write_reg(dev, addr, &value, 1); } esp_err_t apds9930_init_desc(apds9930_t *dev, uint8_t addr, i2c_port_t port, gpio_num_t sda_gpio, gpio_num_t scl_gpio) { CHECK_ARG(dev); if (addr != 0x39) { ESP_LOGE(TAG, "Invalid I2C address"); return ESP_ERR_INVALID_ARG; } dev->i2c_dev.port = port; dev->i2c_dev.addr = addr; dev->i2c_dev.cfg.sda_io_num = sda_gpio; dev->i2c_dev.cfg.scl_io_num = scl_gpio; #if HELPER_TARGET_IS_ESP32 dev->i2c_dev.cfg.master.clk_speed = I2C_FREQ_HZ; #endif return i2c_dev_create_mutex(&dev->i2c_dev); } esp_err_t apds9930_free_desc(apds9930_t *dev) { CHECK_ARG(dev); return i2c_dev_delete_mutex(&dev->i2c_dev); } esp_err_t apds9930_init(apds9930_t *dev) { esp_err_t err = ESP_OK; CHECK_ARG(dev); I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); CHECK_LOGE(dev, i2c_dev_read_reg(&dev->i2c_dev, APDS9930_ID, &dev->id, 1), "Sensor not found"); if (dev->id != APDS9930_ID_1 && dev->id != APDS9930_ID_2 && dev->id != APDS9930_ID_3) { CHECK_LOGE(dev, ESP_ERR_INVALID_VERSION, "Invalid chip ID: expected: 0x%x or 0x%x or 0x%x got: 0x%x", APDS9930_ID_1, APDS9930_ID_2, APDS9930_ID_3, dev->id); } I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); /* Set ENABLE register to 0 (disable all features) */ if (apds9930_setMode(dev, APDS9930_MODE_ALL | APDS9930_AUTO_INCREMENT, APDS9930_OFF) != ESP_OK) { ESP_LOGE(TAG, "apds9930_init() error 'Regs off'"); err = ESP_ERR_INVALID_ARG; } /* Set default values for ambient light and proximity registers */ I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); CHECK_LOGE(dev, write_register8(&dev->i2c_dev, APDS9930_ATIME | APDS9930_AUTO_INCREMENT, APDS9930_DEFAULT_ATIME), "Default atime"); CHECK_LOGE(dev, write_register8(&dev->i2c_dev, APDS9930_WTIME | APDS9930_AUTO_INCREMENT, APDS9930_DEFAULT_WTIME), "Default wtime"); CHECK_LOGE(dev, write_register8(&dev->i2c_dev, APDS9930_PPULSE | APDS9930_AUTO_INCREMENT, APDS9930_DEFAULT_PPULSE), "Default ppulse"); CHECK_LOGE(dev, write_register8(&dev->i2c_dev, APDS9930_POFFSET | APDS9930_AUTO_INCREMENT, APDS9930_DEFAULT_POFFSET), "Default poffset"); CHECK_LOGE(dev, write_register8(&dev->i2c_dev, APDS9930_CONFIG | APDS9930_AUTO_INCREMENT, APDS9930_DEFAULT_CONFIG), "Default config"); I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); CHECK_LOGE(dev, apds9930_setLEDDrive(dev, APDS9930_DEFAULT_PDRIVE), "Default pdrive"); CHECK_LOGE(dev, apds9930_setProximityGain(dev, APDS9930_DEFAULT_PGAIN), "Default pgain"); CHECK_LOGE(dev, apds9930_setAmbientLightGain(dev, APDS9930_DEFAULT_AGAIN), "Default again"); CHECK_LOGE(dev, apds9930_setProximityDiode(dev, APDS9930_DEFAULT_PDIODE), "Default pdiode"); CHECK_LOGE(dev, apds9930_setProximityIntLowThreshold(dev, APDS9930_DEFAULT_PILT), "Default PILT"); CHECK_LOGE(dev, apds9930_setProximityIntHighThreshold(dev, APDS9930_DEFAULT_PIHT), "Default PIHT"); CHECK_LOGE(dev, apds9930_setLightIntLowThreshold(dev, APDS9930_DEFAULT_AILT), "Default ailt"); CHECK_LOGE(dev, apds9930_setLightIntHighThreshold(dev, APDS9930_DEFAULT_AIHT), "Default aiht"); I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); CHECK_LOGE(dev, write_register8(&dev->i2c_dev, APDS9930_PERS | APDS9930_AUTO_INCREMENT, APDS9930_DEFAULT_PERS), "Default pers"); I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); return err; } /******************************************************************************* * Public methods for controlling the APDS-9930 ******************************************************************************/ uint8_t apds9930_getMode(apds9930_t *dev) { uint8_t enable_value; /* Read current ENABLE register */ I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); if (read_reg_8_nolock(dev, APDS9930_ENABLE | APDS9930_AUTO_INCREMENT, &enable_value) != ESP_OK) { I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); return APDS9930_ERROR; } I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); return enable_value; } esp_err_t apds9930_setMode(apds9930_t *dev, uint8_t mode, uint8_t enable) { uint8_t reg_val; // CHECK_ARG(dev); /* Read current ENABLE register */ I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); I2C_DEV_CHECK(&dev->i2c_dev, read_reg_8_nolock(dev, APDS9930_ENABLE | APDS9930_AUTO_INCREMENT, ®_val)); // i2c_dev_read_reg(&dev->i2c_dev, (uint8_t)APDS9930_ENABLE, ®_val, 1); I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); ESP_LOGI(TAG, "apds9930_setMode(%d, %d) get=%02x", mode, enable, reg_val); /* Change bit(s) in ENABLE register */ enable = enable & 0x01; if (mode <= 6) { if (enable) { reg_val |= (1 << mode); } else { reg_val &= ~(1 << mode); } } else if (mode == APDS9930_MODE_ALL) { if (enable) { reg_val = 0x7F; } else { reg_val = 0x00; } } ESP_LOGI(TAG, "apds9930_setMode write %02x", reg_val); /* Write value back to ENABLE register */ I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); I2C_DEV_CHECK(&dev->i2c_dev, write_reg_8_nolock(dev, APDS9930_ENABLE | APDS9930_AUTO_INCREMENT, reg_val)); // CHECK_LOGE(dev, write_register8(&dev->i2c_dev, APDS9930_ENABLE, reg_val), "Enable register"); // CHECK_LOGE(dev, i2c_dev_write_reg(&dev->i2c_dev, (uint8_t)APDS9930_ENABLE, ®_val, 1), "Enable register"); I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); //vTaskDelay(12 / portTICK_PERIOD_MS); return ESP_OK; } esp_err_t apds9930_enableLightSensor(apds9930_t *dev, bool interrupts) { CHECK_ARG(dev); /* Set default gain, interrupts, enable power, and enable sensor */ CHECK_LOGE(dev, apds9930_setAmbientLightGain(dev, APDS9930_DEFAULT_AGAIN), "setAmbientLightGain"); if ( interrupts ) { CHECK_LOGE(dev, apds9930_setAmbientLightIntEnable(dev, 1), "setAmbientLightIntEnable(1)"); } else { CHECK_LOGE(dev, apds9930_setAmbientLightIntEnable(dev, 0), "setAmbientLightIntEnable(0)"); } CHECK_LOGE(dev, apds9930_enablePower(dev), "enablePower"); CHECK_LOGE(dev, apds9930_setMode(dev, APDS9930_MODE_AMBIENT_LIGHT, 1), "setMode"); return ESP_OK; } esp_err_t apds9930_disableLightSensor(apds9930_t *dev) { CHECK_ARG(dev); CHECK_LOGE(dev, apds9930_setAmbientLightIntEnable(dev, 0), "setAmbientLightIntEnable(0)"); CHECK_LOGE(dev, apds9930_setMode(dev, APDS9930_MODE_AMBIENT_LIGHT, 0), "setMode"); return ESP_OK; } esp_err_t apds9930_enableProximitySensor(apds9930_t *dev, bool interrupts) { CHECK_ARG(dev); /* Set default gain, LED, interrupts, enable power, and enable sensor */ CHECK_LOGE(dev, apds9930_setProximityGain(dev, APDS9930_DEFAULT_PGAIN), "setProximityGain"); CHECK_LOGE(dev, apds9930_setLEDDrive(dev, APDS9930_DEFAULT_PDRIVE), "setLEDDrive"); if( interrupts ) { CHECK_LOGE(dev, apds9930_setProximityIntEnable(dev, 1), "setProximityIntEnable(1)"); } else { CHECK_LOGE(dev, apds9930_setProximityIntEnable(dev, 0), "setProximityIntEnable(0)"); } CHECK_LOGE(dev, apds9930_enablePower(dev), "enablePower"); CHECK_LOGE(dev, apds9930_setMode(dev, APDS9930_MODE_PROXIMITY, 1), "setMode"); return ESP_OK; } esp_err_t apds9930_disableProximitySensor(apds9930_t *dev) { CHECK_ARG(dev); CHECK_LOGE(dev, apds9930_setProximityIntEnable(dev, 0), "setProximityIntEnable(0)"); CHECK_LOGE(dev, apds9930_setMode(dev, APDS9930_MODE_PROXIMITY, 0), "setMode"); return ESP_OK; } esp_err_t apds9930_enablePower(apds9930_t *dev) { return apds9930_setMode(dev, APDS9930_MODE_POWER, 1); } esp_err_t apds9930_disablePower(apds9930_t *dev) { return apds9930_setMode(dev, APDS9930_MODE_POWER, 0); } /******************************************************************************* * Ambient light sensor controls ******************************************************************************/ esp_err_t apds9930_readAmbientLightLux(apds9930_t *dev, float *val) { uint16_t Ch0, Ch1; /* Read value from channels */ CHECK_LOGE(dev, apds9930_readCh0Light(dev, &Ch0), "read ch0"); CHECK_LOGE(dev, apds9930_readCh1Light(dev, &Ch1), "read ch1"); *val = apds9930_floatAmbientToLux(dev, Ch0, Ch1); return ESP_OK; } esp_err_t apds9930_readulAmbientLightLux(apds9930_t *dev, unsigned long *val) { uint16_t Ch0, Ch1; /* Read value from channels */ CHECK_LOGE(dev, apds9930_readCh0Light(dev, &Ch0), "read ch0"); CHECK_LOGE(dev, apds9930_readCh1Light(dev, &Ch1), "read ch1"); *val = apds9930_ulongAmbientToLux(dev, Ch0, Ch1); return ESP_OK; } float apds9930_floatAmbientToLux(apds9930_t *dev, uint16_t Ch0, uint16_t Ch1) { uint8_t x[4] = {1,8,16,120}; float iac; float ALSIT = 2.73 * (256 - APDS9930_DEFAULT_ATIME); if ((Ch0 - APDS9930_ALS_B * Ch1) > (APDS9930_ALS_C * Ch0 - APDS9930_ALS_D * Ch1)) iac = Ch0 - APDS9930_ALS_B * Ch1; else iac = APDS9930_ALS_C * Ch0 - APDS9930_ALS_D * Ch1; //float iac = fmax(Ch0 - APDS9930_ALS_B * Ch1, APDS9930_ALS_C * Ch0 - APDS9930_ALS_D * Ch1); if (iac < 0) iac = 0; float lpc = APDS9930_GA * APDS9930_DF / (ALSIT * x[apds9930_getAmbientLightGain(dev)]); return iac * lpc; } unsigned long apds9930_ulongAmbientToLux(apds9930_t *dev, uint16_t Ch0, uint16_t Ch1) { uint8_t x[4] = {1,8,16,120}; unsigned long iac; unsigned long ALSIT = 2.73 * (256 - APDS9930_DEFAULT_ATIME); if ((Ch0 - APDS9930_ALS_B * Ch1) > (APDS9930_ALS_C * Ch0 - APDS9930_ALS_D * Ch1)) iac = Ch0 - APDS9930_ALS_B * Ch1; else iac = APDS9930_ALS_C * Ch0 - APDS9930_ALS_D * Ch1; //unsigned long iac = max(Ch0 - APDS9930_ALS_B * Ch1, APDS9930_ALS_C * Ch0 - APDS9930_ALS_D * Ch1); // if (iac < 0) iac = 0; unsigned long lpc = APDS9930_GA * APDS9930_DF / (ALSIT * x[apds9930_getAmbientLightGain(dev)]); return iac * lpc; } esp_err_t apds9930_readCh0Light(apds9930_t *dev, uint16_t *val) { uint8_t val_byte; uint16_t val_word; *val = 0; CHECK_ARG(dev); I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); /* Read value from channel 0 */ CHECK_LOGE(dev, i2c_dev_read_reg(&dev->i2c_dev, (uint8_t)APDS9930_Ch0DATAL | APDS9930_AUTO_INCREMENT, &val_byte, 1), "Read ch0 low"); ESP_LOGI(TAG, "l %02x", val_byte); *val = val_byte; CHECK_LOGE(dev, i2c_dev_read_reg(&dev->i2c_dev, (uint8_t)APDS9930_Ch0DATAH | APDS9930_AUTO_INCREMENT, &val_byte, 1), "Read ch0 high"); ESP_LOGI(TAG, "h %02x", val_byte); *val += ((uint16_t)val_byte << 8); I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); ESP_LOGI(TAG, "val %04x", *val); CHECK_LOGE(dev, i2c_dev_read_reg(&dev->i2c_dev, (uint8_t)APDS9930_Ch0DATAL | APDS9930_AUTO_INCREMENT, &val_word, 2), "Read ch0 16"); ESP_LOGI(TAG, "16 %04x", val_word); return ESP_OK; } esp_err_t apds9930_readCh1Light(apds9930_t *dev, uint16_t *val) { uint8_t val_byte; *val = 0; I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); /* Read value from channel 1 */ CHECK_LOGE(dev, i2c_dev_read_reg(&dev->i2c_dev, APDS9930_Ch1DATAL | APDS9930_AUTO_INCREMENT, &val_byte, 1), "Read ch1 low"); *val = val_byte; CHECK_LOGE(dev, i2c_dev_read_reg(&dev->i2c_dev, APDS9930_Ch1DATAH | APDS9930_AUTO_INCREMENT, &val_byte, 1), "Read ch1 high"); *val += ((uint16_t)val_byte << 8); I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); return ESP_OK; } /******************************************************************************* * Proximity sensor controls ******************************************************************************/ esp_err_t apds9930_readProximity(apds9930_t *dev, uint16_t *val) { *val = 0; uint8_t val_byte; I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); /* Read value from proximity data register */ CHECK_LOGE(dev, i2c_dev_read_reg(&dev->i2c_dev, APDS9930_PDATAL | APDS9930_AUTO_INCREMENT, &val_byte, 1), "Read proximity low"); *val = val_byte; CHECK_LOGE(dev, i2c_dev_read_reg(&dev->i2c_dev, APDS9930_PDATAH | APDS9930_AUTO_INCREMENT, &val_byte, 1), "Read proximity high"); *val += ((uint16_t)val_byte << 8); I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); return ESP_OK; } /******************************************************************************* * Getters and setters for register values ******************************************************************************/ uint16_t apds9930_getProximityIntLowThreshold(apds9930_t *dev) { uint16_t val; uint8_t val_byte; /* Read value from PILT register */ I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); if (i2c_dev_read_reg(&dev->i2c_dev, APDS9930_PILTL | APDS9930_AUTO_INCREMENT, &val_byte, 1) != ESP_OK) { val = 0; } val = val_byte; if (i2c_dev_read_reg(&dev->i2c_dev, APDS9930_PILTH | APDS9930_AUTO_INCREMENT, &val_byte, 1) != ESP_OK) { val = 0; } I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); val |= ((uint16_t)val_byte << 8); return val; } esp_err_t apds9930_setProximityIntLowThreshold(apds9930_t *dev, uint16_t threshold) { uint8_t lo; uint8_t hi; hi = threshold >> 8; lo = threshold & 0x00FF; I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); CHECK_LOGE(dev, i2c_dev_write_reg(&dev->i2c_dev, APDS9930_PILTL | APDS9930_AUTO_INCREMENT, &lo, 1), "Write PILTL"); CHECK_LOGE(dev, i2c_dev_write_reg(&dev->i2c_dev, APDS9930_PILTH | APDS9930_AUTO_INCREMENT, &hi, 1), "Write PILTH"); I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); return ESP_OK; } uint16_t apds9930_getProximityIntHighThreshold(apds9930_t *dev) { uint16_t val; uint8_t val_byte; /* Read value from PIHT register */ I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); if (i2c_dev_read_reg(&dev->i2c_dev, APDS9930_PIHTL | APDS9930_AUTO_INCREMENT, &val_byte, 1) != ESP_OK) { val = 0; } val = val_byte; if (i2c_dev_read_reg(&dev->i2c_dev, APDS9930_PIHTH | APDS9930_AUTO_INCREMENT, &val_byte, 1) != ESP_OK) { val = 0; } I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); val |= ((uint16_t)val_byte << 8); return val; } esp_err_t apds9930_setProximityIntHighThreshold(apds9930_t *dev, uint16_t threshold) { uint8_t lo; uint8_t hi; hi = threshold >> 8; lo = threshold & 0x00FF; I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); CHECK_LOGE(dev, i2c_dev_write_reg(&dev->i2c_dev, APDS9930_PIHTL | APDS9930_AUTO_INCREMENT, &lo, 1), "Write PIHTL"); CHECK_LOGE(dev, i2c_dev_write_reg(&dev->i2c_dev, APDS9930_PIHTH | APDS9930_AUTO_INCREMENT, &hi, 1), "Write PIHTH"); I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); return ESP_OK; } uint8_t apds9930_getLEDDrive(apds9930_t *dev) { uint8_t val; /* Read value from CONTROL register */ I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); if (i2c_dev_read_reg(&dev->i2c_dev, APDS9930_CONTROL | APDS9930_AUTO_INCREMENT, &val, 1) != ESP_OK) { I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); return APDS9930_ERROR;; } I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); /* Shift and mask out LED drive bits */ val = (val >> 6) & 0b00000011; return val; } esp_err_t apds9930_setLEDDrive(apds9930_t *dev, uint8_t drive) { uint8_t val; /* Read value from CONTROL register */ I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); CHECK_LOGE(dev, i2c_dev_read_reg(&dev->i2c_dev, APDS9930_CONTROL | APDS9930_AUTO_INCREMENT, &val, 1), "Read control"); /* Set bits in register to given value */ drive &= 0b00000011; drive = drive << 6; val &= 0b00111111; val |= drive; /* Write register value back into CONTROL register */ CHECK_LOGE(dev, i2c_dev_write_reg(&dev->i2c_dev, APDS9930_CONTROL | APDS9930_AUTO_INCREMENT, &val, 1), "Write control"); I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); return ESP_OK; } uint8_t apds9930_getProximityGain(apds9930_t *dev) { uint8_t val; /* Read value from CONTROL register */ I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); if (i2c_dev_read_reg(&dev->i2c_dev, APDS9930_CONTROL | APDS9930_AUTO_INCREMENT, &val, 1) != ESP_OK) { I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); return APDS9930_ERROR;; } I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); /* Shift and mask out PDRIVE bits */ val = (val >> 2) & 0b00000011; return val; } esp_err_t apds9930_setProximityGain(apds9930_t *dev, uint8_t drive) { uint8_t val; /* Read value from CONTROL register */ I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); CHECK_LOGE(dev, i2c_dev_read_reg(&dev->i2c_dev, APDS9930_CONTROL | APDS9930_AUTO_INCREMENT, &val, 1), "Read control"); /* Set bits in register to given value */ drive &= 0b00000011; drive = drive << 2; val &= 0b11110011; val |= drive; /* Write register value back into CONTROL register */ CHECK_LOGE(dev, i2c_dev_write_reg(&dev->i2c_dev, APDS9930_CONTROL | APDS9930_AUTO_INCREMENT, &val, 1), "Write control"); I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); return ESP_OK; } uint8_t apds9930_getProximityDiode(apds9930_t *dev) { uint8_t val; /* Read value from CONTROL register */ I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); if (i2c_dev_read_reg(&dev->i2c_dev, APDS9930_CONTROL | APDS9930_AUTO_INCREMENT, &val, 1) != ESP_OK) { I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); return APDS9930_ERROR;; } I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); /* Shift and mask out PDRIVE bits */ val = (val >> 4) & 0b00000011; return val; } esp_err_t apds9930_setProximityDiode(apds9930_t *dev, uint8_t drive) { uint8_t val; /* Read value from CONTROL register */ I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); CHECK_LOGE(dev, i2c_dev_read_reg(&dev->i2c_dev, APDS9930_CONTROL | APDS9930_AUTO_INCREMENT, &val, 1), "Read control"); /* Set bits in register to given value */ drive &= 0b00000011; drive = drive << 4; val &= 0b11001111; val |= drive; /* Write register value back into CONTROL register */ CHECK_LOGE(dev, i2c_dev_write_reg(&dev->i2c_dev, APDS9930_CONTROL | APDS9930_AUTO_INCREMENT, &val, 1), "Write control"); I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); return ESP_OK; } uint8_t apds9930_getAmbientLightGain(apds9930_t *dev) { uint8_t val; /* Read value from CONTROL register */ I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); if (i2c_dev_read_reg(&dev->i2c_dev, APDS9930_CONTROL | APDS9930_AUTO_INCREMENT, &val, 1) != ESP_OK) { I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); return APDS9930_ERROR;; } I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); /* Shift and mask out ADRIVE bits */ val &= 0b00000011; return val; } esp_err_t apds9930_setAmbientLightGain(apds9930_t *dev, uint8_t drive) { uint8_t val; /* Read value from CONTROL register */ I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); CHECK_LOGE(dev, i2c_dev_read_reg(&dev->i2c_dev, APDS9930_CONTROL | APDS9930_AUTO_INCREMENT, &val, 1), "Read control"); /* Set bits in register to given value */ drive &= 0b00000011; val &= 0b11111100; val |= drive; /* Write register value back into CONTROL register */ CHECK_LOGE(dev, i2c_dev_write_reg(&dev->i2c_dev, APDS9930_CONTROL | APDS9930_AUTO_INCREMENT, &val, 1), "Write control"); I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); return ESP_OK; } uint8_t apds9930_getAmbientGainLevel(apds9930_t *dev) { uint8_t val; /* Read value from CONTROL register */ I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); if (i2c_dev_read_reg(&dev->i2c_dev, APDS9930_CONTROL | APDS9930_AUTO_INCREMENT, &val, 1) != ESP_OK) { I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); return APDS9930_ERROR;; } I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); /* Shift and mask out AGL bit */ val = (val >> 2) & 0b00000001; return val; } esp_err_t apds9930_setAmbientGainLevel(apds9930_t *dev, uint8_t enable) { uint8_t val; /* Read value from CONTROL register */ I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); CHECK_LOGE(dev, i2c_dev_read_reg(&dev->i2c_dev, APDS9930_CONTROL | APDS9930_AUTO_INCREMENT, &val, 1), "Read control"); /* Set bits in register to given value */ enable &= 0b00000001; enable = enable << 2; val &= 0b11111011; val |= enable; /* Write register value back into CONTROL register */ CHECK_LOGE(dev, i2c_dev_write_reg(&dev->i2c_dev, APDS9930_CONTROL | APDS9930_AUTO_INCREMENT, &val, 1), "Write control"); I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); return ESP_OK; } esp_err_t apds9930_getLightIntLowThreshold(apds9930_t *dev, uint16_t *threshold) { uint8_t val_byte; *threshold = 0; /* Read value from ambient light low threshold, low byte register */ I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); if (i2c_dev_read_reg(&dev->i2c_dev, APDS9930_AILTL | APDS9930_AUTO_INCREMENT, &val_byte, 1) != ESP_OK) { *threshold = 0; } *threshold = val_byte; if (i2c_dev_read_reg(&dev->i2c_dev, APDS9930_AILTH | APDS9930_AUTO_INCREMENT, &val_byte, 1) != ESP_OK) { *threshold = 0; } I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); *threshold = *threshold + ((uint16_t)val_byte << 8); return ESP_OK; } esp_err_t apds9930_setLightIntLowThreshold(apds9930_t *dev, uint16_t threshold) { uint8_t val_low; uint8_t val_high; /* Break 16-bit threshold into 2 8-bit values */ val_low = threshold & 0x00FF; val_high = (threshold & 0xFF00) >> 8; I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); CHECK_LOGE(dev, i2c_dev_write_reg(&dev->i2c_dev, APDS9930_AILTL | APDS9930_AUTO_INCREMENT, &val_low, 1), "Write AILTL"); CHECK_LOGE(dev, i2c_dev_write_reg(&dev->i2c_dev, APDS9930_AILTH | APDS9930_AUTO_INCREMENT, &val_high, 1), "Write AILTH"); I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); return ESP_OK; } esp_err_t apds9930_getLightIntHighThreshold(apds9930_t *dev, uint16_t *threshold) { uint8_t val_byte; *threshold = 0; /* Read value from ambient light high threshold, low byte register */ I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); if (i2c_dev_read_reg(&dev->i2c_dev, APDS9930_AIHTL | APDS9930_AUTO_INCREMENT, &val_byte, 1) != ESP_OK) { *threshold = 0; } *threshold = val_byte; if (i2c_dev_read_reg(&dev->i2c_dev, APDS9930_AIHTH | APDS9930_AUTO_INCREMENT, &val_byte, 1) != ESP_OK) { *threshold = 0; } I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); *threshold = *threshold + ((uint16_t)val_byte << 8); return ESP_OK; } esp_err_t apds9930_setLightIntHighThreshold(apds9930_t *dev, uint16_t threshold) { uint8_t val_low; uint8_t val_high; /* Break 16-bit threshold into 2 8-bit values */ val_low = threshold & 0x00FF; val_high = (threshold & 0xFF00) >> 8; I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); CHECK_LOGE(dev, i2c_dev_write_reg(&dev->i2c_dev, APDS9930_AIHTL | APDS9930_AUTO_INCREMENT, &val_low, 1), "Write AIHTL"); CHECK_LOGE(dev, i2c_dev_write_reg(&dev->i2c_dev, APDS9930_AIHTH | APDS9930_AUTO_INCREMENT, &val_high, 1), "Write AIHTH"); I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); return ESP_OK; } uint8_t apds9930_getAmbientLightIntEnable(apds9930_t *dev) { uint8_t val; /* Read value from ENABLE register */ I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); if (i2c_dev_read_reg(&dev->i2c_dev, APDS9930_ENABLE | APDS9930_AUTO_INCREMENT, &val, 1) != ESP_OK) { I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); return APDS9930_ERROR;; } I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); /* Shift and mask out AIEN bit */ val = (val >> 4) & 0b00000001; return val; } esp_err_t apds9930_setAmbientLightIntEnable(apds9930_t *dev, uint8_t enable) { uint8_t val; /* Read value from ENABLE register */ I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); CHECK_LOGE(dev, i2c_dev_read_reg(&dev->i2c_dev, APDS9930_ENABLE | APDS9930_AUTO_INCREMENT, &val, 1), "Read enable"); /* Set bits in register to given value */ enable &= 0b00000001; enable = enable << 4; val &= 0b11101111; val |= enable; /* Write register value back into ENABLE register */ CHECK_LOGE(dev, i2c_dev_write_reg(&dev->i2c_dev, APDS9930_ENABLE | APDS9930_AUTO_INCREMENT, &val, 1), "Write enable"); I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); return ESP_OK; } uint8_t apds9930_getProximityIntEnable(apds9930_t *dev) { uint8_t val; /* Read value from ENABLE register */ I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); if (i2c_dev_read_reg(&dev->i2c_dev, APDS9930_ENABLE | APDS9930_AUTO_INCREMENT, &val, 1) != ESP_OK) { I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); return APDS9930_ERROR;; } I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); /* Shift and mask out PIEN bit */ val = (val >> 5) & 0b00000001; return val; } esp_err_t apds9930_setProximityIntEnable(apds9930_t *dev, uint8_t enable) { uint8_t val; /* Read value from ENABLE register */ I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); CHECK_LOGE(dev, i2c_dev_read_reg(&dev->i2c_dev, APDS9930_ENABLE | APDS9930_AUTO_INCREMENT, &val, 1), "Read enable"); /* Set bits in register to given value */ enable &= 0b00000001; enable = enable << 5; val &= 0b11011111; val |= enable; /* Write register value back into ENABLE register */ CHECK_LOGE(dev, i2c_dev_write_reg(&dev->i2c_dev, APDS9930_ENABLE | APDS9930_AUTO_INCREMENT, &val, 1), "Write enable"); I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); return ESP_OK; } esp_err_t apds9930_clearAmbientLightInt(apds9930_t *dev) { uint8_t val = APDS9930_CLEAR_ALS_INT; I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); I2C_DEV_CHECK(&dev->i2c_dev, i2c_dev_write(&dev->i2c_dev, NULL, 0, &val, 1)); I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); return ESP_OK; } esp_err_t apds9930_clearProximityInt(apds9930_t *dev) { uint8_t val = APDS9930_CLEAR_PROX_INT; I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); I2C_DEV_CHECK(&dev->i2c_dev, i2c_dev_write(&dev->i2c_dev, NULL, 0, &val, 1)); I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); return ESP_OK; } esp_err_t apds9930_clearAllInts(apds9930_t *dev) { uint8_t val = APDS9930_CLEAR_ALL_INTS; I2C_DEV_TAKE_MUTEX(&dev->i2c_dev); I2C_DEV_CHECK(&dev->i2c_dev, i2c_dev_write(&dev->i2c_dev, NULL, 0, &val, 1)); I2C_DEV_GIVE_MUTEX(&dev->i2c_dev); return ESP_OK; }