upm/src/bh1750/bh1750.c
Noel Eck 21ecbd90eb ANDROID: Treat utilities as its own library
Since src/utilities now builds a C/C++ library, other targets which were
using symbols from utilities now need to include the correct target
dependency.  This is mainly for upm_delay* functions.  Added utilities-c
target to all sensor library CMakeLists.txt which require it.

Moved macro for __FILENAME__ from upm_utilities.h to upm_fti.h since
ONLY the FTI headers used this.

Signed-off-by: Noel Eck <noel.eck@intel.com>
2017-04-24 10:27:44 -07:00

308 lines
7.1 KiB
C

/*
* Authors: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* 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 <assert.h>
#include "bh1750.h"
#include "upm_utilities.h"
bh1750_context bh1750_init(int bus, uint8_t addr, BH1750_OPMODES_T mode)
{
// make sure MRAA is initialized
int mraa_rv;
if ((mraa_rv = mraa_init()) != MRAA_SUCCESS)
{
printf("%s: mraa_init() failed (%d).\n", __FUNCTION__, mraa_rv);
return NULL;
}
bh1750_context dev =
(bh1750_context)malloc(sizeof(struct _bh1750_context));
if (!dev)
{
printf("%s: context allocation failed.\n", __FUNCTION__);
return NULL;
}
dev->bus = bus;
dev->is_continuous = false;
// init the i2c context
if (!(dev->i2c = mraa_i2c_init(dev->bus)))
{
printf("%s: mraa_i2c_init failed.\n", __FUNCTION__);
free(dev);
return NULL;
}
// now check the address...
if (mraa_i2c_address(dev->i2c, addr) != MRAA_SUCCESS)
{
printf("%s: mraa_i2c_address failed.\n", __FUNCTION__);
bh1750_close(dev);
return NULL;
}
// set the mode
if (bh1750_set_opmode(dev, mode) != UPM_SUCCESS)
{
printf("%s: bh1750_set_mode failed.\n", __FUNCTION__);
bh1750_close(dev);
return NULL;
}
return dev;
}
void bh1750_close(const bh1750_context dev)
{
assert(dev != NULL);
if (dev->i2c)
mraa_i2c_stop(dev->i2c);
free(dev);
}
upm_result_t bh1750_get_lux(const bh1750_context dev, float* lux)
{
assert(dev != NULL);
// from the datasheet, page 7
static const float coeff = 1.2;
uint16_t raw_lux = 0;
upm_result_t rv;
if ((rv = bh1750_read_data(dev, &raw_lux)) != UPM_SUCCESS)
{
printf("%s: bh1750_read_data failed.\n", __FUNCTION__);
return rv;
}
*lux = (float)raw_lux;
*lux /= coeff;
return rv;
}
bool bh1750_power_up(const bh1750_context dev)
{
assert(dev != NULL);
if (bh1750_send_command(dev, BH1750_CMD_POWER_UP))
{
printf("%s: bh1750_send_command failed.\n", __FUNCTION__);
return false;
}
return true;
}
bool bh1750_power_down(const bh1750_context dev)
{
assert(dev != NULL);
if (bh1750_send_command(dev, BH1750_CMD_POWER_DOWN))
{
printf("%s: bh1750_send_command failed.\n", __FUNCTION__);
return false;
}
return true;
}
bool bh1750_reset(const bh1750_context dev)
{
assert(dev != NULL);
if (bh1750_send_command(dev, BH1750_CMD_RESET))
{
printf("%s: bh1750_send_command failed.\n", __FUNCTION__);
return false;
}
return true;
}
upm_result_t bh1750_send_command(const bh1750_context dev, uint8_t cmd)
{
assert(dev != NULL);
if (mraa_i2c_write_byte(dev->i2c, cmd))
{
printf("%s: mraa_i2c_write_byte failed.\n", __FUNCTION__);
return UPM_ERROR_OPERATION_FAILED;
}
return UPM_SUCCESS;
}
upm_result_t bh1750_read_data(const bh1750_context dev, uint16_t* data)
{
assert(dev != NULL);
// if we are in a non-continuous mode, we need to power up the
// device and send the measurement mode command we are interested
// in. After the measurement has been read, the device will then
// power down again.
if (!dev->is_continuous)
{
// power up
if (!bh1750_power_up(dev))
{
printf("%s: bh1750_power_up failed.\n", __FUNCTION__);
return UPM_ERROR_OPERATION_FAILED;
}
// send the command, and delay appropriately
if (bh1750_send_command(dev, dev->opmode))
{
printf("%s: bh1750_send_command failed.\n", __FUNCTION__);
return UPM_ERROR_OPERATION_FAILED;
}
upm_delay_ms(dev->delayms);
}
// now get our data...
const int num_bytes = 2;
uint8_t bytes[num_bytes];
int bytes_read = 0;
if ((bytes_read = mraa_i2c_read(dev->i2c, bytes, num_bytes)) != num_bytes)
{
printf("%s: mraa_i2c_read failed.\n", __FUNCTION__);
return UPM_ERROR_NO_DATA;
}
// uncompensated, raw data
*data = (bytes[0] << 8) | bytes[1];
return UPM_SUCCESS;
}
upm_result_t bh1750_set_opmode(const bh1750_context dev,
BH1750_OPMODES_T mode)
{
assert(dev != NULL);
switch(mode)
{
case BH1750_OPMODE_H1_CONT:
dev->is_continuous = true;
dev->delayms = BH1750_MAX_MEAS_TIME_H;
dev->opmode = BH1750_CMD_CONT_H_RES_MODE1;
break;
case BH1750_OPMODE_H2_CONT:
dev->is_continuous = true;
dev->delayms = BH1750_MAX_MEAS_TIME_H;
dev->opmode = BH1750_CMD_CONT_H_RES_MODE2;
break;
case BH1750_OPMODE_H1_ONCE:
dev->is_continuous = false;
dev->delayms = BH1750_MAX_MEAS_TIME_H;
dev->opmode = BH1750_CMD_ONETIME_H_RES_MODE1;
break;
case BH1750_OPMODE_H2_ONCE:
dev->is_continuous = false;
dev->delayms = BH1750_MAX_MEAS_TIME_H;
dev->opmode = BH1750_CMD_ONETIME_H_RES_MODE2;
break;
case BH1750_OPMODE_L_CONT:
dev->is_continuous = true;
dev->delayms = BH1750_MAX_MEAS_TIME_L;
dev->opmode = BH1750_CMD_CONT_L_RES_MODE;
break;
case BH1750_OPMODE_L_ONCE:
dev->is_continuous = false;
dev->delayms = BH1750_MAX_MEAS_TIME_L;
dev->opmode = BH1750_CMD_ONETIME_L_RES_MODE;
break;
default:
printf("%s: Invalid mode.\n", __FUNCTION__);
return UPM_ERROR_INVALID_PARAMETER;
}
// If we are in a continuous mode, power on the device and start
// measuring.
if (dev->is_continuous)
{
if (!bh1750_power_up(dev))
{
printf("%s: bh1750_power_up failed.\n", __FUNCTION__);
return UPM_ERROR_OPERATION_FAILED;
}
if (bh1750_send_command(dev, dev->opmode))
{
printf("%s: bh1750_send_command failed.\n", __FUNCTION__);
return UPM_ERROR_OPERATION_FAILED;
}
upm_delay_ms(dev->delayms);
}
else
{
// if we are not in a continuous mode, power the device off
if (!bh1750_power_down(dev))
{
printf("%s: bh1750_power_down failed.\n", __FUNCTION__);
return UPM_ERROR_OPERATION_FAILED;
}
}
return UPM_SUCCESS;
}