zephyr/samples/sensor/ccs811/src/main.c
Andy Ross 32bb2395c2 timeout: Fix up API usage
Kernel timeouts have always been a 32 bit integer despite the
existence of generation macros, and existing code has been
inconsistent about using them.  Upcoming commits are going to make the
timeout arguments opaque, so fix things up to be rigorously correct.
Changes include:

+ Adding a K_TIMEOUT_EQ() macro for code that needs to compare timeout
  values for equality (e.g. with K_FOREVER or K_NO_WAIT).

+ Adding a k_msleep() synonym for k_sleep() which can continue to take
  integral arguments as k_sleep() moves away to timeout arguments.

+ Pervasively using the K_MSEC(), K_SECONDS(), et. al. macros to
  generate timeout arguments.

+ Removing the usage of K_NO_WAIT as the final argument to
  K_THREAD_DEFINE().  This is just a count of milliseconds and we need
  to use a zero.

This patch include no logic changes and should not affect generated
code at all.

Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
2020-03-31 19:40:47 -04:00

191 lines
4.4 KiB
C

/*
* Copyright (c) 2018 Peter Bigot Consulting, LLC
* Copyright (c) 2018 Linaro Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include <device.h>
#include <drivers/sensor.h>
#include <sys/printk.h>
#include <drivers/sensor/ccs811.h>
#include <stdio.h>
static bool app_fw_2;
static const char *now_str(void)
{
static char buf[16]; /* ...HH:MM:SS.MMM */
u32_t now = k_uptime_get_32();
unsigned int ms = now % MSEC_PER_SEC;
unsigned int s;
unsigned int min;
unsigned int h;
now /= MSEC_PER_SEC;
s = now % 60U;
now /= 60U;
min = now % 60U;
now /= 60U;
h = now;
snprintf(buf, sizeof(buf), "%u:%02u:%02u.%03u",
h, min, s, ms);
return buf;
}
static int do_fetch(struct device *dev)
{
struct sensor_value co2, tvoc, voltage, current;
int rc = 0;
int baseline = -1;
#ifdef CONFIG_APP_MONITOR_BASELINE
rc = ccs811_baseline_fetch(dev);
if (rc >= 0) {
baseline = rc;
rc = 0;
}
#endif
if (rc == 0) {
rc = sensor_sample_fetch(dev);
}
if (rc == 0) {
const struct ccs811_result_type *rp = ccs811_result(dev);
sensor_channel_get(dev, SENSOR_CHAN_CO2, &co2);
sensor_channel_get(dev, SENSOR_CHAN_VOC, &tvoc);
sensor_channel_get(dev, SENSOR_CHAN_VOLTAGE, &voltage);
sensor_channel_get(dev, SENSOR_CHAN_CURRENT, &current);
printk("\n[%s]: CCS811: %u ppm eCO2; %u ppb eTVOC\n",
now_str(), co2.val1, tvoc.val1);
printk("Voltage: %d.%06dV; Current: %d.%06dA\n", voltage.val1,
voltage.val2, current.val1, current.val2);
#ifdef CONFIG_APP_MONITOR_BASELINE
printk("BASELINE %04x\n", baseline);
#endif
if (app_fw_2 && !(rp->status & CCS811_STATUS_DATA_READY)) {
printk("STALE DATA\n");
}
if (rp->status & CCS811_STATUS_ERROR) {
printk("ERROR: %02x\n", rp->error);
}
}
return rc;
}
#ifndef CONFIG_CCS811_TRIGGER_NONE
static void trigger_handler(struct device *dev, struct sensor_trigger *trig)
{
int rc = do_fetch(dev);
if (rc == 0) {
printk("Triggered fetch got %d\n", rc);
} else if (-EAGAIN == rc) {
printk("Triggered fetch got stale data\n");
} else {
printk("Triggered fetch failed: %d\n", rc);
}
}
#endif /* !CONFIG_CCS811_TRIGGER_NONE */
static void do_main(struct device *dev)
{
while (true) {
int rc = do_fetch(dev);
if (rc == 0) {
printk("Timed fetch got %d\n", rc);
} else if (-EAGAIN == rc) {
printk("Timed fetch got stale data\n");
} else {
printk("Timed fetch failed: %d\n", rc);
break;
}
k_msleep(1000);
}
}
void main(void)
{
struct device *dev = device_get_binding(DT_LABEL(DT_INST(0, ams_ccs811)));
struct ccs811_configver_type cfgver;
int rc;
if (!dev) {
printk("Failed to get device binding");
return;
}
printk("device is %p, name is %s\n", dev, dev->config->name);
rc = ccs811_configver_fetch(dev, &cfgver);
if (rc == 0) {
printk("HW %02x; FW Boot %04x App %04x ; mode %02x\n",
cfgver.hw_version, cfgver.fw_boot_version,
cfgver.fw_app_version, cfgver.mode);
app_fw_2 = (cfgver.fw_app_version >> 8) > 0x11;
}
#ifdef CONFIG_APP_USE_ENVDATA
struct sensor_value temp = { CONFIG_APP_ENV_TEMPERATURE };
struct sensor_value humidity = { CONFIG_APP_ENV_HUMIDITY };
rc = ccs811_envdata_update(dev, &temp, &humidity);
printk("ENV_DATA set for %d Cel, %d %%RH got %d\n",
temp.val1, humidity.val1, rc);
#endif
#ifdef CONFIG_CCS811_TRIGGER
struct sensor_trigger trig = { 0 };
#ifdef CONFIG_APP_TRIGGER_ON_THRESHOLD
printk("Triggering on threshold:\n");
if (rc == 0) {
struct sensor_value thr = {
.val1 = CONFIG_APP_CO2_MEDIUM_PPM,
};
rc = sensor_attr_set(dev, SENSOR_CHAN_CO2,
SENSOR_ATTR_LOWER_THRESH,
&thr);
printk("L/M threshold to %d got %d\n", thr.val1, rc);
}
if (rc == 0) {
struct sensor_value thr = {
.val1 = CONFIG_APP_CO2_HIGH_PPM,
};
rc = sensor_attr_set(dev, SENSOR_CHAN_CO2,
SENSOR_ATTR_UPPER_THRESH,
&thr);
printk("M/H threshold to %d got %d\n", thr.val1, rc);
}
trig.type = SENSOR_TRIG_THRESHOLD;
trig.chan = SENSOR_CHAN_CO2;
#elif defined(CONFIG_APP_TRIGGER_ON_DATAREADY)
printk("Triggering on data ready\n");
trig.type = SENSOR_TRIG_DATA_READY;
trig.chan = SENSOR_CHAN_ALL;
#else
#error Unhandled trigger on
#endif
if (rc == 0) {
rc = sensor_trigger_set(dev, &trig, trigger_handler);
}
if (rc == 0) {
#ifdef CONFIG_APP_TRIGGER_ON_DATAREADY
while (true) {
k_sleep(K_FOREVER);
}
#endif
}
printk("Trigger installation got: %d\n", rc);
#endif /* CONFIG_CCS811_TRIGGER */
if (rc == 0) {
do_main(dev);
}
}