-
-
Save Pillar1989/c579b789e38e856cde16e77345932ac4 to your computer and use it in GitHub Desktop.
beagleconect sensortest factory firmware source code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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