I don't know if you get this or if it will help, but I've been trying to get the PPSI262 sensor to work for a while now, and I had a bit of success. Here is my python code - but you should be able to translate it to Arduino code somewhat easily - most of it is just getting the registers set correctly. I still don't have it working exactly like I want, but it's at least doing something useful!
import busio
import board
import time
import ulab
PPSI262_ADR = 0x5B
FIFO_EN = 0
FIFO_EN_MASK = 0x40
ENABLE_ULP = 0
ENABLE_ULP_MASK = 0x20
RW_CONT = 0
RW_CONT_MASK = 0x10
SW_RESET = 0
SW_RESET_MASK = 8
TM_COUNT_RST = 0
TM_COUNT_RST_MASK = 2
SPI_REG_READ = 0
SPI_REG_READ_MASK = 1
LED2STC = 1
LED2STC_MASK = 0xFFFF
LED2ENDC = 2
LED2ENDC_MASK = 0xFFFF
LED1LEDSTC = 3
LED1LEDSTC_MASK = 0xFFFF
LED1LEDENDC = 4
LED1LEDENDC_MASK = 0xFFFF
ALED2STC = 5
ALED2STC_MASK = 0xFFFF
ALED2ENDC = 6
ALED2ENDC_MASK = 0xFFFF
LED3STC = 5
LED3STC_MASK = 0xFFFF
LED3ENDC = 6
LED3ENDC_MASK = 0xFFFF
LED1STC = 7
LED1STC_MASK = 0xFFFF
LED1ENDC = 8
LED1ENDC_MASK = 0xFFFF
LED2LEDSTC = 9
LED2LEDSTC_MASK = 0xFFFF
LED2LEDENDC = 0xA
LED2LEDENDC_MASK = 0xFFFF
ALED1STC = 0xB
ALED1STC_MASK = 0xFFFF
ALED1ENDC = 0xC
ALED1ENDC_MASK = 0xFFFF
LED2CONVST = 0xD
LED2CONVST_MASK = 0xFFFF
LED2CONVEND = 0xE
LED2CONVEND_MASK = 0xFFFF
LED3CONVST = 0xF
LED3CONVST_MASK = 0xFFFF
LED3CONVEND = 0x10
LED3CONVEND_MASK = 0xFFFF
ALED2CONVST = 0xF
ALED2CONVST_MASK = 0xFFFF
ALED2CONVEND = 0x10
ALED2CONVEND_MASK = 0xFFFF
LED1CONVST = 0x11
LED1CONVST_MASK = 0xFFFF
LED1CONVEND = 0x12
LED1CONVEND_MASK = 0xFFFF
ALED1CONVST = 0x13
ALED1CONVST_MASK = 0xFFFF
ALED1CONVEND = 0x14
ALED1CONVEND_MASK = 0xFFFF
PRPCOUNT = 0x1D
PRPCOUNT_MASK = 0xFFFF
TIMEREN = 0x1E
TIMEREN_MASK = 0x100
NUMAV = 0x1E
NUMAV_MASK = 0xF
TIA_GAIN_SEP3_MSB = 0x1F
TIA_GAIN_SEP3_MSB_MASK = 0x4000
TIA_CF_SEP3 = 0x1F
TIA_CF_SEP3_MASK = 0x3800
TIA_GAIN_SEP3_LSB = 0x1F
TIA_GAIN_SEP3_LSB_MASK = 0x700
TIA_GAIN_SEP2_MSB = 0x1F
TIA_GAIN_SEP2_MSB_MASK = 0x40
TIA_CF_SEP2 = 0x1F
TIA_CF_SEP2_MASK = 0x38
TIA_GAIN_SEP2_LSB = 0x1F
TIA_GAIN_SEP2_LSB_MASK = 7
ENSEPGAIN = 0x20
ENSEPGAIN_MASK = 0x8000
TIA_GAIN_SEP_MSB = 0x20
TIA_GAIN_SEP_MSB_MASK = 0x40
TIA_CF_SEP = 0x20
TIA_CF_SEP_MASK = 0x38
TIA_GAIN_SEP_LSB = 0x20
TIA_GAIN_SEP_LSB_MASK = 7
IFS_OFFDAC = 0x21
IFS_OFFDAC_MASK = 0x7000
FILTER_BW_0 = 0x21
FILTER_BW_0_MASK = 0x200
TIA_GAIN_MSB = 0x21
TIA_GAIN_MSB_MASK = 0x40
TIA_CF = 0x21
TIA_CF_MASK = 0x38
TIA_GAIN_LSB = 0x21
TIA_GAIN_LSB_MASK = 7
ILED3_LSB = 0x22
ILED3_LSB_MASK = 0xC00000
ILED2_LSB = 0x22
ILED2_LSB_MASK = 0x300000
ILED1_LSB = 0x22
ILED1_LSB_MASK = 0xC0000
ILED3_MSB = 0x22
ILED3_MSB_MASK = 0x3F000
ILED2_MSB = 0x22
ILED2_MSB_MASK = 0xFC0
ILED1_MSB = 0x22
ILED1_MSB_MASK = 0x3F
CONTROL_DYN_TX_0 = 0x23
CONTROL_DYN_TX_0_MASK = 0x100000
ILED_FS = 0x23
ILED_FS_MASK = 0x20000
ENSEPGAIN4 = 0x23
ENSEPGAIN4_MASK = 0x8000
CONTROL_DYN_BIAS = 0x23
CONTROL_DYN_BIAS_MASK = 0x4000
OSC_ENABLE = 0x23
OSC_ENABLE_MASK = 0x200
CONTROL_DYN_TIA = 0x23
CONTROL_DYN_TIA_MASK = 0x10
CONTROL_DYN_ADC = 0x23
CONTROL_DYN_ADC_MASK = 8
PDNRX = 0x23
PDNRX_MASK = 2
PDNAFE = 0x23
PDNAFE_MASK = 1
ILED4_MSB = 0x24
ILED4_MSB_MASK = 0x1F800
ILED4_LSB = 0x24
ILED4_LSB_MASK = 0x600
FIFO_TOGGLE = 0x28
FIFO_TOGGLE_MASK = 0x400000
DESIGN_ID = 0x28
DESIGN_ID_MASK = 0x1FFF80
SDOUT_TRISTATE_D = 0x29
SDOUT_TRISTATE_D_MASK = 0x80000
SDOUT_TRISTATE = 0x29
SDOUT_TRISTATE_MASK = 0x200
LED2VAL = 0x2A
LED2VAL_MASK = 0xFFFFFF
LED3VAL = 0x2B
LED3VAL_MASK = 0xFFFFFF
ALED2VAL = 0x2B
ALED2VAL = 0xFFFFFF
LED1VAL = 0x2C
LED1VAL_MASK = 0xFFFFFF
ALED1VAL = 0x2D
ALED1VAL_MASK = 0xFFFFFF
LED2_MINUS_ALED2VAL = 0x2E
LED2_MINUS_ALED2VAL_MASK = 0xFFFFFF
LED1_MINUS_ALED1VAL = 0x2F
LED1_MINUS_ALED1VAL_MASK = 0xFFFFFF
FILTER_BW_1 = 0x31
FILTER_BW_1_MASK = 0x800000
PD_DISCONNECT = 0x31
PD_DISCONNECT_MASK = 0x400
ENABLE_INPUT_SHORT = 0x31
ENABLE_INPUT_SHORT_MASK = 0x20
PROG_INT2_STC = 0x34
PROG_INT2_STC_MASK = 0xFFFF
PROG_INT2_ENDC = 0x35
PROG_INT2_ENDC_MASK = 0xFFFF
LED3LEDSTC = 0x36
LED3LEDSTC_MASK = 0xFFFF
LED3LEDENDC = 0x37
LED3LEDENDC_MASK = 0xFFFF
CLKDIV_TE = 0x39
CLKDIV_TE_MASK = 7
EARLY_OFFSET_DAC = 0x3A
EARLY_OFFSET_DAC_MASK = 0x100000
POL_OFFDAC_LED2 = 0x3A
POL_OFFDAC_LED2_MASK = 0x80000
I_OFFDAC_LED2_MID_A = 0x3A
I_OFFDAC_LED2_MID_A_MASK = 0x78000
POL_OFFDAC_AMB1 = 0x3A
POL_OFFDAC_AMB1_MASK = 0x4000
I_OFFDAC_LED2_MID_B = 0x3A
I_OFFDAC_LED2_MID_B_MASK = 0x3C00
POL_OFFDAC_LED1 = 0x3A
POL_OFFDAC_LED1_MASK = 0x200
I_OFFDAC_LED2_MID_C = 0x3A
I_OFFDAC_LED2_MID_C_MASK = 0x1E0
POL_OFFDAC_LED3 = 0x3A
POL_OFFDAC_LED3_MASK = 0x10
I_OFFDAC_LED3_MID = 0x3A
I_OFFDAC_LED3_MID_MASK = 0xF
POL_OFFDAC_AMB2 = 0x3A
POL_OFFDAC_AMB2_MASK = 0x10
I_OFFDAC_AMB2_MID = 0x3A
I_OFFDAC_AMB2_MID_MASK = 0xF
THR_DET_LOW_CODE = 0x3B
THR_DET_LOW_CODE_MASK = 0xFFFFFF
THR_DET_HIGH_CODE = 0x3C
THR_DET_HIGH_CODE_MASK = 0xFFFFFF
WM_MODE = 0x3D
WM_MODE_MASK = 0x80000
THR_DET_PHASE_SEL_BIT_7 = 0x3D
THR_DET_PHASE_SEL_BIT_7_MASK = 0x8000
THR_DET_PHASE_SEL_BIT_6 = 0x3D
THR_DET_PHASE_SEL_BIT_6_MASK = 0x4000
THR_DET_PHASE_SEL_BIT_5 = 0x3D
THR_DET_PHASE_SEL_BIT_5_MASK = 0x2000
THR_DET_PHASE_SEL_BIT_4 = 0x3D
THR_DET_PHASE_SEL_BIT_4_MASK = 0x1000
THR_DET_PHASE_SEL_BIT_3 = 0x3D
THR_DET_PHASE_SEL_BIT_3_MASK = 0x800
THR_DET_PHASE_SEL_BIT_2 = 0x3D
THR_DET_PHASE_SEL_BIT_2_MASK = 0x400
THR_DET_PHASE_SEL_BIT_1 = 0x3D
THR_DET_PHASE_SEL_BIT_1_MASK = 0x100
THR_DET_PHASE_SEL_BIT_8 = 0x3D
THR_DET_PHASE_SEL_BIT_8_MASK = 0x80
FIFO_EN_DEC = 0x3D
FIFO_EN_DEC_MASK = 0x40
DEC_EN = 0x3D
DEC_EN_MASK = 0x20
THR_DET_EN = 0x3D
THR_DET_EN_MASK = 0x10
DEC_FACTOR = 0x3D
DEC_FACTOR_MASK = 0xE
THR_DET_PHASE_SEL_BIT_0 = 0x3D
THR_DET_PHASE_SEL_BIT_0_MASK = 1
I_OFF_DAC_LED2_LSB_EXT = 0x3E
I_OFF_DAC_LED2_LSB_EXT_MASK = 0x1000
I_OFF_DAC_AMB_LSB_EXT = 0x3E
I_OFF_DAC_AMB_LSB_EXT_MASK = 0x800
I_OFF_DAC_LED1_LSB_EXT = 0x3E
I_OFF_DAC_LED1_LSB_EXT_MASK = 0x400
I_OFF_DAC_LED3_LSB_EXT = 0x3E
I_OFF_DAC_LED3_LSB_EXT_MASK = 0x100
I_OFF_DAC_LED2_MSB = 0x3E
I_OFF_DAC_LED2_MSB_MASK = 0x80
I_OFF_DAC_LED2_LSB = 0x3E
I_OFF_DAC_LED2_LSB_MASK = 0x40
I_OFF_DAC_AMB_MSB = 0x3E
I_OFF_DAC_AMB_MSB_MASK = 0x20
I_OFF_DAC_AMB_LSB = 0x3E
I_OFF_DAC_AMB_LSB_MASK = 0x10
I_OFF_DAC_LED1_MSB = 0x3E
I_OFF_DAC_LED1_MSB_MASK = 8
I_OFF_DAC_LED1_LSB = 0x3E
I_OFF_DAC_LED1_LSB_MASK = 4
I_OFF_DAC_LED3_MSB = 0x3E
I_OFF_DAC_LED3_MSB_MASK = 2
I_OFF_DAC_LED3_LSB = 0x3E
I_OFF_DAC_LED3_LSB_MASK = 1
AVG_LED2_MINUS_ALED2VAL = 0x3F
AVG_LED2_MINUS_ALED2VAL_MASK = 0xFFFFFF
AVG_LED1_MINUS_ALED1VAL = 0x40
AVG_LED1_MINUS_ALED1VAL_MASK = 0xFFFFFF
INT_MUX3 = 0x42
INT_MUX3_MASK = 0xC00000
INT_MUX2 = 0x42
INT_MUX2_MASK = 0x300000
FIFO_EARLY = 0x42
FIFO_EARLY_MASK = 0x7C000
REG_WM_FIFO = 0x42
REG_WM_FIFO_MASK = 0x3FC0
REG_FIFO_PERIOD = 0x42
REG_FIFO_PERIOD_MASK = 0x3FC0
INT_MUX1 = 0x42
INT_MUX1_MASK = 0x30
FIFO_PARTITION = 0x42
FIFO_PARTITION_MASK = 0xF
LED4LEDSTC = 0x43
LED4LEDSTC_MASK = 0xFFFF
LED4LEDENDC = 0x44
LED4LEDENDC_MASK = 0xFFFF
TG_PD1STC = 0x45
TG_PD1STC_MASK = 0xFFFF
TG_PD1ENDC = 0x46
TG_PD1ENDC_MASK = 0xFFFF
TG_PD2STC = 0x47
TG_PD2STC_MASK = 0xFFFF
TG_PD2ENDC = 0x48
TG_PD2ENDC_MASK = 0xFFFF
TG_PD3STC = 0x49
TG_PD3STC_MASK = 0xFFFF
TG_PD3ENDC = 0x4A
TG_PD3ENDC_MASK = 0xFFFF
EN_PROG_OUT1 = 0x4B
EN_PROG_OUT1_MASK = 0x100
CONTROL_DYN_VCM = 0x4B
CONTROL_DYN_VCM_MASK = 8
CONTROL_DYN_DLDO = 0x4B
CONTROL_DYN_DLDO_MASK = 4
CONTROL_DYN_ALDO = 0x4B
CONTROL_DYN_ALDO_MASK = 2
CONTROL_DYN_BG = 0x4B
CONTROL_DYN_BG_MASK = 1
TRIPLE_PD_ENABLE = 0x4E
TRIPLE_PD_ENABLE_MASK = 0x10
DUAL_PD_ENABLE = 0x4E
DUAL_PD_ENABLE_MASK = 8
SHORT_ALDO_TO_DLDO_IN_DEEP_SLEEP = 0x50
SHORT_ALDO_TO_DLDO_IN_DEEP_SLEEP_MASK = 0x20
CONTROL_DYN_TX_1 = 0x50
CONTROL_DYN_TX_1_MASK = 8
MASK_FIFO_RDY = 0x51
MASK_FIFO_RDY_MASK = 0x200
FORCE_FIFO_OFFSET = 0x51
FORCE_FIFO_OFFSET_MASK = 0x100
FIFO_OFFSET_TO_FORCE = 0x51
FIFO_OFFSET_TO_FORCE_MASK = 0xFF
DATA_RDY_STC = 0x52
DATA_RDY_STC_MASK = 0xFFFF
DATA_RDY_ENDC = 0x53
DATA_RDY_ENDC_MASK = 0xFFFF
MASK_PPG = 0x54
MASK_PPG_MASK = 0x7000
MASK1_PPG = 0x54
MASK1_PPG_MASK = 0x1C0
MASK2_PPG = 0x54
MASK2_PPG_MASK = 0x38
MASK3_PPG = 0x54
MASK3_PPG_MASK = 7
PROG_INT1_STC = 0x57
PROG_INT1_STC_MASK = 0xFFFF
PROG_INT1_ENDC = 0x58
PROG_INT1_ENDC_MASK = 0xFFFF
EN_AMB_LOOP = 0x60
EN_AMB_LOOP_MASK = 0x800
CHOOSE_AMB_PHASE = 0x60
CHOOSE_AMB_PHASE_MASK = 0x600
FREEZE_LOOP = 0x60
FREEZE_LOOP_MASK = 0x20
HYST_LOOP = 0x60
HYST_LOOP_MASK = 0x18
DYN_TIA_STC = 0x64
DYN_TIA_STC_MASK = 0xFFFF
DYN_TIA_ENDC = 0x65
DYN_TIA_ENDC_MASK = 0xFFFF
DYN_ADC_STC = 0x66
DYN_ADC_STC_MASK = 0xFFFF
DYN_ADC_ENDC = 0x67
DYN_ADC_ENDC_MASK = 0xFFFF
DYN_CLK_STC = 0x68
DYN_CLK_STC_MASK = 0xFFFF
DYN_CLK_ENDC = 0x69
DYN_CLK_ENDC_MASK = 0xFFFF
DEEP_SLEEP_STC = 0x6A
DEEP_SLEEP_STC_MASK = 0xFFFF
DEEP_SLEEP_ENDC = 0x6B
DEEP_SLEEP_ENDC_MASK = 0xFFFF
REG_POINTER_DIFF = 0x6D
REG_POINTER_DIFF_MASK = 0xFF
EN_DRV2_LED4 = 0x72
EN_DRV2_LED4_MASK = 0x80
EN_DRV2_LED3 = 0x72
EN_DRV2_LED3_MASK = 0x40
EN_DRV2_LED2 = 0x72
EN_DRV2_LED2_MASK = 0x20
EN_DRV2_LED1 = 0x72
EN_DRV2_LED1_MASK = 0x10
DIS_DRV1_LED4 = 0x72
DIS_DRV1_LED4_MASK = 8
DIS_DRV1_LED3 = 0x72
DIS_DRV1_LED3_MASK = 4
DIS_DRV1_LED2 = 0x72
DIS_DRV1_LED2_MASK = 2
DIS_DRV1_LED1 = 0x72
MASK_DIS_DRV1_LED1 = 1
current_fifo_toggle = 0
last_fifo_read = time.monotonic()
sample_count = 1
samples_to_average = 6
internal_osc_freq = 128000
clock_divisor = 1
pulse_rep_freq = 150
## legacy testing/proofing code
CSR_ADRS = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x31, 0x34, 0x35, 0x36, 0x37, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4E, 0x50, 0x51, 0x52, 0x53, 0x54, 0x57, 0x58, 0x60, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6D, 0x72]
# Get thewhole 24-bit value of a register by it's address
def readcsr(i2c, addr):
readcsr = bytearray(3)
i2c.writeto_then_readfrom(PPSI262_ADR, bytes([addr]), readcsr)
value = int.from_bytes(readcsr, 'big')
return value
# Set thewhole 24-bit value of a register by it's address
def writecsr(i2c, addr, value):
writecsr = ((addr << 24) + value).to_bytes(4, 'big')
i2c.writeto(PPSI262_ADR, writecsr)
# Read out the entire contents of the device's registers
def dumpcsrs(i2c):
for address in CSR_ADRS:
print(hex(address), ":", (readcsr(i2c, address)))
# Returns the index, counting from 0, of the least significant set bit in `x`.
def ffs(x):
return (x&-x).bit_length()-1
# Invert the bits in a 24-bit (or otherwise specified) number
def bit_not(n, numbits=24):
return (1 << numbits) - 1 - n
# Get the value of a specific register by it's name and mask
def register_get(i2c, addr, mask, shift=True):
readcsr = bytearray(3)
i2c.writeto_then_readfrom(PPSI262_ADR, bytes([addr]), readcsr)
value = (int.from_bytes(readcsr, 'big') & mask)
if (shift == True):
value = value >> ffs(mask)
return value
# Set the value of a specific register by it's name and mask
def register_set(i2c, addr, mask, value):
old_value = register_get(i2c, addr, 0xFFFFFF, False)
old_value = old_value & bit_not(mask)
value = old_value | (value << ffs(mask))
writecsr = ((addr << 24) | value).to_bytes(4, 'big')
i2c.writeto(PPSI262_ADR, writecsr)
# Preform a software reset
def sw_reset(i2c):
register_set(i2c, SW_RESET, SW_RESET_MASK, 1)
# read the FIFO
def read_fifo(i2c):
global current_fifo_toggle, sample_count, samples_to_average, pulse_rep_freq, last_fifo_read
"""
# wait until the FIFO is ready
new_fifo_toggle = register_get(i2c, FIFO_TOGGLE, FIFO_TOGGLE_MASK)
if (current_fifo_toggle == None):
current_fifo_toggle = new_fifo_toggle
while (current_fifo_toggle == new_fifo_toggle):
new_fifo_toggle = register_get(i2c, FIFO_TOGGLE, FIFO_TOGGLE_MASK)
current_fifo_toggle = new_fifo_toggle
#time.sleep(0.0001)
"""
time_now = time.monotonic()
while (last_fifo_read > time_now):
time_now = time.monotonic()
last_fifo_read = time_now + samples_to_average/pulse_rep_freq
# Force the FIFO read pointer to the beginning of the data
#register_set(i2c, FORCE_FIFO_OFFSET, FORCE_FIFO_OFFSET_MASK, 1)
#register_set(i2c, FIFO_OFFSET_TO_FORCE, FIFO_OFFSET_TO_FORCE_MASK, 0)
led2_values = []
led1_values = []
readcsr = bytearray(6 * sample_count)
i2c.writeto_then_readfrom(PPSI262_ADR, bytes([0xFF]), readcsr)
for i in range(sample_count):
j = i * 6
led2_values.append(int.from_bytes(readcsr[j:(j+3)], 'big'))
led1_values.append(int.from_bytes(readcsr[(j+3):(j+6)], 'big'))
return [led1_values, led2_values]
# Initialize the sensor
def init_sensor(i2c):
global current_fifo_toggle, sample_count, samples_to_average, internal_osc_freq, clock_divisor, pulse_rep_freq
# reset the device
sw_reset(i2c)
time.sleep(0.01)
# Divide the clock
if (clock_divisor >= 16):
register_set(i2c, CLKDIV_TE, CLKDIV_TE_MASK, 7)
clock_divisor = 16
elif (clock_divisor >= 8):
register_set(i2c, CLKDIV_TE, CLKDIV_TE_MASK, 6)
clock_divisor = 8
elif (clock_divisor >= 4):
register_set(i2c, CLKDIV_TE, CLKDIV_TE_MASK, 5)
clock_divisor = 4
elif (clock_divisor >= 2):
register_set(i2c, CLKDIV_TE, CLKDIV_TE_MASK, 4)
clock_divisor = 2
else:
register_set(i2c, CLKDIV_TE, CLKDIV_TE_MASK, 0)
clock_divisor = 1
clock_freq = internal_osc_freq / clock_divisor
tick_period = 1000000 / clock_freq
prf_count = int(clock_freq / pulse_rep_freq) - 1
# get the current value of FIFO_TOGGLE (it alternates between 1 and 0 as FIFO_RDY is triggered)
current_fifo_toggle = None #register_get(i2c, FIFO_TOGGLE, FIFO_TOGGLE_MASK)
register_set(i2c, NUMAV, NUMAV_MASK, int(samples_to_average - 1)) # Set the ADC output to be the average of [samples_to_average] samples
# Setup LED current drivers and switching
register_set(i2c, ILED_FS, ILED_FS_MASK, 1) # Set the full-scale output of the LED current driver to 100mA (set to 0 for 50mA)
register_set(i2c, EN_DRV2_LED1, EN_DRV2_LED1_MASK, 1) # Enable the second current dirver for LED1 (Green)
register_set(i2c, EN_DRV2_LED2, EN_DRV2_LED2_MASK, 1) # Enable the second current dirver for LED1 (IR)
# Green LED (LED1) - Should output 150mA according to datasheet
register_set(i2c, ILED1_MSB, ILED1_MSB_MASK, 63) # LED1's current to 100mA * 2 drivers = 200mA (high bits)
register_set(i2c, ILED1_LSB, ILED1_LSB_MASK, 3) # LED1's current to 100mA * 2 drivers = 200mA (low bits)
# IR LED (LED2) - Should output 100 mA according to datasheet
register_set(i2c, ILED2_MSB, ILED2_MSB_MASK, 63) # LED2's current to 75mA * 2 drivers = 150mA (high bits)
register_set(i2c, ILED2_LSB, ILED2_LSB_MASK, 3) # LED2's current to 75mA * 2 drivers = 150mA (low bits)
# Turn off LED3 and LED4 - Not needed because they are off by default
#register_set(i2c, ILED3_MSB, ILED3_MSB_MASK, 0) # LED3's current to OFF (high bits)
#register_set(i2c, ILED3_LSB, ILED3_LSB_MASK, 0) # LED3's current to OFF (low bits)
#register_set(i2c, ILED4_MSB, ILED4_MSB_MASK, 0) # LED4's current to OFF (high bits)
#register_set(i2c, ILED4_LSB, ILED4_LSB_MASK, 0) # LED4's current to OFF (low bits)
# Determine the sampling rate for the sensor (relative to the PRF?) - all 4 should be set to idential values
register_set(i2c, MASK_PPG, MASK_PPG_MASK, 0b0) # 3 bits wide - no idea what this does.
register_set(i2c, MASK1_PPG, MASK1_PPG_MASK, 0b0)
register_set(i2c, MASK2_PPG, MASK2_PPG_MASK, 0b0)
register_set(i2c, MASK3_PPG, MASK3_PPG_MASK, 0b0)
# Set the TIA (trans-impedence amplifier) gain
register_set(i2c, TIA_GAIN_LSB, TIA_GAIN_LSB_MASK, 0b011) # 3-bits (LSB) - resistor value
register_set(i2c, TIA_GAIN_MSB, TIA_GAIN_MSB_MASK, 0) # 1-bit (MSB)
register_set(i2c, TIA_CF, TIA_CF_MASK, 0b000) # 3-bits - capacitor value
# Setup the FIFO
register_set(i2c, FIFO_PARTITION, FIFO_PARTITION_MASK, 5) # store (LED2—Ambient2), (LED1—Ambient1) ADC values
register_set(i2c, REG_FIFO_PERIOD, REG_FIFO_PERIOD_MASK, sample_count) # retain [sample_count] sample cycles
register_set(i2c, FIFO_EN, FIFO_EN_MASK, 1) # turn on the FIFO
active_phase_start = int(520 / tick_period) + 1
led_on_width = int(70 / tick_period) + 1
sampling_start_delay = int(30 / tick_period) + 1
sampling_width = int(35 / tick_period) + 1
convert_start_delay = led_on_width + 2
convert_width = int((56.5 * samples_to_average + 72) / tick_period) + 16 #+ 4
phase_width = convert_start_delay + convert_width + 4 #+ led_on_width
phase_0_start = 0 + active_phase_start
phase_1_start = phase_width * 1 + active_phase_start
phase_2_start = phase_width * 2 + active_phase_start
phase_3_start = phase_width * 3 + active_phase_start
## TODO:
# If active_phase_end is greater than the PRF count, throw an error
# Set up deep sleep behavior options
# Set up external oscillator options
dont_activate = prf_count + 16
# Set the sensor to run a 500Hz PRF (Pulse Repetition Frequency) cycle
register_set(i2c, PRPCOUNT, PRPCOUNT_MASK, prf_count)
register_set(i2c, ENABLE_ULP, ENABLE_ULP_MASK, 1)
register_set(i2c, LED2LEDSTC, LED2LEDSTC_MASK, phase_0_start)
register_set(i2c, LED2LEDENDC, LED2LEDENDC_MASK, phase_0_start + led_on_width)
register_set(i2c, LED2STC, LED2STC_MASK, phase_0_start + sampling_start_delay)
register_set(i2c, LED2ENDC, LED2ENDC_MASK, phase_0_start + sampling_start_delay + sampling_width)
register_set(i2c, LED2CONVST, LED2CONVST_MASK, phase_0_start + convert_start_delay)
register_set(i2c, LED2CONVEND, LED2CONVEND_MASK, phase_0_start + convert_start_delay + convert_width)
register_set(i2c, LED3LEDSTC, LED3LEDSTC_MASK, dont_activate) # Don't turn on
register_set(i2c, LED3LEDENDC, LED3LEDENDC_MASK, dont_activate) # Don't turn on
register_set(i2c, ALED2STC, ALED2STC_MASK, phase_1_start + sampling_start_delay)
register_set(i2c, ALED2ENDC, ALED2ENDC_MASK, phase_1_start + sampling_start_delay + sampling_width)
register_set(i2c, ALED2CONVST, ALED2CONVST_MASK, phase_1_start + convert_start_delay)
register_set(i2c, ALED2CONVEND, ALED2CONVEND_MASK, phase_1_start + convert_start_delay + convert_width)
register_set(i2c, LED1LEDSTC, LED1LEDSTC_MASK, phase_2_start)
register_set(i2c, LED1LEDENDC, LED1LEDENDC_MASK, phase_2_start + led_on_width)
register_set(i2c, LED1STC, LED1STC_MASK, phase_2_start + sampling_start_delay)
register_set(i2c, LED1ENDC, LED1ENDC_MASK, phase_2_start + sampling_start_delay + sampling_width)
register_set(i2c, LED1CONVST, LED1CONVST_MASK, phase_2_start + convert_start_delay)
register_set(i2c, LED1CONVEND, LED1CONVEND_MASK, phase_2_start + convert_start_delay + convert_width)
register_set(i2c, LED4LEDSTC, LED4LEDSTC_MASK, dont_activate) # Don't turn on
register_set(i2c, LED4LEDENDC, LED4LEDENDC_MASK, dont_activate) # Don't turn on
register_set(i2c, ALED1STC, ALED1STC_MASK, phase_3_start + sampling_start_delay)
register_set(i2c, ALED1ENDC, ALED1ENDC_MASK, phase_3_start + sampling_start_delay + sampling_width)
register_set(i2c, ALED1CONVST, ALED1CONVST_MASK, phase_3_start + convert_start_delay)
register_set(i2c, ALED1CONVEND, ALED1CONVEND_MASK, phase_3_start + convert_start_delay + convert_width)
register_set(i2c, DATA_RDY_STC, DATA_RDY_STC_MASK, phase_3_start + convert_start_delay + convert_width + 6)
register_set(i2c, DATA_RDY_ENDC, DATA_RDY_ENDC_MASK, phase_3_start + convert_start_delay + convert_width + 7)
# Active phase start and end timings
register_set(i2c, DYN_TIA_STC, DYN_TIA_STC_MASK, 0)
register_set(i2c, DYN_TIA_ENDC, DYN_TIA_ENDC_MASK, dont_activate)
register_set(i2c, DYN_ADC_STC, DYN_ADC_STC_MASK, 0)
register_set(i2c, DYN_ADC_ENDC, DYN_ADC_ENDC_MASK, dont_activate)
register_set(i2c, DYN_CLK_STC, DYN_CLK_STC_MASK, 0)
register_set(i2c, DYN_CLK_ENDC, DYN_CLK_ENDC_MASK, dont_activate)
# Deep sleep behavior
#register_set(i2c, CONTROL_DYN_TIA, CONTROL_DYN_TIA_MASK, 0)
#register_set(i2c, CONTROL_DYN_ADC, CONTROL_DYN_ADC_MASK, 0)
#register_set(i2c, CONTROL_DYN_ALDO, CONTROL_DYN_ALDO_MASK, 0)
#register_set(i2c, CONTROL_DYN_DLDO, CONTROL_DYN_DLDO_MASK, 0)
#register_set(i2c, SHORT_ALDO_TO_DLDO_IN_DEEP_SLEEP, SHORT_ALDO_TO_DLDO_IN_DEEP_SLEEP_MASK, 1)
# Deep sleep phase start and end timings
register_set(i2c, DEEP_SLEEP_STC, DEEP_SLEEP_STC_MASK, dont_activate) # Don't go into deep sleep
register_set(i2c, DEEP_SLEEP_ENDC, DEEP_SLEEP_ENDC_MASK, dont_activate) # Don't go into deep sleep
# Enable the internal oscillator
register_set(i2c, OSC_ENABLE, OSC_ENABLE_MASK, 1) # Turn on the internal oscillator
def start_sensor(i2c):
# start the timer to begin operation
register_set(i2c, TIMEREN, TIMEREN_MASK, 1)
def stop_sensor(i2c):
# start the timer to begin operation
register_set(i2c, TIMEREN, TIMEREN_MASK, 0)
i2c = busio.I2C(scl=board.GP21, sda=board.GP20)
i2c.try_lock()
init_sensor(i2c)
time.sleep(0.1)
start_sensor(i2c)
readings = [[],[], []]
start_time = time.monotonic()
#for i in range(300):
avg1 = 0
avg0 = 0
count_total = 0
last_reading = [[0,0,0],[0,0,0]]
for i in range(30):
sensor_output = read_fifo(i2c)
avg1 = sensor_output[1][0]
avg0 = sensor_output[0][0]
last_reading[0].append(sensor_output[0][0])
last_reading[0].pop(0)
last_reading[1].append(sensor_output[1][0])
last_reading[1].pop(0)
while True:
count_total = count_total + 1
if (count_total > 20):
count_total = 20
sensor_output = read_fifo(i2c)
last_reading[0].append(sensor_output[0][0])
last_reading[0].pop(0)
last_reading[1].append(sensor_output[1][0])
last_reading[1].pop(0)
avg0 = (avg0 * count_total + sensor_output[0][0]) / (count_total + 1)
avg1 = (avg1 * count_total + sensor_output[1][0]) / (count_total + 1)
print((ulab.numpy.mean(last_reading[0]) - avg0, + (ulab.numpy.mean(last_reading[1]) - avg1) * 10))
#readings[0].append(sensor_output[0])
#readings[1].append(sensor_output[1])
#readings[2].append([time.monotonic() - start_time] * sample_count)
time.sleep(0.05)
stop_sensor(i2c)
print("sensor output")
print(readings)
## Dump out everything before and after software reset
#
#dumpcsrs(i2c)
#sw_reset(i2c)
#dumpcsrs(i2c)
i2c.unlock()
i2c.deinit()