Skip to content

Instantly share code, notes, and snippets.

@Pillar1989
Created November 2, 2021 02:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Pillar1989/c579b789e38e856cde16e77345932ac4 to your computer and use it in GitHub Desktop.
Save Pillar1989/c579b789e38e856cde16e77345932ac4 to your computer and use it in GitHub Desktop.
beagleconect sensortest factory firmware source code
/*
* Copyright (c) 2020 Friedt Professional Engineering Services, Inc
* Copyright (c) 2020 Jason Kridner
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include <device.h>
#include <drivers/gpio.h>
#include <drivers/led.h>
#include <drivers/sensor.h>
#include <drivers/spi.h>
#include <drivers/i2c.h>
#include <drivers/uart.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <net/net_ip.h>
#include <net/socket.h>
#include <sys/util.h>
#include <random/rand32.h>
#define LOG_LEVEL LOG_LEVEL_INF
#include <logging/log.h>
LOG_MODULE_REGISTER(sensortest);
#define BLINK_MS 500
#define MAX_STR_LEN 200
#define I2C_DEV DT_LABEL(DT_ALIAS(i2c_0)
#define UART_DEVICE_NAME "UART_1"
static char outstr[MAX_STR_LEN];
enum api {
LED_API,
BUTTON_API,
SENSOR_API,
};
enum edev {
LED_24G,
BUTTON,
LIGHT,
ACCEL,
HUMIDITY,
ENVIRONMENT,
AIRQUALITY,
PARTICULATE,
I2CDEVICE,
NUM_DEVICES,
};
struct led_work {
uint8_t active_led;
struct k_delayed_work dwork;
};
const struct uart_config uart_cfg = {
.baudrate = 115200,
.parity = UART_CFG_PARITY_NONE,
.stop_bits = UART_CFG_STOP_BITS_1,
.data_bits = UART_CFG_DATA_BITS_8,
.flow_ctrl = UART_CFG_FLOW_CTRL_NONE
};
static void sensor_work_handler(struct k_work *work);
static const char *device_labels[NUM_DEVICES] = {
[LED_24G] = DT_LABEL(DT_ALIAS(led0)),
[BUTTON] = DT_LABEL(DT_ALIAS(sw0)),
[LIGHT] = "LIGHT",
[ACCEL] = "ACCEL",
[HUMIDITY] = "HUMIDITY",
[ENVIRONMENT] = "ENVIRONMENT",
[AIRQUALITY] = "AIRQUALITY",
[PARTICULATE] = "PARTICULATE",
[I2CDEVICE] = "I2CDEVICE",
};
static const char *device_names[NUM_DEVICES] = {
[LED_24G] = DT_GPIO_LABEL(DT_ALIAS(led0), gpios),
[BUTTON] = DT_GPIO_LABEL(DT_ALIAS(sw0), gpios),
[LIGHT] = "OPT3001-LIGHT",
[ACCEL] = "LIS2DE12-ACCEL",
[HUMIDITY] = "HDC2010-HUMIDITY",
[ENVIRONMENT] = "BME680-ENVIRONMENT",
[AIRQUALITY] = "SGP30-AIRQUALITY",
[PARTICULATE] = "HM3301-PARTICULATE",
[I2CDEVICE] = "I2C_0",
};
static const uint8_t device_pins[NUM_DEVICES] = {
[LED_24G] = DT_GPIO_PIN(DT_ALIAS(led0), gpios),
[BUTTON] = DT_GPIO_PIN(DT_ALIAS(sw0), gpios),
};
static const enum api apis[NUM_DEVICES] = {
LED_API,
BUTTON_API,
SENSOR_API, /* LIGHT */
SENSOR_API, /* ACCEL */
SENSOR_API, /* HUMIDITY */
SENSOR_API, /* ENVIRONMENT */
SENSOR_API, /* AIRQUALITY */
SENSOR_API, /* PARTICULATE */
SENSOR_API, /* I2CDEVICE */
};
static struct device *devices[NUM_DEVICES];
static struct led_work led_work;
K_WORK_DEFINE(sensor_work, sensor_work_handler);
static struct gpio_callback button_callback;
static struct sockaddr_in6 addr;
static int fd = -1;
/* Set TIMED_SENSOR_READ to 0 to disable */
#define TIMED_SENSOR_READ 60
static int sensor_read_count = TIMED_SENSOR_READ;
#define FRAM_I2C_ADDR 0x48
#define MSP430_BUZZER 0x00
#define BUZZER_ON 0x00
#define BUZZER_OFF 0x01
#define MSP430_LED1 0x01
#define LED1_ON 0x02
#define LED1_OFF 0x03
#define MSP430_LED2 0x02
#define LED2_ON 0x04
#define LED2_OFF 0x05
#define MSP430_L900M 0x03
#define L900M_ON 0x06
#define L900M_OFF 0x07
static int write_addr(const struct device *i2c_dev, uint16_t addr)
{
uint8_t wr_addr[2];
struct i2c_msg msgs[2];
/* FRAM address */
wr_addr[0] = (addr >> 8) & 0xFF;
wr_addr[1] = addr & 0xFF;
/* Send the address to write to */
msgs[0].buf = wr_addr;
msgs[0].len = 2U;
msgs[0].flags = I2C_MSG_WRITE;
return i2c_transfer(i2c_dev, &msgs[0], 1, FRAM_I2C_ADDR);
}
static int msp430_io_ctrl(const struct device *i2c_dev, uint8_t io, uint8_t data){
return write_addr(i2c_dev, io * 2 + data);
}
static void led_work_handler(struct k_work *work)
{
ARG_UNUSED(work);
int r;
LOG_DBG("%s(): active_led: %u", __func__, led_work.active_led);
r = gpio_pin_set(devices[LED_24G], device_pins[LED_24G], led_work.active_led);
__ASSERT(r == 0, "failed to turn off led %u: %d", prev_led, r);
msp430_io_ctrl(devices[I2CDEVICE], MSP430_BUZZER, led_work.active_led);
msp430_io_ctrl(devices[I2CDEVICE], MSP430_LED1, led_work.active_led);
msp430_io_ctrl(devices[I2CDEVICE], MSP430_LED2, led_work.active_led);
msp430_io_ctrl(devices[I2CDEVICE], MSP430_L900M, led_work.active_led);
led_work.active_led = led_work.active_led ? 0: 1;
r = k_delayed_work_submit(&led_work.dwork, K_MSEC(BLINK_MS));
__ASSERT(r == 0, "k_delayed_work_submit() failed for LED %u work: %d",
led_work.active_led, r);
if (sensor_read_count > 0) {
sensor_read_count--;
if (sensor_read_count <= 0) {
sensor_read_count = TIMED_SENSOR_READ;
if(TIMED_SENSOR_READ > 0)
sensor_read_count +=
sys_rand32_get() % TIMED_SENSOR_READ;
k_work_submit(&sensor_work);
}
}
}
static void print_sensor_value(size_t idx, const char *chan,
struct sensor_value *val)
{
LOG_INF("%s: %s%d,%d", device_labels[idx], chan, val->val1, val->val2);
sprintf(outstr+strlen(outstr), "%d%c:", idx, chan[0]);
sprintf(outstr+strlen(outstr), "%d", val->val1);
if (val->val2 != 0) {
sprintf(outstr+strlen(outstr), ".%02d;", abs(val->val2) / 10000);
} else {
sprintf(outstr+strlen(outstr), ";");
}
}
static void send_sensor_value()
{
if ((fd >= 0) && (strlen(outstr) > 0)) {
//LOG_INF("%s", log_strdup(outstr));
sendto(fd, outstr, strlen(outstr), 0,
(const struct sockaddr *) &addr,
sizeof(addr));
}
outstr[0] = '\0';
}
static void sensor_work_handler(struct k_work *work)
{
struct sensor_value val;
struct sensor_value th[2] = {{0,0}, {0,0}}; /* calibration data for SGP30 */
outstr[0] = '\0';
for (size_t i = 0; i < NUM_DEVICES; ++i) {
if (apis[i] != SENSOR_API) {
continue;
}
if (devices[i] == NULL) {
continue;
}
if (i == I2CDEVICE) {
continue;
}
sensor_sample_fetch(devices[i]);
if (i == LIGHT) {
sensor_channel_get(devices[i], SENSOR_CHAN_LIGHT, &val);
print_sensor_value(i, "l: ", &val);
send_sensor_value();
continue;
}
if (i == ACCEL) {
#if 0
sensor_channel_get(devices[i], SENSOR_CHAN_ACCEL_X,
&val);
print_sensor_value(i, "x: ", &val);
sensor_channel_get(devices[i], SENSOR_CHAN_ACCEL_Y,
&val);
print_sensor_value(i, "y: ", &val);
sensor_channel_get(devices[i], SENSOR_CHAN_ACCEL_Z,
&val);
print_sensor_value(i, "z: ", &val);
send_sensor_value();
#endif
continue;
}
if (i == HUMIDITY) {
sensor_channel_get(devices[i], SENSOR_CHAN_HUMIDITY,
&val);
print_sensor_value(i, "h: ", &val);
sensor_channel_get(devices[i], SENSOR_CHAN_AMBIENT_TEMP,
&val);
print_sensor_value(i, "t: ", &val);
send_sensor_value();
continue;
}
if (i == ENVIRONMENT) {
sensor_channel_get(devices[i], SENSOR_CHAN_AMBIENT_TEMP, &val);
th[0].val1 = val.val1;
th[0].val2 = val.val2;
print_sensor_value(i, "t: ", &val);
sensor_channel_get(devices[i], SENSOR_CHAN_PRESS, &val);
print_sensor_value(i, "p: ", &val);
sensor_channel_get(devices[i], SENSOR_CHAN_HUMIDITY, &val);
th[1].val1 = val.val1;
th[1].val2 = val.val2;
print_sensor_value(i, "h: ", &val);
sensor_channel_get(devices[i], SENSOR_CHAN_GAS_RES, &val);
print_sensor_value(i, "g: ", &val);
send_sensor_value();
continue;
}
if (i == AIRQUALITY) {
sensor_channel_get(devices[i], SENSOR_CHAN_VOC, &val);
print_sensor_value(i, "v: ", &val);
sensor_channel_get(devices[i], SENSOR_CHAN_CO2, &val);
print_sensor_value(i, "c: ", &val);
if(th[0].val1 != 0) {
sensor_attr_set(devices[i], SENSOR_CHAN_VOC,
SENSOR_ATTR_CALIB_TARGET, &th[0]);
}
send_sensor_value();
continue;
}
if (i == PARTICULATE) {
sensor_channel_get(devices[i], SENSOR_CHAN_PM_1_0, &val);
print_sensor_value(i, "1: ", &val);
sensor_channel_get(devices[i], SENSOR_CHAN_PM_2_5, &val);
print_sensor_value(i, "2: ", &val);
sensor_channel_get(devices[i], SENSOR_CHAN_PM_10, &val);
print_sensor_value(i, "X: ", &val);
send_sensor_value();
continue;
}
}
}
static void button_handler(struct device *port, struct gpio_callback *cb,
gpio_port_pins_t pins)
{
ARG_UNUSED(port);
gpio_pin_t pin = device_pins[BUTTON];
gpio_port_pins_t mask = BIT(pin);
if ((mask & cb->pin_mask) != 0) {
if ((mask & pins) != 0) {
/* BEL (7) triggers BEEP on MSP430 */
LOG_INF("%c%s event", 7, device_labels[BUTTON]);
/* print sensor readings */
k_work_submit(&sensor_work);
}
}
}
static void uart_fifo_callback(const struct device *dev, void *user_data)
{
uint8_t recvData;
ARG_UNUSED(user_data);
/* Verify uart_irq_update() */
if (!uart_irq_update(dev)) {
LOG_INF("retval should always be 1\n");
return;
}
/* Verify uart_irq_rx_ready() */
if (uart_irq_rx_ready(dev)) {
/* Verify uart_fifo_read() */
uart_fifo_read(dev, &recvData, 1);
LOG_INF("uart: %c", recvData);
uart_fifo_fill(dev, &recvData,1);
}
}
static void trigger_handler(const struct device *sensor,
struct sensor_trigger *trig)
{
static unsigned int count;
struct sensor_value accel[3];
const char *overrun = "";
int rc = sensor_sample_fetch(sensor);
++count;
if (rc == -EBADMSG) {
/* Sample overrun. Ignore in polled mode. */
if (IS_ENABLED(CONFIG_LIS2DH_TRIGGER)) {
overrun = "[OVERRUN] ";
}
rc = 0;
}
if (rc == 0) {
// rc = sensor_channel_get(sensor,
// SENSOR_CHAN_ACCEL_XYZ,
// accel);
sensor_channel_get(sensor, SENSOR_CHAN_ACCEL_X,
&accel[0]);
print_sensor_value(ACCEL, "x: ", &accel[0]);
sensor_channel_get(sensor, SENSOR_CHAN_ACCEL_Y,
&accel[1]);
print_sensor_value(ACCEL, "y: ", &accel[1]);
sensor_channel_get(sensor, SENSOR_CHAN_ACCEL_Z,
&accel[2]);
print_sensor_value(ACCEL, "z: ", &accel[2]);
send_sensor_value();
}
// if (rc < 0) {
// LOG_INF("ERROR: Update failed: %d\n", rc);
// } else {
// LOG_INF("#%u @ %u ms: %sx %f , y %f , z %f\n",
// count, k_uptime_get_32(), overrun,
// sensor_value_to_double(&accel[0]),
// sensor_value_to_double(&accel[1]),
// sensor_value_to_double(&accel[2]));
// }
}
void main(void)
{
int r;
outstr[0] = '\0';
const struct device *uart_dev = device_get_binding(UART_DEVICE_NAME);
struct sensor_trigger trig;
trig.type = SENSOR_TRIG_DATA_READY;
trig.chan = SENSOR_CHAN_ACCEL_XYZ;
fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
if (fd < 0) {
LOG_ERR("failed to open socket");
} else {
memset(&addr, 0, sizeof(struct sockaddr_in6));
addr.sin6_family = AF_INET6;
addr.sin6_port = htons(9999);
inet_pton(AF_INET6, "ff02::1", &addr.sin6_addr);
}
for (size_t i = 0; i < NUM_DEVICES; ++i) {
LOG_INF("opening device %s", device_labels[i]);
devices[i] =
(struct device *)device_get_binding(device_names[i]);
if (devices[i] == NULL) {
LOG_ERR("failed to open device %s", device_labels[i]);
continue;
}
/* per-device setup */
switch (apis[i]) {
case LED_API:
r = gpio_pin_configure(devices[i], device_pins[i],
GPIO_OUTPUT_LOW);
__ASSERT(r == 0,
"gpio_pin_configure(%s, %u, %x) failed: %d",
device_labels[i], device_pins[i],
GPIO_OUTPUT_LOW, r);
break;
case BUTTON_API:
r = gpio_pin_configure(
devices[i], device_pins[i],
(GPIO_INPUT |
DT_GPIO_FLAGS(DT_ALIAS(sw0), gpios)));
__ASSERT(r == 0,
"gpio_pin_configure(%s, %u, %x) failed: %d",
device_labels[i], device_pins[i],
(GPIO_INPUT |
DT_GPIO_FLAGS(DT_ALIAS(sw0), gpios)),
r);
r = gpio_pin_interrupt_configure(
devices[i], device_pins[i],
GPIO_INT_EDGE_TO_ACTIVE);
__ASSERT(
r == 0,
"gpio_pin_interrupt_configure(%s, %u, %x) failed: %d",
device_labels[i], device_pins[i],
GPIO_INT_EDGE_TO_ACTIVE, r);
break;
case SENSOR_API:
break;
default:
break;
}
}
r = uart_configure(uart_dev, &uart_cfg);
if (r == -ENOTSUP) {
__ASSERT(r == 0, "uart configure error %d",r);
}
uart_irq_callback_set(uart_dev, uart_fifo_callback);
uart_irq_rx_enable(uart_dev);
#if 0
if (IS_ENABLED(CONFIG_LIS2DH_ODR_RUNTIME)) {
struct sensor_value odr = {
.val1 = 1,
};
r = sensor_attr_set(devices[ACCEL], trig.chan,
SENSOR_ATTR_SAMPLING_FREQUENCY,
&odr);
__ASSERT(r != 0, "Failed to set odr: %d\n",r);
struct sensor_value full_cale = {
.val1 = 1,
};
sensor_g_to_ms2(16, &full_cale);
r = sensor_attr_set(devices[ACCEL], trig.chan,
SENSOR_ATTR_FULL_SCALE,
&full_cale);
__ASSERT(r != 0, "Failed to set full_cale: %d\n",r);
struct sensor_value slope = {
.val1 = 4,
.val2 = 0,
};
r = sensor_attr_set(devices[ACCEL], trig.chan,
SENSOR_ATTR_SLOPE_DUR,
&slope);
__ASSERT(r != 0, "Failed to set slope: %d\n",r);
LOG_INF("Sampling at %u Hz\n", odr.val1);
}
r = sensor_trigger_set(devices[ACCEL], &trig, trigger_handler);
__ASSERT(r != 0, "Failed to set trigger: %d\n",r);
#endif
/* setup timer-driven LED event */
led_work.dwork.work.handler = led_work_handler;
led_work.active_led = LED_24G;
r = k_delayed_work_submit(&led_work.dwork, K_MSEC(BLINK_MS));
__ASSERT(r == 0, "k_delayed_work_submit() failed for LED %u work: %d",
LED_24G, r);
/* setup input-driven button event */
gpio_init_callback(
&button_callback, (gpio_callback_handler_t)button_handler,
BIT(device_pins[BUTTON]));
r = gpio_add_callback(devices[BUTTON], &button_callback);
__ASSERT(r == 0, "gpio_add_callback() failed: %d", r);
for (;;) {
k_sleep(K_MSEC(1000));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment