mirror of
https://github.com/eclipse/upm.git
synced 2025-03-15 04:57:30 +03:00
BH1792: C/C++ driver for ROHM heart rate sensor
- Base C implementation, with all features and measurement modes (interrupts uses ISR) - C++ wrapper around C implementation Signed-off-by: Assam Boudjelthia <assam.boudjelthia@fi.rohmeurope.com> Signed-off-by: Mihai Tudor Panu <mihai.tudor.panu@intel.com>
This commit is contained in:
parent
c2ce3e8222
commit
e0105cb601
8
src/bh1792/CMakeLists.txt
Executable file
8
src/bh1792/CMakeLists.txt
Executable file
@ -0,0 +1,8 @@
|
||||
upm_mixed_module_init (NAME bh1792
|
||||
DESCRIPTION "ROHM Color Sensor"
|
||||
C_HDR bh1792.h bh1792glc_registers.h
|
||||
C_SRC bh1792.c
|
||||
CPP_HDR bh1792.hpp
|
||||
CPP_SRC bh1792.cxx
|
||||
CPP_WRAPS_C
|
||||
REQUIRES mraa)
|
889
src/bh1792/bh1792.c
Executable file
889
src/bh1792/bh1792.c
Executable file
@ -0,0 +1,889 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Author: Assam Boudjelthia
|
||||
* Copyright (c) 2018 Rohm Semiconductor.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "bh1792.h"
|
||||
|
||||
/**
|
||||
* @brief Reads the value of a register
|
||||
*
|
||||
* @param dev The sensor context
|
||||
* @param reg Register address
|
||||
* @param data Pointer of uint8_t to save register value
|
||||
* @return UPM result
|
||||
*/
|
||||
static upm_result_t bh1792_read_register(bh1792_context dev, uint8_t reg,
|
||||
uint8_t *data);
|
||||
|
||||
/**
|
||||
* @brief Reads the values of a set of registers
|
||||
*
|
||||
* @param dev The sensor context
|
||||
* @param reg Register address
|
||||
* @param data Pointer of uint8_t to save registers values
|
||||
* @return UPM result
|
||||
*/
|
||||
static upm_result_t bh1792_read_registers(bh1792_context dev, uint8_t reg,
|
||||
uint8_t *data, uint8_t len);
|
||||
|
||||
/**
|
||||
* @brief Writes a value to a register
|
||||
*
|
||||
* @param dev The sensor context
|
||||
* @param value Value to write
|
||||
* @param reg Register address
|
||||
* @return UPM result
|
||||
*/
|
||||
static upm_result_t bh1792_write_register(bh1792_context dev, uint8_t value,
|
||||
uint8_t reg);
|
||||
|
||||
/**
|
||||
* @brief Sets a bit on in a register with a bit mask
|
||||
*
|
||||
* @param dev The sensor context
|
||||
* @param reg Register address
|
||||
* @param bit_mask Mask to use
|
||||
* @return UPM result
|
||||
*/
|
||||
static upm_result_t bh1792_set_bit_on(bh1792_context dev, uint8_t reg,
|
||||
uint8_t bit_mask);
|
||||
|
||||
/**
|
||||
* @brief Sets a bit off in a register with a bit mask
|
||||
*
|
||||
* @param dev The sensor context
|
||||
* @param reg Register address
|
||||
* @param bit_mask Mask to use
|
||||
* @return UPM result
|
||||
*/
|
||||
static upm_result_t bh1792_set_bit_off(bh1792_context dev, uint8_t reg,
|
||||
uint8_t bit_mask);
|
||||
|
||||
/**
|
||||
* @brief Sets the value of a register as a given pattern with a bit mask
|
||||
*
|
||||
* @param dev The sensor context
|
||||
* @param reg Register address
|
||||
* @param value Value to write
|
||||
* @param bit_mask Mask to use
|
||||
* @return UPM result
|
||||
*/
|
||||
static upm_result_t bh1792_set_bits_with_mask(bh1792_context dev, uint8_t reg,
|
||||
uint8_t value, uint8_t bit_mask);
|
||||
|
||||
/**
|
||||
* @brief Writes sync bit each 1 second. This function is used in a thread.
|
||||
*
|
||||
* @param dev The sensor context
|
||||
*/
|
||||
static void *bh1792_sync_measurement(void *args);
|
||||
|
||||
/**
|
||||
* @brief Sets the measurement time for synchronized mode
|
||||
*
|
||||
* @param dev The sensor context
|
||||
* @param meas_mode Measurement mode choice, take a value of MEAS_MODES
|
||||
* @return UPM result
|
||||
*/
|
||||
static upm_result_t bh1792_set_sync_meas_mode(bh1792_context dev, uint16_t meas_freq);
|
||||
|
||||
/**
|
||||
* @brief Selects the LED light type to use for measurement
|
||||
*
|
||||
* @param dev The sensor context
|
||||
* @param led_type Can take a value of GREEN or IR
|
||||
* @return UPM result
|
||||
*/
|
||||
static upm_result_t bh1792_select_led_type(bh1792_context dev, LED_TYPES led_type);
|
||||
|
||||
/**
|
||||
* @brief Sets the interrupt mode to be used, this is called when choosing
|
||||
* operation mode
|
||||
*
|
||||
* @param dev The sensor context
|
||||
* @param int_mode Interrupt mode, one of INTERRUPT_MODES values
|
||||
* @return UPM result
|
||||
*/
|
||||
static upm_result_t bh1792_set_interrupt_mode(bh1792_context dev, INTERRUPT_MODES int_mode);
|
||||
|
||||
/**
|
||||
* @brief Sets the RDY bit of the sensor
|
||||
*
|
||||
* @param dev The sensor context
|
||||
* @return UPM result
|
||||
*/
|
||||
static upm_result_t bh1792_set_rdy_bit(bh1792_context dev);
|
||||
|
||||
|
||||
static upm_result_t bh1792_read_register(bh1792_context dev, uint8_t reg,
|
||||
uint8_t *data)
|
||||
{
|
||||
if(!dev)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
uint8_t value = mraa_i2c_read_byte_data(dev->i2c, reg);
|
||||
if(value < 0) {
|
||||
printf("%s: mraa_i2c_read_byte_data() failed\n", __FUNCTION__);
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
*data = value;
|
||||
return UPM_SUCCESS;
|
||||
}
|
||||
|
||||
static upm_result_t bh1792_read_registers(bh1792_context dev, uint8_t reg,
|
||||
uint8_t *data, uint8_t len)
|
||||
{
|
||||
if(!dev)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
uint8_t value;
|
||||
|
||||
for(int i = 0; i < len; i++) {
|
||||
if(bh1792_read_register(dev, reg + i, &value) != UPM_SUCCESS) {
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
*(data + i) = value;
|
||||
}
|
||||
|
||||
return UPM_SUCCESS;
|
||||
}
|
||||
|
||||
static upm_result_t bh1792_write_register(bh1792_context dev, uint8_t value,
|
||||
uint8_t reg)
|
||||
{
|
||||
if(!dev)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
if (mraa_i2c_write_byte_data(dev->i2c, value, reg) != MRAA_SUCCESS) {
|
||||
printf("%s: mraa_i2c_write_byte_data() failed\n", __FUNCTION__);
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
return UPM_SUCCESS;
|
||||
}
|
||||
|
||||
static upm_result_t bh1792_set_bit_on(bh1792_context dev, uint8_t reg,
|
||||
uint8_t bit_mask)
|
||||
{
|
||||
if(!dev)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
uint8_t reg_value;
|
||||
int status;
|
||||
|
||||
status = bh1792_read_register(dev, reg, ®_value);
|
||||
if(status < 0) {
|
||||
printf("%s: Failed to read register 0x%2X\n", __FUNCTION__, reg);
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
reg_value |= bit_mask;
|
||||
return bh1792_write_register(dev, reg_value, reg);
|
||||
}
|
||||
|
||||
static upm_result_t bh1792_set_bit_off(bh1792_context dev, uint8_t reg,
|
||||
uint8_t bit_mask)
|
||||
{
|
||||
if(!dev)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
uint8_t reg_value;
|
||||
int status;
|
||||
|
||||
status = bh1792_read_register(dev, reg, ®_value);
|
||||
if(status < 0) {
|
||||
printf("%s: Failed to read register 0x%2X\n", __FUNCTION__, reg);
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
reg_value &= ~bit_mask;
|
||||
return bh1792_write_register(dev, reg_value, reg);
|
||||
}
|
||||
|
||||
static upm_result_t bh1792_set_bits_with_mask(bh1792_context dev, uint8_t reg,
|
||||
uint8_t value, uint8_t bit_mask)
|
||||
{
|
||||
if(!dev)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
uint8_t reg_value;
|
||||
int status;
|
||||
|
||||
status = bh1792_read_register(dev, reg, ®_value);
|
||||
if(status < 0) {
|
||||
printf("%s: Failed to read register 0x%2X\n", __FUNCTION__, reg);
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
reg_value &= ~bit_mask;
|
||||
reg_value |= value;
|
||||
return bh1792_write_register(dev, reg_value, reg);
|
||||
}
|
||||
|
||||
bh1792_context bh1792_init(int bus, int addr)
|
||||
{
|
||||
bh1792_context dev = (bh1792_context)malloc(sizeof(struct _bh1792_context));
|
||||
if (!dev)
|
||||
return NULL;
|
||||
|
||||
dev->i2c = NULL;
|
||||
dev->interrupt = NULL;
|
||||
|
||||
if (mraa_init() != MRAA_SUCCESS) {
|
||||
printf("%s: mraa_init() failed.\n", __FUNCTION__);
|
||||
bh1792_close(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(dev->i2c = mraa_i2c_init(bus))) {
|
||||
printf("%s: mraa_i2c_init() failed.\n", __FUNCTION__);
|
||||
bh1792_close(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (mraa_i2c_address(dev->i2c, addr)) {
|
||||
printf("%s: mraa_i2c_address() failed.\n", __FUNCTION__);
|
||||
bh1792_close(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(bh1792_check_who_am_i(dev) != UPM_SUCCESS)
|
||||
return NULL;
|
||||
|
||||
dev->enabled = false;
|
||||
dev->isrEnabled = false;
|
||||
dev->sync_thread_alive = false;
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
void bh1792_close(bh1792_context dev)
|
||||
{
|
||||
if(dev) {
|
||||
bh1792_stop_measurement(dev);
|
||||
if(dev->isrEnabled)
|
||||
bh1792_remove_isr(dev);
|
||||
|
||||
if (dev->i2c)
|
||||
mraa_i2c_stop(dev->i2c);
|
||||
|
||||
if(dev->sync_thread_alive) {
|
||||
dev->sync_thread_alive = false;
|
||||
pthread_join(dev->sync_thread, NULL);
|
||||
}
|
||||
|
||||
free(dev);
|
||||
}
|
||||
}
|
||||
|
||||
upm_result_t bh1792_check_who_am_i(bh1792_context dev)
|
||||
{
|
||||
if(!dev)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
uint8_t who_am_i;
|
||||
if(bh1792_read_register(dev, BH1792_MANUFACTURER_REG, &who_am_i) != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
if(who_am_i != BH1792_MANUFACTURER_REG_MANUFACTURER_ID) {
|
||||
printf("%s: wrong manufacturer ID\n", __FUNCTION__);
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
if(bh1792_read_register(dev, BH1792_PARTID_REG, &who_am_i) != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
if(who_am_i != BH1792_PARTID_REG_PART_ID) {
|
||||
printf("%s: wrong part ID\n", __FUNCTION__);
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
return UPM_SUCCESS;
|
||||
}
|
||||
|
||||
static upm_result_t bh1792_set_rdy_bit(bh1792_context dev)
|
||||
{
|
||||
return bh1792_set_bit_on(dev, BH1792_MEAS_CONTROL1, BH1792_MEAS_CONTROL1_RDY);
|
||||
}
|
||||
|
||||
bool bh1792_is_enabled(bh1792_context dev)
|
||||
{
|
||||
if(!dev)
|
||||
return false;
|
||||
|
||||
return dev->enabled;
|
||||
}
|
||||
|
||||
upm_result_t bh1792_soft_reset(bh1792_context dev)
|
||||
{
|
||||
return bh1792_set_bit_on(dev, BH1792_RESET, BH1792_RESET_SWRESET);
|
||||
}
|
||||
|
||||
static upm_result_t bh1792_select_led_type(bh1792_context dev, LED_TYPES led_type)
|
||||
{
|
||||
if(!dev)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
uint8_t status;
|
||||
|
||||
if(led_type == GREEN) {
|
||||
status = bh1792_set_bit_off(dev, BH1792_MEAS_CONTROL1,
|
||||
BH1792_MEAS_CONTROL1_SEL_ADC_MASK);
|
||||
if(status != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
} else {
|
||||
if(dev->op_mode == SYNCHRONIZED) {
|
||||
printf("%s: IR LED only for single & non-sync modes\n", __FUNCTION__);
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
status = bh1792_set_bit_on(dev, BH1792_MEAS_CONTROL1,
|
||||
BH1792_MEAS_CONTROL1_SEL_ADC_MASK);
|
||||
if(status != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
dev->led_type = led_type;
|
||||
|
||||
return UPM_SUCCESS;
|
||||
}
|
||||
|
||||
static upm_result_t bh1792_set_sync_meas_mode(bh1792_context dev, uint16_t meas_freq)
|
||||
{
|
||||
if(!dev)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
uint8_t status;
|
||||
|
||||
MEAS_MODES meas_mode;
|
||||
switch(meas_freq) {
|
||||
case 32:
|
||||
meas_mode = MSR_32Hz;
|
||||
break;
|
||||
case 64:
|
||||
meas_mode = MSR_64Hz;
|
||||
break;
|
||||
case 128:
|
||||
meas_mode = MSR_128Hz;
|
||||
break;
|
||||
case 256:
|
||||
meas_mode = MSR_256Hz;
|
||||
break;
|
||||
case 1024:
|
||||
meas_mode = MSR_1024Hz;
|
||||
break;
|
||||
default:
|
||||
return UPM_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
status = bh1792_set_bits_with_mask(dev, BH1792_MEAS_CONTROL1, meas_mode,
|
||||
BH1792_MEAS_CONTROL1_MSR_MASK);
|
||||
if(status != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
dev->meas_freq = meas_freq;
|
||||
|
||||
return UPM_SUCCESS;
|
||||
}
|
||||
|
||||
upm_result_t bh1792_get_meas_time_ms(bh1792_context dev, float *meas_time_ms)
|
||||
{
|
||||
if(!dev)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
uint8_t meas_time_reg;
|
||||
|
||||
if(bh1792_read_register(dev, BH1792_MEAS_CONTROL1, &meas_time_reg) != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
switch(meas_time_reg & BH1792_MEAS_CONTROL1_MSR_MASK) {
|
||||
case MSR_32Hz:
|
||||
*meas_time_ms = 1000 / (float)32;
|
||||
break;
|
||||
case MSR_64Hz:
|
||||
*meas_time_ms = 1000 / (float)64;
|
||||
break;
|
||||
case MSR_128Hz:
|
||||
*meas_time_ms = 1000 / (float)128;
|
||||
break;
|
||||
case MSR_256Hz:
|
||||
*meas_time_ms = 1000 / (float)256;
|
||||
break;
|
||||
case MSR_1024Hz:
|
||||
*meas_time_ms = 1000 / (float)1024;
|
||||
break;
|
||||
case MSR_SINGLE:
|
||||
case MSR_NON_SYNC:
|
||||
*meas_time_ms = 1000 / (float)4;
|
||||
break;
|
||||
default:
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
return UPM_SUCCESS;
|
||||
}
|
||||
|
||||
upm_result_t bh1792_set_green_leds_current(bh1792_context dev, uint8_t current)
|
||||
{
|
||||
if(!dev)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
if(current > LED_CURRENT_MAX)
|
||||
return UPM_ERROR_OUT_OF_RANGE;
|
||||
|
||||
uint8_t status;
|
||||
|
||||
status = bh1792_set_bits_with_mask(dev, BH1792_MEAS_CONTROL2,
|
||||
current & BH1792_MEAS_CONTROL2_LED_CURRENT1_MASK,
|
||||
BH1792_MEAS_CONTROL2_LED_CURRENT1_MASK);
|
||||
if(status != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
dev->green_current = current;
|
||||
|
||||
return UPM_SUCCESS;
|
||||
}
|
||||
|
||||
upm_result_t bh1792_get_green_leds_current(bh1792_context dev, uint8_t *current)
|
||||
{
|
||||
if(!dev)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
uint8_t data;
|
||||
|
||||
if(bh1792_read_register(dev, BH1792_MEAS_CONTROL2, &data) != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
*current = data & BH1792_MEAS_CONTROL2_LED_CURRENT1_MASK;
|
||||
return UPM_SUCCESS;
|
||||
}
|
||||
|
||||
upm_result_t bh1792_set_ir_led_current(bh1792_context dev, uint8_t current)
|
||||
{
|
||||
if(!dev)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
if(current > LED_CURRENT_MAX)
|
||||
return UPM_ERROR_OUT_OF_RANGE;
|
||||
|
||||
uint8_t status;
|
||||
|
||||
status = bh1792_set_bits_with_mask(dev, BH1792_MEAS_CONTROL3,
|
||||
current & BH1792_MEAS_CONTROL3_LED_CURRENT2_MASK,
|
||||
BH1792_MEAS_CONTROL3_LED_CURRENT2_MASK);
|
||||
if(status != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
dev->ir_current = current;
|
||||
|
||||
return UPM_SUCCESS;
|
||||
}
|
||||
|
||||
upm_result_t bh1792_get_ir_led_current(bh1792_context dev, uint8_t *current)
|
||||
{
|
||||
if(!dev)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
uint8_t data;
|
||||
|
||||
if(bh1792_read_register(dev, BH1792_MEAS_CONTROL3, &data) != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
*current = data & BH1792_MEAS_CONTROL3_LED_CURRENT2_MASK;
|
||||
return UPM_SUCCESS;
|
||||
}
|
||||
|
||||
upm_result_t bh1792_set_ir_threshold(bh1792_context dev, uint16_t threshold)
|
||||
{
|
||||
if(!dev)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
if(bh1792_write_register(dev, threshold, BH1792_MEAS_CONTROL4_L) != UPM_SUCCESS ||
|
||||
bh1792_write_register(dev, threshold >> 8, BH1792_MEAS_CONTROL4_H) != UPM_SUCCESS) {
|
||||
printf("%s: Failed to write high threshold\n", __FUNCTION__);
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
dev->threshold = threshold;
|
||||
|
||||
return UPM_SUCCESS;
|
||||
}
|
||||
|
||||
upm_result_t bh1792_get_ir_threshold(bh1792_context dev, uint16_t *threshold)
|
||||
{
|
||||
if(!dev)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
uint8_t data[2];
|
||||
|
||||
if(bh1792_read_register(dev, BH1792_MEAS_CONTROL4_H, &data[1]) != UPM_SUCCESS ||
|
||||
bh1792_read_register(dev, BH1792_MEAS_CONTROL4_L, &data[0]) != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
*threshold = data[1] << 8 | data[0];
|
||||
return UPM_SUCCESS;
|
||||
}
|
||||
|
||||
upm_result_t bh1792_get_fifo_size(bh1792_context dev, uint8_t *count)
|
||||
{
|
||||
if(!dev)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
uint8_t fifo_count;
|
||||
|
||||
if(bh1792_read_register(dev, BH1792_FIFO_LEV, &fifo_count) != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
*count = fifo_count & BH1792_FIFO_LEV_LEVEL_MASK;
|
||||
return UPM_SUCCESS;
|
||||
}
|
||||
|
||||
static upm_result_t bh1792_set_interrupt_mode(bh1792_context dev, INTERRUPT_MODES int_mode)
|
||||
{
|
||||
if(!dev)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
if(bh1792_set_bits_with_mask(dev, BH1792_MEAS_CONTROL5, int_mode,
|
||||
BH1792_MEAS_CONTROL5_INT_SEL_MASK) != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
dev->interrupt_mode = int_mode;
|
||||
|
||||
return UPM_SUCCESS;
|
||||
}
|
||||
|
||||
upm_result_t bh1792_disable_interrupt(bh1792_context dev)
|
||||
{
|
||||
return bh1792_set_bits_with_mask(dev, BH1792_MEAS_CONTROL5, 0,
|
||||
BH1792_MEAS_CONTROL5_INT_SEL_MASK);
|
||||
}
|
||||
|
||||
upm_result_t bh1792_clear_interrupt(bh1792_context dev)
|
||||
{
|
||||
uint8_t data;
|
||||
return bh1792_read_register(dev, BH1792_INT_CLEAR, &data);
|
||||
}
|
||||
|
||||
static void *bh1792_sync_measurement(void *args)
|
||||
{
|
||||
bh1792_context dev = (bh1792_context)args;
|
||||
|
||||
dev->sync_thread_alive = true;
|
||||
while(dev->sync_thread_alive) {
|
||||
bh1792_set_bit_on(dev, BH1792_MEAS_SYNC, BH1792_MEAS_SYNC_MEAS_SYNC);
|
||||
usleep(ONE_SEC_IN_MIRCO_SEC);
|
||||
}
|
||||
|
||||
return (void *)UPM_SUCCESS;
|
||||
}
|
||||
|
||||
upm_result_t bh1792_start_measurement(bh1792_context dev)
|
||||
{
|
||||
if(!dev)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
if(dev->op_mode == SYNCHRONIZED) {
|
||||
if(dev->sync_thread_alive) {
|
||||
dev->sync_thread_alive = false;
|
||||
pthread_join(dev->sync_thread, NULL);
|
||||
}
|
||||
pthread_create(&dev->sync_thread, NULL, &bh1792_sync_measurement, dev);
|
||||
}
|
||||
|
||||
if(bh1792_set_bit_on(dev, BH1792_MEAS_START, BH1792_MEAS_START_MEAS_ST) != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
dev->enabled = true;
|
||||
|
||||
return UPM_SUCCESS;
|
||||
}
|
||||
|
||||
upm_result_t bh1792_stop_measurement(bh1792_context dev)
|
||||
{
|
||||
if(!dev)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
if(bh1792_soft_reset(dev) != UPM_SUCCESS)
|
||||
return UPM_SUCCESS;
|
||||
|
||||
dev->enabled = false;
|
||||
|
||||
return UPM_SUCCESS;
|
||||
}
|
||||
|
||||
upm_result_t bh1792_restart_measurement(bh1792_context dev)
|
||||
{
|
||||
if(!dev)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
uint8_t status;
|
||||
|
||||
status = bh1792_stop_measurement(dev);
|
||||
if(status != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
if(status != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
switch(dev->op_mode) {
|
||||
case SYNCHRONIZED:
|
||||
status = bh1792_enable_sync_mode(dev, dev->meas_freq, dev->green_current);
|
||||
break;
|
||||
case NON_SYNCHRONIZED:
|
||||
status = bh1792_enable_non_sync_mode(dev, dev->ir_current, dev->threshold);
|
||||
break;
|
||||
case SINGLE_GREEN:
|
||||
status = bh1792_enable_single_mode(dev, GREEN, dev->green_current);
|
||||
break;
|
||||
case SINGLE_IR:
|
||||
status = bh1792_enable_single_mode(dev, IR, dev->ir_current);
|
||||
break;
|
||||
}
|
||||
|
||||
if(status != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
return bh1792_start_measurement(dev);
|
||||
}
|
||||
|
||||
upm_result_t bh1792_get_fifo_data(bh1792_context dev, uint16_t fifo_led_off[],
|
||||
uint16_t fifo_led_on[])
|
||||
{
|
||||
if(!dev)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
if(dev->op_mode != SYNCHRONIZED)
|
||||
return UPM_ERROR_NO_DATA;
|
||||
|
||||
uint8_t data[4];
|
||||
for(int i = 0; i < FIFO_WATERMARK; i++) {
|
||||
if(bh1792_read_registers(dev, BH1792_FIFO_DATA0_L, data, 4) != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
fifo_led_off[i] = data[1] << 8 | data[0];
|
||||
fifo_led_on[i] = data[3] << 8 | data[2];
|
||||
}
|
||||
|
||||
return UPM_SUCCESS;
|
||||
}
|
||||
|
||||
upm_result_t bh1792_discard_fifo_data(bh1792_context dev)
|
||||
{
|
||||
if(!dev)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
uint8_t data[4];
|
||||
|
||||
for(int i = 0; i < FIFO_WATERMARK; i++)
|
||||
bh1792_read_registers(dev, BH1792_FIFO_DATA0_L, data, 4);
|
||||
|
||||
return UPM_SUCCESS;
|
||||
}
|
||||
|
||||
upm_result_t bh1792_get_green_data(bh1792_context dev, uint16_t *green_led_off,
|
||||
uint16_t *green_led_on)
|
||||
{
|
||||
if(!dev)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
if(dev->op_mode == NON_SYNCHRONIZED || dev->op_mode == SINGLE_IR)
|
||||
return UPM_ERROR_NO_DATA;
|
||||
|
||||
uint8_t data[4];
|
||||
|
||||
if(bh1792_read_registers(dev, BH1792_DATAOUT_LEDOFF_L, data, 4) != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
*green_led_off = data[1] << 8 | data[0];
|
||||
*green_led_on = data[3] << 8 | data[2];
|
||||
|
||||
return UPM_SUCCESS;
|
||||
}
|
||||
|
||||
upm_result_t bh1792_get_ir_data(bh1792_context dev, uint16_t *ir_led_off,
|
||||
uint16_t *ir_led_on)
|
||||
{
|
||||
if(!dev)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
if(dev->op_mode != NON_SYNCHRONIZED && dev->op_mode != SINGLE_IR)
|
||||
return UPM_ERROR_NO_DATA;
|
||||
|
||||
uint8_t data[4];
|
||||
|
||||
if(bh1792_read_registers(dev, BH1792_IRDATA_LEDOFF_L, data, 4) != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
*ir_led_off = data[1] << 8 | data[0];
|
||||
*ir_led_on = data[3] << 8 | data[2];
|
||||
|
||||
return UPM_SUCCESS;
|
||||
}
|
||||
|
||||
upm_result_t bh1792_enable_sync_mode(bh1792_context dev, uint16_t meas_freq,
|
||||
uint8_t green_current)
|
||||
{
|
||||
if(!dev)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
uint8_t status;
|
||||
|
||||
if(bh1792_set_rdy_bit(dev) != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
if(bh1792_set_green_leds_current(dev, green_current) != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
if(bh1792_select_led_type(dev, GREEN) != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
status = bh1792_set_sync_meas_mode(dev, meas_freq);
|
||||
if(status != UPM_SUCCESS)
|
||||
return status;
|
||||
|
||||
dev->op_mode = SYNCHRONIZED;
|
||||
return bh1792_set_interrupt_mode(dev, WATER_MARK);
|
||||
}
|
||||
|
||||
upm_result_t bh1792_enable_non_sync_mode(bh1792_context dev, uint8_t ir_current,
|
||||
uint16_t threshold)
|
||||
{
|
||||
if(!dev)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
if(bh1792_set_rdy_bit(dev) != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
if(bh1792_set_ir_led_current(dev, ir_current) != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
if(bh1792_select_led_type(dev, IR) != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
if(bh1792_set_sync_meas_mode(dev, MSR_NON_SYNC) != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
dev->op_mode = NON_SYNCHRONIZED;
|
||||
return bh1792_set_interrupt_mode(dev, IR_THRESHOLD_JUDGE);
|
||||
}
|
||||
|
||||
upm_result_t bh1792_enable_single_mode(bh1792_context dev, LED_TYPES led_type,
|
||||
uint8_t current)
|
||||
{
|
||||
if(!dev)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
if(bh1792_set_rdy_bit(dev) != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
if(led_type == GREEN) {
|
||||
if(bh1792_set_green_leds_current(dev, current) != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
} else {
|
||||
if(bh1792_set_ir_led_current(dev, current) != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
if(bh1792_select_led_type(dev, led_type) != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
if(bh1792_set_sync_meas_mode(dev, MSR_SINGLE) != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
if(led_type == GREEN)
|
||||
dev->op_mode = SINGLE_GREEN;
|
||||
else
|
||||
dev->op_mode = SINGLE_IR;
|
||||
|
||||
return bh1792_set_interrupt_mode(dev, ON_COMPLETE);
|
||||
}
|
||||
|
||||
upm_result_t bh1792_install_isr(bh1792_context dev, mraa_gpio_edge_t edge,
|
||||
int pin, void (*isr)(void *), void *isr_args)
|
||||
{
|
||||
if(!dev)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
if(dev->isrEnabled)
|
||||
bh1792_remove_isr(dev);
|
||||
|
||||
mraa_gpio_context isr_gpio = NULL;
|
||||
|
||||
if (!(isr_gpio = mraa_gpio_init(pin))) {
|
||||
printf("%s: mraa_gpio_init() failed.\n", __FUNCTION__);
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
mraa_gpio_dir(isr_gpio, MRAA_GPIO_IN);
|
||||
|
||||
if (mraa_gpio_isr(isr_gpio, edge, isr, isr_args) != MRAA_SUCCESS) {
|
||||
mraa_gpio_close(isr_gpio);
|
||||
printf("%s: mraa_gpio_isr() failed.\n", __FUNCTION__);
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
}
|
||||
|
||||
dev->interrupt = isr_gpio;
|
||||
dev->isrEnabled = true;
|
||||
|
||||
return UPM_SUCCESS;
|
||||
}
|
||||
|
||||
upm_result_t bh1792_install_isr_falling_edge(bh1792_context dev, int pin,
|
||||
void (*isr)(void *), void *isr_args)
|
||||
{
|
||||
return bh1792_install_isr(dev, MRAA_GPIO_EDGE_FALLING, pin, isr, isr_args);
|
||||
}
|
||||
|
||||
void bh1792_remove_isr(bh1792_context dev)
|
||||
{
|
||||
if(dev) {
|
||||
mraa_gpio_isr_exit(dev->interrupt);
|
||||
mraa_gpio_close(dev->interrupt);
|
||||
dev->interrupt = NULL;
|
||||
dev->isrEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
upm_result_t bh1792_registers_dump(bh1792_context dev, char *dump)
|
||||
{
|
||||
if(!dev)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
|
||||
uint8_t reg_values[10];
|
||||
int count = 0;
|
||||
int len = 8;
|
||||
|
||||
if(bh1792_read_registers(dev, BH1792_MEAS_CONTROL1, reg_values, len) != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
count += sprintf(dump, "0x41 ");
|
||||
for(int i = 0; i < len; i++)
|
||||
count += sprintf(dump + count, "%02X ", reg_values[i]);
|
||||
sprintf(dump + count - 1, "\n");
|
||||
|
||||
len = 1;
|
||||
if(bh1792_read_registers(dev, BH1792_FIFO_LEV, reg_values, len) != UPM_SUCCESS)
|
||||
return UPM_ERROR_OPERATION_FAILED;
|
||||
count += sprintf(dump + count, "0x4B ");
|
||||
for(int i = 0; i < len; i++)
|
||||
count += sprintf(dump + count, "%02X ", reg_values[i]);
|
||||
|
||||
return UPM_SUCCESS;
|
||||
}
|
305
src/bh1792/bh1792.cxx
Executable file
305
src/bh1792/bh1792.cxx
Executable file
@ -0,0 +1,305 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Author: Assam Boudjelthia
|
||||
* Copyright (c) 2018 Rohm Semiconductor.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include "bh1792.hpp"
|
||||
|
||||
using namespace upm;
|
||||
|
||||
BH1792::BH1792(int bus, int addr) : m_bh1792(bh1792_init(bus, addr))
|
||||
{
|
||||
if(!m_bh1792)
|
||||
throw std::runtime_error(std::string(__FUNCTION__) +
|
||||
"bh1792_init() failed");
|
||||
}
|
||||
|
||||
BH1792::~BH1792()
|
||||
{
|
||||
bh1792_close(m_bh1792);
|
||||
}
|
||||
|
||||
void BH1792::CheckWhoAmI()
|
||||
{
|
||||
if(bh1792_check_who_am_i(m_bh1792) != UPM_SUCCESS)
|
||||
throw std::runtime_error(std::string(__FUNCTION__) +
|
||||
"bh1792_check_who_am_i() failed");
|
||||
}
|
||||
|
||||
bool BH1792::IsEnabled()
|
||||
{
|
||||
return bh1792_is_enabled(m_bh1792);
|
||||
}
|
||||
|
||||
void BH1792::SoftReset()
|
||||
{
|
||||
if(bh1792_soft_reset(m_bh1792) != UPM_SUCCESS)
|
||||
throw std::runtime_error(std::string(__FUNCTION__) +
|
||||
"bh1792_soft_reset() failed");
|
||||
}
|
||||
|
||||
float BH1792::GetMeasurementTimeMS()
|
||||
{
|
||||
float meas_time;
|
||||
|
||||
if(bh1792_get_meas_time_ms(m_bh1792, &meas_time) != UPM_SUCCESS)
|
||||
throw std::runtime_error(std::string(__FUNCTION__) +
|
||||
"bh1792_get_meas_time_ms() failed");
|
||||
|
||||
return meas_time;
|
||||
}
|
||||
|
||||
void BH1792::SetGreenLedsCurrent(uint16_t current)
|
||||
{
|
||||
uint8_t status;
|
||||
|
||||
status = bh1792_set_green_leds_current(m_bh1792, current);
|
||||
if(status == UPM_ERROR_OUT_OF_RANGE) {
|
||||
throw std::range_error(std::string(__FUNCTION__) +
|
||||
"bh1792_set_green_leds_current() failed, current not in range");
|
||||
} else if(status != UPM_SUCCESS) {
|
||||
throw std::runtime_error(std::string(__FUNCTION__) +
|
||||
"bh1792_set_green_leds_current() failed");
|
||||
}
|
||||
}
|
||||
|
||||
int BH1792::GetGreenLedsCurrent()
|
||||
{
|
||||
uint8_t current;
|
||||
|
||||
if(bh1792_get_green_leds_current(m_bh1792, ¤t) != UPM_SUCCESS)
|
||||
throw std::runtime_error(std::string(__FUNCTION__) +
|
||||
"bh1792_get_green_leds_current() failed");
|
||||
|
||||
return (int)current;
|
||||
}
|
||||
|
||||
void BH1792::SetIrLedCurrent(uint16_t current)
|
||||
{
|
||||
uint8_t status;
|
||||
|
||||
status = bh1792_set_ir_led_current(m_bh1792, current);
|
||||
if(status == UPM_ERROR_OUT_OF_RANGE) {
|
||||
throw std::range_error(std::string(__FUNCTION__) +
|
||||
"bh1792_set_ir_led_current() failed, current not in range");
|
||||
} else if(status != UPM_SUCCESS) {
|
||||
throw std::runtime_error(std::string(__FUNCTION__) +
|
||||
"bh1792_set_ir_led_current() failed");
|
||||
}
|
||||
}
|
||||
|
||||
int BH1792::GetIrLedCurrent()
|
||||
{
|
||||
uint8_t current;
|
||||
|
||||
if(bh1792_get_ir_led_current(m_bh1792, ¤t) != UPM_SUCCESS)
|
||||
throw std::runtime_error(std::string(__FUNCTION__) +
|
||||
"bh1792_get_ir_led_current() failed");
|
||||
|
||||
return (int)current;
|
||||
}
|
||||
|
||||
void BH1792::SetIrThreshold(uint16_t threshold)
|
||||
{
|
||||
if(bh1792_set_ir_threshold(m_bh1792, threshold) != UPM_SUCCESS)
|
||||
throw std::runtime_error(std::string(__FUNCTION__) +
|
||||
"bh1792_set_ir_threshold() failed");
|
||||
}
|
||||
|
||||
int BH1792::GetIrThreshold()
|
||||
{
|
||||
uint16_t threshold;
|
||||
|
||||
if(bh1792_get_ir_threshold(m_bh1792, &threshold) != UPM_SUCCESS)
|
||||
throw std::runtime_error(std::string(__FUNCTION__) +
|
||||
"bh1792_get_ir_threshold() failed");
|
||||
|
||||
return (int)threshold;
|
||||
}
|
||||
|
||||
int BH1792::GetFifoSize()
|
||||
{
|
||||
uint8_t size;
|
||||
|
||||
if(bh1792_get_fifo_size(m_bh1792, &size) != UPM_SUCCESS)
|
||||
throw std::runtime_error(std::string(__FUNCTION__) +
|
||||
"bh1792_get_fifo_size() failed");
|
||||
|
||||
return (int)size;
|
||||
}
|
||||
|
||||
void BH1792::DisableInterrupt()
|
||||
{
|
||||
if(bh1792_disable_interrupt(m_bh1792) != UPM_SUCCESS)
|
||||
throw std::runtime_error(std::string(__FUNCTION__) +
|
||||
"bh1792_disable_interrupt() failed");
|
||||
}
|
||||
|
||||
void BH1792::ClearInterrupt()
|
||||
{
|
||||
if(bh1792_clear_interrupt(m_bh1792) != UPM_SUCCESS)
|
||||
throw std::runtime_error(std::string(__FUNCTION__) +
|
||||
"bh1792_clear_interrupt() failed");
|
||||
}
|
||||
|
||||
void BH1792::StartMeasurement()
|
||||
{
|
||||
if(bh1792_start_measurement(m_bh1792) != UPM_SUCCESS)
|
||||
throw std::runtime_error(std::string(__FUNCTION__) +
|
||||
"bh1792_start_measurement() failed");
|
||||
}
|
||||
|
||||
void BH1792::StopMeasurement()
|
||||
{
|
||||
if(bh1792_stop_measurement(m_bh1792) != UPM_SUCCESS)
|
||||
throw std::runtime_error(std::string(__FUNCTION__) +
|
||||
"bh1792_stop_measurement() failed");
|
||||
}
|
||||
|
||||
void BH1792::RestartMeasurement()
|
||||
{
|
||||
if(bh1792_restart_measurement(m_bh1792) != UPM_SUCCESS)
|
||||
throw std::runtime_error(std::string(__FUNCTION__) +
|
||||
"bh1792_restart_measurement() failed");
|
||||
}
|
||||
|
||||
std::vector<std::vector<int>> BH1792::GetFifoData()
|
||||
{
|
||||
uint16_t fifo_off[FIFO_WATERMARK], fifo_on[FIFO_WATERMARK];
|
||||
|
||||
if(bh1792_get_fifo_data(m_bh1792, fifo_off, fifo_on) != UPM_SUCCESS)
|
||||
throw std::runtime_error(std::string(__FUNCTION__) +
|
||||
"bh1792_get_fifo_data() failed");
|
||||
|
||||
std::vector<int> item;
|
||||
std::vector<std::vector<int>> result;
|
||||
item.reserve(2);
|
||||
result.reserve(FIFO_WATERMARK);
|
||||
for(int i = 0; i < FIFO_WATERMARK; i++) {
|
||||
item.clear();
|
||||
item.push_back(fifo_off[i]);
|
||||
item.push_back(fifo_on[i]);
|
||||
result.push_back(item);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void BH1792::DiscardFifoData()
|
||||
{
|
||||
if(bh1792_discard_fifo_data(m_bh1792) != UPM_SUCCESS)
|
||||
throw std::runtime_error(std::string(__FUNCTION__) +
|
||||
"bh1792_discard_fifo_data() failed");
|
||||
}
|
||||
|
||||
std::vector<int> BH1792::GetGreenData()
|
||||
{
|
||||
uint16_t green_off, green_on;
|
||||
|
||||
if(bh1792_get_green_data(m_bh1792, &green_off, &green_on) != UPM_SUCCESS)
|
||||
throw std::runtime_error(std::string(__FUNCTION__) +
|
||||
"bh1792_get_green_data() failed");
|
||||
|
||||
std::vector<int> result;
|
||||
result.reserve(2);
|
||||
result.push_back(green_off);
|
||||
result.push_back(green_on);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<int> BH1792::GetIrData()
|
||||
{
|
||||
uint16_t ir_off, ir_on;
|
||||
|
||||
if(bh1792_get_ir_data(m_bh1792, &ir_off, &ir_on) != UPM_SUCCESS)
|
||||
throw std::runtime_error(std::string(__FUNCTION__) +
|
||||
"bh1792_get_ir_data() failed");
|
||||
|
||||
std::vector<int> result;
|
||||
result.reserve(2);
|
||||
result.push_back(ir_off);
|
||||
result.push_back(ir_on);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void BH1792::EnableSyncMode(uint16_t measFreq, uint16_t green_current)
|
||||
{
|
||||
uint8_t status;
|
||||
|
||||
status = bh1792_enable_sync_mode(m_bh1792, measFreq, green_current);
|
||||
if(status == UPM_ERROR_INVALID_PARAMETER) {
|
||||
throw std::invalid_argument(std::string(__FUNCTION__) +
|
||||
"bh1792_enable_sync_mode() failed, invalid measurement frequncy");
|
||||
} else if(status != UPM_SUCCESS) {
|
||||
throw std::runtime_error(std::string(__FUNCTION__) +
|
||||
"bh1792_enable_sync_mode() failed");
|
||||
}
|
||||
}
|
||||
|
||||
void BH1792::EnableNonSyncMode(uint16_t ir_current, uint16_t threshold)
|
||||
{
|
||||
if(bh1792_enable_non_sync_mode(m_bh1792, ir_current, threshold) != UPM_SUCCESS)
|
||||
throw std::runtime_error(std::string(__FUNCTION__) +
|
||||
"bh1792_enable_non_sync_mode() failed");
|
||||
}
|
||||
|
||||
void BH1792::EnableSingleMode(LED_TYPES led_type, uint16_t current)
|
||||
{
|
||||
if(bh1792_enable_single_mode(m_bh1792, led_type, current) != UPM_SUCCESS)
|
||||
throw std::runtime_error(std::string(__FUNCTION__) +
|
||||
"bh1792_enable_single_mode() failed");
|
||||
}
|
||||
|
||||
void BH1792::InstallISR(mraa_gpio_edge_t edge, int pin, void (*isr)(void *), void *isr_args)
|
||||
{
|
||||
if(bh1792_install_isr(m_bh1792, edge, pin, isr, isr_args) != UPM_SUCCESS)
|
||||
throw std::runtime_error(std::string(__FUNCTION__) +
|
||||
"bh1792_install_isr() failed");
|
||||
}
|
||||
|
||||
void BH1792::InstallISR(int pin, void (*isr)(void *), void *isr_args)
|
||||
{
|
||||
if(bh1792_install_isr_falling_edge(m_bh1792, pin, isr, isr_args) != UPM_SUCCESS)
|
||||
throw std::runtime_error(std::string(__FUNCTION__) +
|
||||
"bh1792_install_isr_falling_edge() failed");
|
||||
}
|
||||
|
||||
void BH1792::RemoveISR()
|
||||
{
|
||||
bh1792_remove_isr(m_bh1792);
|
||||
}
|
||||
|
||||
std::string BH1792::RegistersDump()
|
||||
{
|
||||
char dump[255];
|
||||
std::string dumpStr;
|
||||
|
||||
if(bh1792_registers_dump(m_bh1792, dump) != UPM_SUCCESS)
|
||||
throw std::runtime_error(std::string(__FUNCTION__) +
|
||||
"bh1792_registers_dump() failed");
|
||||
dumpStr = dump;
|
||||
return dumpStr;
|
||||
}
|
419
src/bh1792/bh1792.h
Executable file
419
src/bh1792/bh1792.h
Executable file
@ -0,0 +1,419 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Author: Assam Boudjelthia
|
||||
* Copyright (c) 2018 Rohm Semiconductor.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <mraa/i2c.h>
|
||||
#include <mraa/gpio.h>
|
||||
#include <unistd.h>
|
||||
#include <upm_types.h>
|
||||
#include <pthread.h>
|
||||
#include "bh1792glc_registers.h"
|
||||
|
||||
/**
|
||||
* @brief C API for the bh1792 Heart Rate sensor driver
|
||||
* @defgroup bh1792 libupm-bh1792
|
||||
* @ingroup ROHM i2c medical
|
||||
*/
|
||||
/**
|
||||
* @library bh1792
|
||||
* @sensor bh1792
|
||||
* @comname Heart Rate Sensor
|
||||
* @type medical
|
||||
* @man ROHM
|
||||
* @con i2c
|
||||
*
|
||||
* @brief C API for the bh1792 Heart Rate sensor driver
|
||||
*/
|
||||
|
||||
#define ONE_SEC_IN_MIRCO_SEC 1000000
|
||||
#define FIFO_WATERMARK 32
|
||||
#define LED_CURRENT_MAX 63
|
||||
|
||||
/**
|
||||
* @brief Measurement modes, for synchronized time modes, non synchronized
|
||||
* and single modes.
|
||||
*/
|
||||
typedef enum {
|
||||
MSR_64Hz = BH1792_MEAS_CONTROL1_MSR_64HZ,
|
||||
MSR_32Hz = BH1792_MEAS_CONTROL1_MSR_32HZ,
|
||||
MSR_128Hz = BH1792_MEAS_CONTROL1_MSR_128HZ,
|
||||
MSR_256Hz = BH1792_MEAS_CONTROL1_MSR_256HZ,
|
||||
MSR_1024Hz = BH1792_MEAS_CONTROL1_MSR_1024HZ,
|
||||
MSR_NON_SYNC = BH1792_MEAS_CONTROL1_MSR_NON_SYNCH_MODE,
|
||||
MSR_SINGLE = BH1792_MEAS_CONTROL1_MSR_SINGLE_MEAS_MODE
|
||||
} MEAS_MODES;
|
||||
|
||||
/**
|
||||
* @brief LED light types
|
||||
*/
|
||||
typedef enum {
|
||||
GREEN,
|
||||
IR
|
||||
} LED_TYPES;
|
||||
|
||||
/**
|
||||
* @brief Interrupt modes of the sensor
|
||||
*/
|
||||
typedef enum {
|
||||
WATER_MARK = BH1792_MEAS_CONTROL5_INT_SEL_FIFO_WATERMARK,
|
||||
IR_THRESHOLD_JUDGE = BH1792_MEAS_CONTROL5_INT_SEL_IR_THRESHOLD,
|
||||
ON_COMPLETE = BH1792_MEAS_CONTROL5_INT_SEL_ON_COMPLETE
|
||||
} INTERRUPT_MODES;
|
||||
|
||||
/**
|
||||
* @brief Operations modes available with the sensor
|
||||
*/
|
||||
typedef enum {
|
||||
SYNCHRONIZED,
|
||||
NON_SYNCHRONIZED,
|
||||
SINGLE_GREEN,
|
||||
SINGLE_IR
|
||||
} OP_MODES;
|
||||
|
||||
/**
|
||||
* @brief bh1792 sensor context
|
||||
*/
|
||||
typedef struct _bh1792_context
|
||||
{
|
||||
mraa_i2c_context i2c;
|
||||
mraa_gpio_context interrupt;
|
||||
bool enabled;
|
||||
bool isrEnabled;
|
||||
OP_MODES op_mode;
|
||||
pthread_t sync_thread;
|
||||
bool sync_thread_alive;
|
||||
LED_TYPES led_type;
|
||||
INTERRUPT_MODES interrupt_mode;
|
||||
uint16_t meas_freq;
|
||||
uint8_t green_current;
|
||||
uint8_t ir_current;
|
||||
uint16_t threshold;
|
||||
} *bh1792_context;
|
||||
|
||||
/**
|
||||
* @brief Init the sensor with specific bus and address. Before starting
|
||||
* measurement, one of (bh1792_enable_sync_mode, bh1792_enable_non_sync_mode,
|
||||
* or bh1792_enable_single_mode) have to be called.
|
||||
*
|
||||
* @param bus I2C bus number
|
||||
* @param addr I2C sensor address
|
||||
* @return context of initialized sensor
|
||||
*/
|
||||
bh1792_context bh1792_init(int bus, int addr);
|
||||
|
||||
/**
|
||||
* @brief Close and free sensor context
|
||||
*
|
||||
* @param dev Sensor context
|
||||
*/
|
||||
void bh1792_close(bh1792_context dev);
|
||||
|
||||
/**
|
||||
* @brief Check "who am I" register value to identify the sensor
|
||||
*
|
||||
* @param dev Sensor context
|
||||
* @return UPM result
|
||||
*/
|
||||
upm_result_t bh1792_check_who_am_i(bh1792_context dev);
|
||||
|
||||
/**
|
||||
* @brief Checks if the measuremnt on sensor is enabled
|
||||
*
|
||||
* @param The sensor context
|
||||
* @return True if measurement is enabled, or false otherwise
|
||||
*/
|
||||
bool bh1792_is_enabled(bh1792_context dev);
|
||||
|
||||
/**
|
||||
* @brief Initiates a software reset to the sensor. All register values will
|
||||
* be written to their defaults, thus intended operation mode need to be
|
||||
* enabled.
|
||||
*
|
||||
* @param dev Sensor context
|
||||
* @return UPM result
|
||||
*/
|
||||
upm_result_t bh1792_soft_reset(bh1792_context dev);
|
||||
|
||||
/**
|
||||
* @brief Gets the value of measurement time is milli-seconds
|
||||
*
|
||||
* @param dev The sensor context
|
||||
* @param meas_time_ms Float pointer to store value of measurement time
|
||||
* @return UPM result
|
||||
*/
|
||||
upm_result_t bh1792_get_meas_time_ms(bh1792_context dev, float *meas_time);
|
||||
|
||||
/**
|
||||
* @brief Sets the green LED Current value
|
||||
*
|
||||
* @param dev The sensor context
|
||||
* @param current The current value, accepted values are between 0-63
|
||||
* @return UPM result
|
||||
*/
|
||||
upm_result_t bh1792_set_green_leds_current(bh1792_context dev, uint8_t current);
|
||||
|
||||
/**
|
||||
* @brief Gets the green LED current value
|
||||
*
|
||||
* @param dev The sensor context
|
||||
* @param current Pointer to store the read current value
|
||||
* @return UPM result
|
||||
*/
|
||||
upm_result_t bh1792_get_green_leds_current(bh1792_context dev, uint8_t *current);
|
||||
|
||||
/**
|
||||
* @brief Sets the IR LED Current value
|
||||
*
|
||||
* @param dev The sensor context
|
||||
* @param current The current value, accepted values are between 0-63
|
||||
* @return UPM result
|
||||
*/
|
||||
upm_result_t bh1792_set_ir_led_current(bh1792_context dev, uint8_t current);
|
||||
|
||||
/**
|
||||
* @brief Gets the IR LED current value
|
||||
*
|
||||
* @param dev The sensor context
|
||||
* @param current Pointer to store the read current value
|
||||
* @return UPM result
|
||||
*/
|
||||
upm_result_t bh1792_get_ir_led_current(bh1792_context dev, uint8_t *current);
|
||||
|
||||
/**
|
||||
* @brief Sets interrupt ir threshold value for non-synchronized mode
|
||||
*
|
||||
* @param dev Sensor context
|
||||
* @param threshold Value to be written, range 0-65536
|
||||
* @return UPM result
|
||||
*/
|
||||
upm_result_t bh1792_set_ir_threshold(bh1792_context dev, uint16_t threshold);
|
||||
|
||||
/**
|
||||
* @brief Gets interrupt ir threshold value
|
||||
*
|
||||
* @param dev Sensor context
|
||||
* @param threshold Pointer (uint16_t) to write value
|
||||
* @return UPM result
|
||||
*/
|
||||
upm_result_t bh1792_get_ir_threshold(bh1792_context dev, uint16_t *threshold);
|
||||
|
||||
/**
|
||||
* @brief Gets the current size of built-in FIFO
|
||||
*
|
||||
* @param dev The sensor context
|
||||
* @param count The pointer to store the size
|
||||
* @return UPM result
|
||||
*/
|
||||
upm_result_t bh1792_get_fifo_size(bh1792_context dev, uint8_t *count);
|
||||
|
||||
/**
|
||||
* @brief Disables interrupt function. Interrupt is enabled by default on all
|
||||
* operation modes, so this have to be called after enabling a specific
|
||||
* operation mode
|
||||
*
|
||||
* @param dev The sensor context
|
||||
* @return UPM result
|
||||
*/
|
||||
upm_result_t bh1792_disable_interrupt(bh1792_context dev);
|
||||
|
||||
/**
|
||||
* @brief Clears the interrupt flag allowing more interrupts to be raised
|
||||
*
|
||||
* @param dev The sensor context
|
||||
* @return UPM result
|
||||
*/
|
||||
upm_result_t bh1792_clear_interrupt(bh1792_context dev);
|
||||
|
||||
/**
|
||||
* @brief Starts the measuremnt on sensor or enable the sensor
|
||||
*
|
||||
* @param dev The sensor context
|
||||
* @return UPM result
|
||||
*/
|
||||
upm_result_t bh1792_start_measurement(bh1792_context dev);
|
||||
|
||||
/**
|
||||
* @breif Stops the measurement by setting the software reset bit. This
|
||||
* function will reset all config registers. To resume from previous
|
||||
* configuration call bh1792_restart_measurement().
|
||||
*
|
||||
* @param dev The sensor context
|
||||
* @return UPM result
|
||||
*/
|
||||
upm_result_t bh1792_stop_measurement(bh1792_context dev);
|
||||
|
||||
/**
|
||||
* @brief Restart the measurement, This function stops measurement, then
|
||||
* re-writes the configuration registers again and start measurement with same
|
||||
* configuration.
|
||||
*
|
||||
* @param dev The sensor context
|
||||
* @return UPM result
|
||||
*/
|
||||
upm_result_t bh1792_restart_measurement(bh1792_context dev);
|
||||
|
||||
/**
|
||||
* @brief Gets the fifo data of 32 entries and resets the WATERMARK interrupt
|
||||
* flag.
|
||||
*
|
||||
* @param dev The sensor context
|
||||
* @param fifo_led_off Array/Pointer to store 32 entries of fifo LED_OFF data
|
||||
* @param fifo_led_on Array/Pointer to store 32 entries of fifo LED_ON data
|
||||
* @return UPM result
|
||||
*/
|
||||
upm_result_t bh1792_get_fifo_data(bh1792_context dev, uint16_t fifo_led_off[],
|
||||
uint16_t fifo_led_on[]);
|
||||
|
||||
/**
|
||||
* @brief Reads and discard the 32 FIFO entries to reset the WATERMARK
|
||||
* interrupt flag.
|
||||
*
|
||||
* @param dev The sensor context
|
||||
* @return UPM result
|
||||
*/
|
||||
upm_result_t bh1792_discard_fifo_data(bh1792_context dev);
|
||||
|
||||
/**
|
||||
* @brief Gets the values from using green LED light
|
||||
*
|
||||
* @param dev The sensor context
|
||||
* @param green_led_off Pointer to store the reading value of LED_OFF
|
||||
* @param green_led_on Pointer to store the reading value of LED_ON
|
||||
* @return UPM result
|
||||
*/
|
||||
upm_result_t bh1792_get_green_data(bh1792_context dev, uint16_t *green_led_off,
|
||||
uint16_t *green_led_on);
|
||||
|
||||
/**
|
||||
* @brief Gets the values from using IR LED light
|
||||
*
|
||||
* @param dev The sensor context
|
||||
* @param ir_led_off Pointer to store the reading value of LED_OFF
|
||||
* @param ir_led_on Pointer to store the reading value of LED_ON
|
||||
* @return UPM result
|
||||
*/
|
||||
upm_result_t bh1792_get_ir_data(bh1792_context dev, uint16_t *ir_led_off,
|
||||
uint16_t *ir_led_on);
|
||||
|
||||
/**
|
||||
* @brief Enables and configures the sensor to use synchronized mode. This will
|
||||
* use the built-in FIFO and raises a WATERMARK interrupt when FIFO size
|
||||
* reaches 32 entries. To clear that interrupt flag FIFO must be read or
|
||||
* discarded. This mode uses only green LED.
|
||||
*
|
||||
* You need to call bh1792_start_measurement() after this.
|
||||
*
|
||||
* @param dev The sensor context
|
||||
* @param meas_freq Measurement frequncy mode, valid values 32, 64, 128, 256,
|
||||
* 1024
|
||||
* @param green_current Green LED current value
|
||||
* @return UPM result
|
||||
*/
|
||||
upm_result_t bh1792_enable_sync_mode(bh1792_context dev, uint16_t meas_freq,
|
||||
uint8_t green_current);
|
||||
|
||||
/**
|
||||
* @brief Enabled and configures the sensor to use non-synchronized mode. This
|
||||
* mode uses IR_THRESHOLD interrupt, it will raise an interrupt if IR LED ON
|
||||
* value is equal or greater than the threshold value. Interrupt must be
|
||||
* cleared before receiving new interrupts. This mode uses only IR LED.
|
||||
*
|
||||
* You need to call bh1792_start_measurement() after this.
|
||||
*
|
||||
* @param dev The sensor context
|
||||
* @param ir_current The IR LED current value
|
||||
* @param threshold The IR LED interrupt threshold value
|
||||
* @return UPM result
|
||||
*/
|
||||
upm_result_t bh1792_enable_non_sync_mode(bh1792_context dev, uint8_t ir_current,
|
||||
uint16_t threshold);
|
||||
|
||||
/**
|
||||
* @brief Enables and configures the sensor to use single mode. This sets the
|
||||
* sensor to take only one measurement and raise an interrupt after measurement
|
||||
* is finished. Interrupt flags has to be cleared to recieved new interrupts.
|
||||
* This mode uses both green and IR LEDs.
|
||||
*
|
||||
* You need to call bh1792_start_measurement() after this. If you need to get
|
||||
* continuous values, clear interrupt and bh1792_start_measurement()
|
||||
* continuously.
|
||||
*
|
||||
* @param dev The sensor context
|
||||
* @param led_type LED light type to use, takes GREEN or IR values
|
||||
* @param current The chosen led_type current value
|
||||
* @return UPM result
|
||||
*/
|
||||
upm_result_t bh1792_enable_single_mode(bh1792_context dev, LED_TYPES led_type,
|
||||
uint8_t current);
|
||||
|
||||
/**
|
||||
* @brief Installs the ISR to a given GPIO pin
|
||||
*
|
||||
* @param dev Sensor context
|
||||
* @param edge Edge type to raise ISR with, of type mraa_gpio_edge_t
|
||||
* @param pin GPIO pin number
|
||||
* @param isr Pointer to ISR function
|
||||
* @param isr_args Arguments to pass the ISR function
|
||||
* @return UPM result
|
||||
*/
|
||||
upm_result_t bh1792_install_isr(bh1792_context dev, mraa_gpio_edge_t edge,
|
||||
int pin, void (*isr)(void *), void *isr_args);
|
||||
|
||||
/**
|
||||
* @brief Installs the ISR to a given GPIO pin
|
||||
*
|
||||
* @param dev Sensor context
|
||||
* @param pin GPIO pin number
|
||||
* @param isr Pointer to ISR function
|
||||
* @param isr_args Arguments to pass the ISR function
|
||||
* @return UPM result
|
||||
*/
|
||||
upm_result_t bh1792_install_isr_falling_edge(bh1792_context dev, int pin,
|
||||
void (*isr)(void *), void *isr_args);
|
||||
|
||||
/**
|
||||
* @brief Removes the ISR if it is installed
|
||||
*
|
||||
* @param dev Sensor context
|
||||
*/
|
||||
void bh1792_remove_isr(bh1792_context dev);
|
||||
|
||||
/**
|
||||
* @brief Gets a dump of configuration registers as a string
|
||||
*
|
||||
* @param dev Sensor context
|
||||
* @param dump Pointer of char to save dump string
|
||||
* @return UPM result
|
||||
*/
|
||||
upm_result_t bh1792_registers_dump(bh1792_context dev, char *dump);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
322
src/bh1792/bh1792.hpp
Executable file
322
src/bh1792/bh1792.hpp
Executable file
@ -0,0 +1,322 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Author: Assam Boudjelthia
|
||||
* Copyright (c) 2018 Rohm Semiconductor.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "bh1792.h"
|
||||
|
||||
/**
|
||||
* @brief C++ API for the bh1792 Heart Rate sensor driver
|
||||
* @defgroup bh1792 libupm-bh1792
|
||||
* @ingroup ROHM i2c medical
|
||||
*/
|
||||
/**
|
||||
* @library bh1792
|
||||
* @sensor bh1792
|
||||
* @comname Heart Rate Sensor
|
||||
* @type medical
|
||||
* @man ROHM
|
||||
* @con i2c
|
||||
*
|
||||
* @brief C++ API for the bh1792 driver
|
||||
*/
|
||||
|
||||
namespace upm {
|
||||
class BH1792 {
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Init the sensor with specific bus and address. Before
|
||||
* starting measurement, one of (EnableSyncMode, EnableNonSyncMode,
|
||||
* or EnableSingleMode) has to be called.
|
||||
*
|
||||
* @param bus I2C bus number
|
||||
* @param addr I2C sensor address
|
||||
* @throws std::runtime_error on initialization failure
|
||||
*/
|
||||
BH1792(int bus = 0, int addr = 0x5b);
|
||||
|
||||
/**
|
||||
* @brief Close and free sensor
|
||||
*/
|
||||
virtual ~BH1792();
|
||||
|
||||
/**
|
||||
* @brief Check "who am I" register value to identify the sensor
|
||||
*
|
||||
* @throws std::runtime_error if this value is incorrect
|
||||
*/
|
||||
void CheckWhoAmI();
|
||||
|
||||
/**
|
||||
* @brief Checks if the measuremnt on sensor is enabled
|
||||
*
|
||||
* @return True if measurement is enabled, or false otherwise
|
||||
*/
|
||||
bool IsEnabled();
|
||||
|
||||
/**
|
||||
* @brief Initiates a software reset to the sensor. All register values
|
||||
* will be written to their defaults, thus intended operation mode need
|
||||
* to be enabled.
|
||||
*
|
||||
* @throws std::runtime_error if software reset fails
|
||||
*/
|
||||
void SoftReset();
|
||||
|
||||
/**
|
||||
* @brief Gets the value of measurement time is milli-seconds
|
||||
*
|
||||
* @return measurement time float in milli-seconds
|
||||
* @throws std::runtime_error if reading measurement time fails
|
||||
*/
|
||||
float GetMeasurementTimeMS();
|
||||
|
||||
/**
|
||||
* @brief Sets the green LED Current value
|
||||
*
|
||||
* @param current The current value, accepted values are between 0-63
|
||||
* @throws std::runtime_error if setting current fails
|
||||
* @throws std::range_error if current value out of range
|
||||
*/
|
||||
void SetGreenLedsCurrent(uint16_t current);
|
||||
|
||||
/**
|
||||
* @brief Gets the green LED current value
|
||||
*
|
||||
* @return Green LED used current
|
||||
* @throws std::runtime_error if reading current fails
|
||||
*/
|
||||
int GetGreenLedsCurrent();
|
||||
|
||||
/**
|
||||
* @brief Sets the IR LED Current value
|
||||
*
|
||||
* @param current The current value, accepted values are between 0-63
|
||||
* @throws std::runtime_error if setting current fails
|
||||
* @throws std::range_error if current value out of range
|
||||
*/
|
||||
void SetIrLedCurrent(uint16_t current);
|
||||
|
||||
/**
|
||||
* @brief Gets the green LED current value
|
||||
*
|
||||
* @return Green LED used current
|
||||
* @throws std::runtime_error if reading current fails
|
||||
*/
|
||||
int GetIrLedCurrent();
|
||||
|
||||
/**
|
||||
* @brief Sets interrupt IR threshold value for non-synchronized mode
|
||||
*
|
||||
* @param threshold Value to be written, range 0-65536
|
||||
* @throws std::runtime_error if setting threshold fails
|
||||
*/
|
||||
void SetIrThreshold(uint16_t threshold);
|
||||
|
||||
/**
|
||||
* @brief Gets interrupt IR threshold value
|
||||
*
|
||||
* @return Green LED used current
|
||||
* @throws std::runtime_error if reading current fails
|
||||
*/
|
||||
int GetIrThreshold();
|
||||
|
||||
/**
|
||||
* @brief Gets the current size of built-in FIFO
|
||||
*
|
||||
* @return Number of entries store in FIFO
|
||||
* @throws std::runtime_error if reading size fails
|
||||
*/
|
||||
int GetFifoSize();
|
||||
|
||||
/**
|
||||
* @brief Disables interrupt function. Interrupt is enabled by default
|
||||
* on all operation modes, so this have to be called after enabling a
|
||||
* specific operation mode
|
||||
*
|
||||
* @throws std::runtime_error if setting interrupt disable bits fails
|
||||
*/
|
||||
void DisableInterrupt();
|
||||
|
||||
/**
|
||||
* @brief Clears the interrupt flag allowing more interrupts to be
|
||||
* raised
|
||||
*
|
||||
* @throws std::runtime_error if clearing interrupt fails
|
||||
*/
|
||||
void ClearInterrupt();
|
||||
|
||||
/**
|
||||
* @brief Starts the measuremnt on sensor or enable the sensor
|
||||
*
|
||||
* @throws std::runtime_error if starting measurement fails
|
||||
*/
|
||||
void StartMeasurement();
|
||||
|
||||
/**
|
||||
* @breif Stops the measurement by setting the software reset bit. This
|
||||
* function will reset all config registers. To resume from previous
|
||||
* configuration call RestartMeasurement().
|
||||
*
|
||||
* @throws std::runtime_error if disabling measurement fails
|
||||
*/
|
||||
void StopMeasurement();
|
||||
|
||||
/**
|
||||
* @brief Restart the measurement, This function stops measurement,
|
||||
* then re-writes the configuration registers again and start
|
||||
* measurement with same configuration.
|
||||
*
|
||||
* @throws std::runtime_error if restarting measurement fails
|
||||
*/
|
||||
void RestartMeasurement();
|
||||
|
||||
/**
|
||||
* @brief Gets the fifo data of 32 entries and resets the WATERMARK
|
||||
* interrupt flag.
|
||||
*
|
||||
* @return vector of values of the retrieved FIFO values, which are
|
||||
* vectors containing 2 values each (led off, led_on)
|
||||
* @throws std::runtime_error if reading FIFO data fails
|
||||
*/
|
||||
std::vector<std::vector<int>> GetFifoData();
|
||||
|
||||
/**
|
||||
* @brief Reads and discard the 32 FIFO entries to reset the WATERMARK
|
||||
* interrupt flag.
|
||||
*
|
||||
* @throws std::runtime_error if reading FIFO data fails
|
||||
*/
|
||||
void DiscardFifoData();
|
||||
|
||||
/**
|
||||
* @brief Gets the values from using green LED light
|
||||
*
|
||||
* @return vector of values (led off, led on) of green led values
|
||||
* @throws std::runtime_error if reading green data fails
|
||||
*/
|
||||
std::vector<int> GetGreenData();
|
||||
|
||||
/**
|
||||
* @brief Gets the values from using IR LED light
|
||||
*
|
||||
* @return vector of values (led off, led on) of IR led values
|
||||
* @throws std::runtime_error if reading IR data fails
|
||||
*/
|
||||
std::vector<int> GetIrData();
|
||||
|
||||
/**
|
||||
* @brief Enables and configures the sensor to use synchronized mode.
|
||||
* This will use the built-in FIFO and raises a WATERMARK interrupt
|
||||
* when FIFO size reaches 32 entries. To clear that interrupt flag FIFO
|
||||
* must be read or discarded. This mode uses only green LED.
|
||||
*
|
||||
* You need to call StartMeasurement() after this.
|
||||
*
|
||||
* @param measFreq Measurement frequncy mode, valid values 32, 64, 128,
|
||||
* 256, 1024
|
||||
* @param green_current Green LED current value
|
||||
* @throws std::runtime_error if enabling synchronized mode fails
|
||||
* @throws std::invalid_argument if measurement frequency is invalid
|
||||
*/
|
||||
void EnableSyncMode(uint16_t measFreq, uint16_t green_current);
|
||||
|
||||
/**
|
||||
* @brief Enabled and configures the sensor to use non-synchronized
|
||||
* mode. This mode uses IR_THRESHOLD interrupt, it will raise an
|
||||
* interrupt if IR LED ON value is equal or greater than the threshold
|
||||
* value. Interrupt must be cleared before receiving new interrupts.
|
||||
* This mode uses only IR LED.
|
||||
*
|
||||
* You need to call StartMeasurement() after this.
|
||||
*
|
||||
* @param ir_current The IR LED current value
|
||||
* @param threshold The IR LED interrupt threshold value
|
||||
*
|
||||
* @throws std::runtime_error if enabling non-synchronized mode fails
|
||||
*/
|
||||
void EnableNonSyncMode(uint16_t ir_current, uint16_t threshold);
|
||||
|
||||
/**
|
||||
* @brief Enables and configures the sensor to use single mode. This
|
||||
* sets the sensor to take only one measurement and raise an interrupt
|
||||
* after measurement is finished. Interrupt flags has to be cleared to
|
||||
* recieved new interrupts. This mode uses both green and IR LEDs.
|
||||
*
|
||||
* You need to call StartMeasurement() after this. If you need to get
|
||||
* continuous values, clear interrupt and StartMeasurement()
|
||||
* continuously.
|
||||
*
|
||||
* @param led_type LED light type to use, takes GREEN or IR (0 or 1)
|
||||
* @param current The chosen led_type current value
|
||||
* @throws std::runtime_error if enabling single mode fails
|
||||
*/
|
||||
void EnableSingleMode(LED_TYPES led_type, uint16_t current);
|
||||
|
||||
/**
|
||||
* @brief Installs the ISR to a given GPIO pin
|
||||
*
|
||||
* @param edge Edge type to raise ISR with, of type mraa_gpio_edge_t
|
||||
* @param pin GPIO pin number
|
||||
* @param isr Pointer to ISR function
|
||||
* @param isr_args Arguments to pass the ISR function
|
||||
* @throws std::runtime_error if installing ISR fails
|
||||
*/
|
||||
void InstallISR(mraa_gpio_edge_t edge, int pin, void (*isr)(void *),
|
||||
void *isr_args);
|
||||
|
||||
/**
|
||||
* @brief Installs the ISR to a given GPIO pin
|
||||
*
|
||||
* @param pin GPIO pin number
|
||||
* @param isr Pointer to ISR function
|
||||
* @param isr_args Arguments to pass the ISR function
|
||||
* @throws std::runtime_error if installing ISR fails
|
||||
*/
|
||||
void InstallISR(int pin, void (*isr)(void *), void *isr_args);
|
||||
|
||||
/**
|
||||
* @brief Removes the ISR if it is installed
|
||||
*/
|
||||
void RemoveISR();
|
||||
|
||||
/**
|
||||
* @brief Gets a dump of configuration registers as a string
|
||||
*
|
||||
* @return string of dumped registers
|
||||
* @throws std::runtime_error if reading one of the registers fails
|
||||
*/
|
||||
std::string RegistersDump();
|
||||
|
||||
private:
|
||||
bh1792_context m_bh1792;
|
||||
|
||||
/* Disable implicit copy and assignment operators */
|
||||
BH1792(const BH1792 &) = delete;
|
||||
BH1792 &operator=(const BH1792 &) = delete;
|
||||
};
|
||||
}
|
28
src/bh1792/bh1792.i
Executable file
28
src/bh1792/bh1792.i
Executable file
@ -0,0 +1,28 @@
|
||||
%include "../common_top.i"
|
||||
|
||||
/* BEGIN Java syntax ------------------------------------------------------- */
|
||||
#ifdef SWIGJAVA
|
||||
%ignore InstallISR(mraa_gpio_edge_t, int, void *, void *);
|
||||
|
||||
%extend upm::BH1792 {
|
||||
void InstallISR(int pin, jobject runnable)
|
||||
{
|
||||
$self->InstallISR(pin, mraa_java_isr_callback, runnable);
|
||||
}
|
||||
}
|
||||
|
||||
JAVA_JNI_LOADLIBRARY(javaupm_bh1792)
|
||||
#endif
|
||||
/* END Java syntax */
|
||||
|
||||
/* BEGIN Common SWIG syntax ------------------------------------------------- */
|
||||
%include "std_vector.i"
|
||||
%template(intVector) std::vector<int>;
|
||||
%template(intVector2D) std::vector<std::vector<int>>;
|
||||
|
||||
%{
|
||||
#include "bh1792.hpp"
|
||||
%}
|
||||
%include "bh1792.h"
|
||||
%include "bh1792.hpp"
|
||||
/* END Common SWIG syntax */
|
62
src/bh1792/bh1792.json
Executable file
62
src/bh1792/bh1792.json
Executable file
@ -0,0 +1,62 @@
|
||||
{
|
||||
"Library": "BH1792",
|
||||
"Description": "ROHM BH1792 Heart Rate Sensor library",
|
||||
"Sensor Class": {
|
||||
"BH1792": {
|
||||
"Name": "ROHM BH1792 Heart Rate Sensor library",
|
||||
"Description": "BH1792GLC is optical sensor for heart rate monitor IC in which LED driver, green light and IR detection photodiode are incorporated. This device drives LED and provides the intensity of light reflected from body. LED brightness can be adjusted by LED driver current. The photodiode having the high sensitivity for green light and excellent wavelength selectivity achieves accurate pulse wave detection.",
|
||||
"Categories": ["medical"],
|
||||
"Connections": ["i2c"],
|
||||
"Project Type": ["prototyping", "commercial"],
|
||||
"Manufacturers": ["ROHM"],
|
||||
"Examples": {
|
||||
"C++": ["bh1792.cxx"],
|
||||
"C": ["bh1792.c"],
|
||||
"Java": ["BH1792_Example.java"],
|
||||
"Python": ["bh1792.py"],
|
||||
"Node.js": ["bh1792.js"]
|
||||
},
|
||||
"Specifications": {
|
||||
"Supply Voltage (VDD)": {
|
||||
"unit": "V",
|
||||
"min": 2.5,
|
||||
"typical": 3.0,
|
||||
"max": 3.6
|
||||
},
|
||||
"Terminal Input Voltage": {
|
||||
"unit": "V",
|
||||
"min": 0.7,
|
||||
"max": 5.5
|
||||
},
|
||||
"Supply Current": {
|
||||
"unit": "uA",
|
||||
"min": 0.8,
|
||||
"max": 200
|
||||
},
|
||||
"LED Supply Current": {
|
||||
"unit": "mA",
|
||||
"typical": 1.4,
|
||||
"max": 3.0
|
||||
},
|
||||
"Standby Mode Current": {
|
||||
"unit": "uA",
|
||||
"typical": 0.8,
|
||||
"max": 1.5
|
||||
},
|
||||
"Operating Temperature": {
|
||||
"unit": "°C",
|
||||
"min": -20,
|
||||
"max": 85
|
||||
}
|
||||
},
|
||||
"Urls": {
|
||||
"Product Pages": [
|
||||
"https://www.rohm.com/sensor-shield-support/heart-rate-sensor2"
|
||||
],
|
||||
"Datasheets": [
|
||||
"https://www.rohm.com/datasheet/BH1792GLC/bh1792glc-e"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
129
src/bh1792/bh1792glc_registers.h
Executable file
129
src/bh1792/bh1792glc_registers.h
Executable file
@ -0,0 +1,129 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2017 Rohm Semiconductor
|
||||
|
||||
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.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __BH1792GLC_REGISTERS_H__
|
||||
#define __BH1792GLC_REGISTERS_H__
|
||||
/* registers */
|
||||
#define BH1792_REGISTER_DUMP_START 0x0F
|
||||
#define BH1792_MANUFACTURER_REG 0x0F
|
||||
// WHO_AM_I -value
|
||||
#define BH1792_PARTID_REG 0x10
|
||||
// Soft reset
|
||||
#define BH1792_RESET 0x40
|
||||
// System control setting
|
||||
#define BH1792_MEAS_CONTROL1 0x41
|
||||
// LED 1 & 2 control register
|
||||
#define BH1792_MEAS_CONTROL2 0x42
|
||||
// LED 3 control register
|
||||
#define BH1792_MEAS_CONTROL3 0x43
|
||||
// IR Interrupt Threshold Value [7:0]
|
||||
#define BH1792_MEAS_CONTROL4_L 0x44
|
||||
// IR Interrupt Threshold Value [15:8]
|
||||
#define BH1792_MEAS_CONTROL4_H 0x45
|
||||
#define BH1792_MEAS_CONTROL5 0x46
|
||||
#define BH1792_MEAS_START 0x47
|
||||
#define BH1792_MEAS_SYNC 0x48
|
||||
#define BH1792_FIFO_LEV 0x4B
|
||||
// FIFO Output data 0 [7:0]
|
||||
#define BH1792_FIFO_DATA0_L 0x4C
|
||||
// FIFO Output data 0 [15:8]
|
||||
#define BH1792_FIFO_DATA0_H 0x4D
|
||||
// FIFO Output data 1 [7:0]
|
||||
#define BH1792_FIFO_DATA1_L 0x4E
|
||||
// FIFO Output data 1 [15:8]
|
||||
#define BH1792_FIFO_DATA1_H 0x4F
|
||||
// IR Data Count Value during no LED emission [7:0]
|
||||
#define BH1792_IRDATA_LEDOFF_L 0x50
|
||||
// IR Data Count Value during no LED emission [15:8]
|
||||
#define BH1792_IRDATA_LEDOFF_H 0x51
|
||||
// IR Data Count Value during LED emission [7:0]
|
||||
#define BH1792_IRDATA_LEDON_L 0x52
|
||||
// IR Data Count Value during LED emission [15:8]
|
||||
#define BH1792_IRDATA_LEDON_H 0x53
|
||||
// Green Data Count Value during no LED emission [7:0]
|
||||
#define BH1792_DATAOUT_LEDOFF_L 0x54
|
||||
// Green Data Count Value during no LED emission [15:8]
|
||||
#define BH1792_DATAOUT_LEDOFF_H 0x55
|
||||
// Green Data Count Value during LED emission [7:0]
|
||||
#define BH1792_DATAOUT_LEDON_L 0x56
|
||||
// Green Data Count Value during LED emission [15:8]
|
||||
#define BH1792_DATAOUT_LEDON_H 0x57
|
||||
// IR threshold judgement and measurement completion interrupt is cleared when reading this register.
|
||||
#define BH1792_INT_CLEAR 0x58
|
||||
#define BH1792_REGISTER_DUMP_END 0x58
|
||||
/* registers bits */
|
||||
#define BH1792_MANUFACTURER_REG_MANUFACTURER_ID (0xE0 << 0)
|
||||
#define BH1792_PARTID_REG_PART_ID (0x0E << 0)
|
||||
// 1 : Software reset is performed
|
||||
#define BH1792_RESET_SWRESET (0x01 << 7)
|
||||
// 1 : OSC block is active, 0: prohibited
|
||||
#define BH1792_MEAS_CONTROL1_RDY (0x01 << 7)
|
||||
// Green mode, leds 1 & 2 active
|
||||
#define BH1792_MEAS_CONTROL1_SEL_ADC_GREEN (0x00 << 4)
|
||||
// IR mode, led 3 active. Can be used only in single and non synch modes.
|
||||
#define BH1792_MEAS_CONTROL1_SEL_ADC_IR (0x01 << 4)
|
||||
// 32 Hz synchronous mode
|
||||
#define BH1792_MEAS_CONTROL1_MSR_32HZ (0x00 << 0)
|
||||
// 128 Hz synchronous mode
|
||||
#define BH1792_MEAS_CONTROL1_MSR_128HZ (0x01 << 0)
|
||||
// 64 Hz synchronous mode
|
||||
#define BH1792_MEAS_CONTROL1_MSR_64HZ (0x02 << 0)
|
||||
// 256 Hz synchronous mode
|
||||
#define BH1792_MEAS_CONTROL1_MSR_256HZ (0x03 << 0)
|
||||
#define BH1792_MEAS_CONTROL1_MSR_PROHIBITED (0x04 << 0)
|
||||
// 1024 Hz synchronous mode
|
||||
#define BH1792_MEAS_CONTROL1_MSR_1024HZ (0x05 << 0)
|
||||
// non synchronized measurement mode
|
||||
#define BH1792_MEAS_CONTROL1_MSR_NON_SYNCH_MODE (0x06 << 0)
|
||||
// single measurement mode
|
||||
#define BH1792_MEAS_CONTROL1_MSR_SINGLE_MEAS_MODE (0x07 << 0)
|
||||
// LED driver mode, for usage see datasheet
|
||||
#define BH1792_MEAS_CONTROL3_LED_EN2 (0x01 << 7)
|
||||
// No interrupt output.
|
||||
#define BH1792_MEAS_CONTROL5_INT_SEL_DISABLE (0x00 << 0)
|
||||
// Watermark interrupt FIFO, fires when number of stored samples reaches 32. Cleared when number of samples falls below 32.
|
||||
#define BH1792_MEAS_CONTROL5_INT_SEL_FIFO_WATERMARK (0x01 << 0)
|
||||
// IR threshold judgement interrupt. Used in non synchroniozed mode.
|
||||
#define BH1792_MEAS_CONTROL5_INT_SEL_IR_THRESHOLD (0x02 << 0)
|
||||
// Measurement completion interrupt. In single mode.
|
||||
#define BH1792_MEAS_CONTROL5_INT_SEL_ON_COMPLETE (0x03 << 0)
|
||||
// Flag of start measurement. MEAS_ST=1 after RDY=1 starts measurement. In single measurement mode MEAS_ST=1 restarts measurement.
|
||||
#define BH1792_MEAS_START_MEAS_ST (0x01 << 0)
|
||||
// Used in synhcronized measurement mode. Write once per second.
|
||||
#define BH1792_MEAS_SYNC_MEAS_SYNC (0x01 << 0)
|
||||
/*registers bit masks */
|
||||
#define BH1792_MANUFACTURER_REG_MANUFACTURER_MASK 0xFF
|
||||
#define BH1792_PARTID_REG_PART_MASK 0xFF
|
||||
// Select LED omitting frequency
|
||||
#define BH1792_MEAS_CONTROL1_SEL_ADC_MASK 0x10
|
||||
// Measurement mode
|
||||
#define BH1792_MEAS_CONTROL1_MSR_MASK 0x07
|
||||
#define BH1792_MEAS_CONTROL2_LED_EN1_MASK 0xC0
|
||||
#define BH1792_MEAS_CONTROL2_LED_CURRENT1_MASK 0x3F
|
||||
#define BH1792_MEAS_CONTROL3_LED_CURRENT2_MASK 0x3F
|
||||
// Interrupt function select
|
||||
#define BH1792_MEAS_CONTROL5_INT_SEL_MASK 0x03
|
||||
#define BH1792_FIFO_LEV_LEVEL_MASK 0x3F
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user