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>
191 lines
4.4 KiB
C
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, ¤t);
|
|
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);
|
|
}
|
|
}
|