/* * File: ltr329.c * Description: Library for the Lite-On Optical Sensor LTR-329ALS-01 * Author: David Zaitlik * Date: 2022-05-22 * * * Copyright (c) 2024 Veles Labs s.r.o. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * */ #include "ltr329.h" static int8_t ltr329_read_register (ltr329_cmd_t register_addr, uint8_t *register_data ); static int8_t ltr329_write_register (ltr329_cmd_t register_addr, uint8_t register_data); /* * Functions to be implemented by user */ /* I2C */ int8_t ltr329_i2c_transmit(uint8_t address, uint8_t *buffer, int len) __attribute__((weak)); int8_t ltr329_i2c_receive(uint8_t address, uint8_t *buffer, int len) __attribute__((weak)); /* Interrupts */ int8_t ltr329_disable_interrupts(void) __attribute__((weak)); int8_t ltr329_enable_interrupts(void) __attribute__((weak)); /* delay function */ void delay_ms(int delay_ms) __attribute__((weak)); static int8_t ltr329_read_register (ltr329_cmd_t register_addr, uint8_t *register_data ) { uint8_t tx_buffer[1]; uint8_t rx_buffer[1]; int result; // start measurement tx_buffer[0] = register_addr; /* disable interrupts to prevent modbus/i2c conflict */ ltr329_disable_interrupts(); result = ltr329_i2c_transmit(LTR329_I2C_ADDRESS<<1, tx_buffer, 1); ltr329_enable_interrupts(); if (result != I2C_OK) { return LTR329_ERROR; } delay_ms(10); /* 10 ms should be enough */ /* read out */ ltr329_disable_interrupts(); result = ltr329_i2c_receive(LTR329_I2C_ADDRESS<<1, rx_buffer, 1); ltr329_enable_interrupts(); if (result != I2C_OK) { return LTR329_ERROR; } *register_data = rx_buffer[0]; return LTR329_OK; } static int8_t ltr329_write_register (ltr329_cmd_t register_addr, uint8_t register_data) { uint8_t tx_buffer[2]; int result; // start measurement tx_buffer[0] = register_addr; tx_buffer[1] = register_data; /* disable interrupts to prevent modbus/i2c conflict */ ltr329_disable_interrupts(); result = ltr329_i2c_transmit(LTR329_I2C_ADDRESS<<1, tx_buffer, 2); ltr329_enable_interrupts(); if (result != I2C_OK) { return LTR329_ERROR; } return LTR329_OK; } int8_t ltr329_write_settings (ltr329_gain_t gain, ltr329_als_mode_t mode, ltr329_integration_time_t integ_time, ltr329_measurement_rate_t meas_rate) { int8_t result; /* Write Gain and ALS Mode */ result = ltr329_write_register(LTR329_ALS_CONTR, (gain | mode)); if (result != LTR329_OK) { return LTR329_ERROR; } /* Write Integration Time and Measurement Rate */ result = ltr329_write_register(LTR329_ALS_MEAS_RATE, (integ_time | meas_rate)); if (result != LTR329_OK) { return LTR329_ERROR; } return LTR329_OK; } int8_t ltr329_read_settings (ltr329_gain_t *gain, ltr329_als_mode_t *mode, ltr329_integration_time_t *integ_time, ltr329_measurement_rate_t *meas_rate) { int8_t result; uint8_t control_register_data; uint8_t rate_register_data; result = ltr329_read_register(LTR329_ALS_CONTR, &control_register_data); if (result != LTR329_OK) { return LTR329_ERROR; } result = ltr329_read_register(LTR329_ALS_MEAS_RATE, &rate_register_data); if (result != LTR329_OK) { return LTR329_ERROR; } uint8_t control_register_gain_mask = 0b00011100; uint8_t control_register_mode_mask = 0b00000001; uint8_t rate_register_int_time_mask = 0b00111000; uint8_t rate_register_rate_mask = 0b00000111; /* Return Registers Values */ /* TODO: This might not be safe */ *gain = control_register_data & control_register_gain_mask; *mode = control_register_data & control_register_mode_mask; *integ_time = rate_register_data & rate_register_int_time_mask; *meas_rate = rate_register_data & rate_register_rate_mask; return LTR329_OK; } int8_t ltr329_sw_reset( void ) { int8_t result; /* Write Gain and ALS Mode */ result = ltr329_write_register(LTR329_ALS_CONTR, 0b00000010); if (result != LTR329_OK) { return LTR329_ERROR; } return LTR329_OK; } int8_t ltr329_measure (uint16_t *data_ch0, uint16_t *data_ch1) { uint8_t ch0_l, ch0_h, ch1_l, ch1_h; int result; result = ltr329_read_register(LTR329_ALS_DATA_CH0_0, &ch0_l); if (result != LTR329_OK) { return LTR329_ERROR; } result = ltr329_read_register(LTR329_ALS_DATA_CH0_1, &ch0_h); if (result != LTR329_OK) { return LTR329_ERROR; } result = ltr329_read_register(LTR329_ALS_DATA_CH1_0, &ch1_l); if (result != LTR329_OK) { return LTR329_ERROR; } result = ltr329_read_register(LTR329_ALS_DATA_CH1_1, &ch1_h); if (result != LTR329_OK) { return LTR329_ERROR; } *data_ch0 = (ch0_h << 8) + ch0_l; *data_ch1 = (ch1_h << 8) + ch1_l; return LTR329_OK; } int8_t ltr329_read_status_register(uint8_t *data_valid, uint8_t *new_data, ltr329_gain_t *gain) { int8_t result; uint8_t status_register_data; result = ltr329_read_register(LTR329_ALS_STATUS, &status_register_data); if (result != LTR329_OK) { return LTR329_ERROR; } /* Check data valid */ uint8_t data_invalid_mask = 0b10000000; if ((status_register_data & data_invalid_mask) == data_invalid_mask) { *data_valid = 0; } else { *data_valid = 1; } /* Check if there is new data */ uint8_t data_status_mask = 0b00000100; if ((status_register_data & data_status_mask) == data_status_mask) { *new_data = 1; } else { *new_data = 0; } /* Check Gain */ /* TODO: This might not be safe */ uint8_t gain_mask = 0b01110000; *gain = status_register_data & gain_mask; return LTR329_OK; } int8_t ltr329_read_device_info (uint8_t *manufacturer_id, uint8_t *part_id) { int8_t result; result = ltr329_read_register(LTR329_MANUFAC_ID, manufacturer_id); if (result != LTR329_OK) { return LTR329_ERROR; } result = ltr329_read_register(LTR329_PART_ID, part_id); if (result != LTR329_OK) { return LTR329_ERROR; } return LTR329_OK; }