#ifndef PROX_TMD2635_H_ #define PROX_TMD2635_H_ // Prerequisites - I2C driver #include "i2c.h" #include #define TMD2635_I2C_ADDR (0x72u) // For use with UNSHIFTED address type, 0b0111.001W, where W is the read/write bit #define PROX_SENSOR_THRESHOLD (1500u) #define PROX_SENSOR_HYSTERESIS (100u) // Register addresses #define PROX_REG_ENABLE (0x80u) // Enable chip oscillator, proximity detection, and proximity wait function #define PROX_REG_PRATE (0x82u) // duration of sample, 88us*(PRATE+1) #define PROX_REG_PILTL (0x88u) // proximity low threshold, low byte #define PROX_REG_PILTH (0x89u) // proximity low threshold, high byte #define PROX_REG_PIHTL (0x8Au) // proximity high threshold, low byte #define PROX_REG_PIHTH (0x8Bu) // proximity high threshold, high byte #define PROX_REG_PERS (0x8Cu) // persistence counter, number of cycles outside PILT/PIHT that triggers an interrupt #define PROX_REG_CFG0 (0x8Du) // contains only PWLONG bit #define PROX_REG_PCFG0 (0x8Eu) // PD amplifier gain and max number of pulses #define PROX_REG_PCFG1 (0x8Fu) // pulse length and laser current #define PROX_REG_REVID (0x91u) // Revision ID (normally reads as 0x10) #define PROX_REG_DEVID (0x92u) // Device ID (normally reads as 0x44) #define PROX_REG_STATUS (0x9Bu) // status flags #define PROX_REG_PDATAL (0x9Cu) // Proximity data low byte #define PROX_REG_PDATAH (0x9Du) // Proximity data high byte #define PROX_REG_REVID2 (0xA6u) // Version ID, normally reads 0x01 or 0x0E #define PROX_REG_SOFTRST (0xA8u) // Software reset #define PROX_REG_PWTIME (0xA9u) // wait time between pulses in 2.78ms increments (programmable between 2.78 to 711.68ms) // note that PWLONG increases wait time by 12x (so it would be 33.36ms to 8.54s) #define PROX_REG_CFG8 (0xAAu) // Photodiode select (near/far/both) #define PROX_REG_CFG3 (0xABu) // Status bits clear when read, and sleep after interrupt #define PROX_REG_CFG6 (0xAEu) // Auto pulse control (APC) disable #define PROX_REG_PFILTER (0xB3u) // Moving average filter #define PROX_REG_POFFSETL (0xC0u) // Offset low byte (subtracted from proximity data) #define PROX_REG_POFFSETH (0xC1u) // Offset high byte (just the sign bit at b0) #define PROX_REG_CALIB (0xD7u) // Calibration control (automatically calculate offset) #define PROX_REG_CALIBCFG (0xD9u) // Bin search target for calib, auto offset adjust, and hardware averaging #define PROX_REG_CALIBSTAT (0xDCu) // If offset was adjusted and calib complete flags #define PROX_REG_INTENAB (0xDDu) // Interrupt enable flags #define PROX_REG_FAC_L (0xE5u) // Factory data, lot code, low byte #define PROX_REG_FAC_H (0xE6u) // Factory data, lot code, high byte #define PROX_REG_TEST9 (0xF9u) // No idea what this does, but the datasheet says this must be set to 0x07 // Bit and field definitions #define PROX_ENABLE_PON (0x01u) // enable oscillator and ADC #define PROX_ENABLE_PEN (0x04u) // enables proximity detection #define PROX_ENABLE_PWEN (0x10u) // enables proximity wait function #define PROX_CFG0_RSVD (0x40u) // must be OR'd with any CFG0 setting #define PROX_CFG0_PWLONG (0x08u) #define PROX_PCFG0_PGAIN_Pos (6) #define PROX_PCFG0_PGAIN_Msk (0x03u << PROX_PCFG0_PGAIN_Pos) #define PROX_PCFG0_PGAIN(value) ((value & 0x03u) << PROX_PCFG0_PGAIN_Pos) #define PROX_PCFG0_PGAIN_1x PROX_PCFG0_PGAIN(0) #define PROX_PCFG0_PGAIN_2x PROX_PCFG0_PGAIN(1) #define PROX_PCFG0_PGAIN_4x PROX_PCFG0_PGAIN(2) #define PROX_PCFG0_PGAIN_8x PROX_PCFG0_PGAIN(3) #define PROX_PCFG0_PPULSE_Pos (0) #define PROX_PCFG0_PPULSE_Msk (0x3Fu << PROX_PCFG0_PPULSE_Pos) #define PROX_PCFG0_PPULSE(value) ((value & 0x3Fu) << PROX_PCFG0_PPULSE_Pos) #define PROX_PCFG1_PPULSELEN_Pos (5) #define PROX_PCFG1_PPULSELEN_Msk (0x07u << PROX_PCFG1_PPULSELEN_Pos) #define PROX_PCFG1_PPULSELEN(value) ((value & 0x07u) << PROX_PCFG1_PPULSELEN_Pos) #define PROX_PCFG1_PPULSELEN_1us PROX_PCFG1_PPULSELEN(0) #define PROX_PCFG1_PPULSELEN_2us PROX_PCFG1_PPULSELEN(1) #define PROX_PCFG1_PPULSELEN_4us PROX_PCFG1_PPULSELEN(2) #define PROX_PCFG1_PPULSELEN_8us PROX_PCFG1_PPULSELEN(3) #define PROX_PCFG1_PPULSELEN_12us PROX_PCFG1_PPULSELEN(4) #define PROX_PCFG1_PPULSELEN_16us PROX_PCFG1_PPULSELEN(5) #define PROX_PCFG1_PPULSELEN_24us PROX_PCFG1_PPULSELEN(6) #define PROX_PCFG1_PPULSELEN_32us PROX_PCFG1_PPULSELEN(7) #define PROX_PCFG1_PLDRIVE_Pos (0) #define PROX_PCFG1_PLDRIVE_Msk (0x0Fu << PROX_PCFG1_PLDRIVE_Pos) #define PROX_PCFG1_PLDRIVE(value) ((value & 0x0Fu) << PROX_PCFG1_PLDRIVE_Pos) #define PROX_PCFG1_PLDRIVE_7mA PROX_PCFG1_PLDRIVE(5) #define PROX_PCFG1_PLDRIVE_8mA PROX_PCFG1_PLDRIVE(6) #define PROX_PCFG1_PLDRIVE_9mA PROX_PCFG1_PLDRIVE(7) #define PROX_PCFG1_PLDRIVE_10mA PROX_PCFG1_PLDRIVE(8) // All status flags can be cleared by writing with '1' // Or if INT_READ_CLEAR in CFG3 is set, all are cleared when the register is read #define PROX_STATUS_PHIGH (0x80u) // PDATA is above high threshold, only triggers when PINT set #define PROX_STATUS_PLOW (0x40u) // PDATA is below low threshold, only triggers when PINT set #define PROX_STATUS_PSAT (0x20u) // saturation event occurred #define PROX_STATUS_PINT (0x10u) // prox results exceeded threshold and persistence settings #define PROX_STATUS_CINT (0x08u) // calibration complete #define PROX_STATUS_ZINT (0x04u) // zero detection, a zero reading of PDATA caused offset to be adjusted (only if AUTO_OFFSET_ADJ set) #define PROX_STATUS_PSAT_REFLECTIVE (0x02u) // saturation during IR VCSEL on time (from IR reflection) #define PROX_STATUS_PSAT_AMBIENT (0x01u) // saturation during IR VCSEL off (from ambient light) #define PROX_SOFTRST_RST (0x01u) // Set to trigger a software reset #define PROX_CFG8_PDSELECT_Pos (0) #define PROX_CFG8_PDSELECT_Msk (0x03u << PROX_CFG8_PDSELECT_Pos) #define PROX_CFG8_PDSELECT(value) ((value & 0x03u) << PROX_CFG8_PDSELECT_Pos) #define PROX_CFG8_PDSELECT_FAR PROX_CFG8_PDSELECT(1) #define PROX_CFG8_PDSELECT_NEAR PROX_CFG8_PDSELECT(2) #define PROX_CFG8_PDSELECT_BOTH PROX_CFG8_PDSELECT(3) #define PROX_CFG3_RSVD (0x04u) // Must be OR'd with any CFG3 setting #define PROX_CFG3_INT_READ_CLEAR (0x80u) #define PROX_CFG3_SAI (0x08u) #define PROX_CFG6_RSVD (0x3Fu) // Must be OR'd with any CFG6 setting #define PROX_PFILTER_PMAVG_Pos (0) #define PROX_PFILTER_PMAVG_Msk (0x03u << PROX_PFILTER_PMAVG_Pos) #define PROX_PFILTER_PMAVG(value) ((value & 0x03u) << PROX_PFILTER_PMAVG_Pos) #define PROX_PFILTER_PMAVG_None PROX_PFILTER_PMAVG(0) #define PROX_PFILTER_PMAVG_2 PROX_PFILTER_PMAVG(1) #define PROX_PFILTER_PMAVG_4 PROX_PFILTER_PMAVG(2) #define PROX_PFILTER_PMAVG_8 PROX_PFILTER_PMAVG(3) #define PROX_CALIB_CALAVG (0x80u) // 1: Enables averaging during calibration, 0: ignores averaging #define PROX_CALIB_ELECTRICAL (0x20u) // 1: Electrical calibration only, 0: optical and electrical #define PROX_CALIB_PRATE (0x10u) // 1: Enables PRATE during calibration, 0: ignores PRATE #define PROX_CALIB_START (0x01u) // Begin calibration #define PROX_CALIBCFG_TARGET_Pos (5) #define PROX_CALIBCFG_TARGET_Msk (0x7u << PROX_CALIBCFG_TARGET_Pos) #define PROX_CALIBCFG_TARGET(value) ((value & 0x07u) << PROX_CALIBCFG_TARGET_Pos) // Note - target value during calibration is equal to 2^(PROX_CALIBCFG_TARGET+2) - 1 // For example, PROX_CALIBCFG_TARGET = 3, value = 2^(2+3) - 1 = 2^5 - 1 = 31 #define PROX_CALIBCFG_RSVD (0x10u) // Must be OR'd with any CALIBCFG settings #define PROX_CALIBCFG_AUTO_OFFSET_ADJ (0x08u) // 1: automatically decrement offset if proximity data is ever zero, 0: don't change offset #define PROX_CALIBCFG_AVG_Pos (0) #define PROX_CALIBCFG_AVG_Msk (0x07u << PROX_CALIBCFG_AVG_Pos) #define PROX_CALIBCFG_AVG(value) ((value & 0x07u) << PROX_CALIBCFG_AVG_Pos) // Note - hardware averaging set here in the calibration config register DOES APPLY to normal // proximity reads. The number of averaging cycles is 2^PROX_CALIBCFG_AVG // So a value of zero in PROX_CALIBCFG_AVG disables the averaging (1 cycle, no averaging) #define PROX_CALIBSTAT_OFFSET_ADJUSTED (0x04u) // Flag when offset was automatically decremented. Cleared by writing 1 to it #define PROX_CALIBSTAT_CALIB_FINISHED (0x01u) // Flag indicating calibration is finished. Reset when matching bit in status register is cleared #define PROX_INTENAB_PIM (0x20u) // Interrupt Mode, 0: level, 1: state #define PROX_INTENAB_PIEN (0x10u) // Proximity interrupt enable #define PROX_INTENAB_PSIEN (0x08u) // Saturation interrupt enable #define PROX_INTENAB_CIEN (0x04u) // calibration interrupt enable #define PROX_INTENAB_ZIEN (0x02u) // zero interrupt enable #define PROX_TEST9_VAL (0x07u) // Datasheet simply says this must be set to TEST9 typedef enum _cal_target { Cal_Target_3 = 0, Cal_Target_7 = 1, Cal_Target_15 = 2, Cal_Target_31 = 3, Cal_Target_63 = 4, Cal_Target_127 = 5, Cal_Target_255 = 6, Cal_Target_511 = 7 } Cal_Target_T; typedef enum _prox_pulse_len { Pulse_Length_1us = 0, Pulse_Length_2us = 1, Pulse_Length_4us = 2, Pulse_Length_8us = 3, Pulse_Length_12us = 4, Pulse_Length_16us = 5, Pulse_Length_24us = 6, Pulse_Length_32us = 7, } Prox_Pulse_Length; typedef enum _prox_pd_select { Prox_PD_Near = 2, Prox_PD_Far = 1, Prox_PD_Both = 3 } Prox_PD_Select; typedef struct _prox_settings { bool pwen; // wait time enable uint8_t prate; // duration of a proximity event (actual wait time between set of pulses) bool pwlong; // long wait time, wait is multiplied by 12 uint8_t pgain; // can be 1, 2, 4, or 8 uint8_t ppulse; // Number of pulses in a prox cycle. if APC is on (default), this is the max number. Otherwise, it's just the number of pulses Prox_Pulse_Length plen; // Duration of a single pulse, from 1us to 32us (0: 1us, 7: 32us. any number larger than 7 here is not allowed) uint8_t pldrive; // laser drive strength in mA, range is 2 to 10 uint8_t pwtime; // wait time in 2.78ms increments (33.36ms when pwlong is true), setting = 0 is actually 1 unit of wait time Prox_PD_Select pdselect; // near, far, or both photodiodes uint8_t pmavg; // Moving average filter over multiple cycles uint8_t proxavg; // Hardware repetition and averaging per cycle } Prox_Settings; uint8_t tmd2635_init(I2C_Handle* hi2c, bool softreset); uint16_t tmd2635_get_distance(I2C_Handle* hi2c); uint16_t tmd2635_get_offset(I2C_Handle* hi2c); uint8_t tmd2635_set_offset(I2C_Handle* hi2c, uint16_t new_offset); bool tmd2635_calibrate(I2C_Handle* hi2c, Cal_Target_T tgt); bool tmd2635_is_connected(void); Prox_Settings* tmd2635_get_settings(void); bool tmd2635_apply_settings(I2C_Handle* hi2c); #endif /* PROX_TMD2635_H_ */