233 lines
6.1 KiB
C
233 lines
6.1 KiB
C
/*
|
|
* 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;
|
|
}
|