AI cleanup

This commit is contained in:
Your Name
2026-05-21 11:43:09 +03:00
parent 3a5e91c4bf
commit cb6266b312
20 changed files with 383 additions and 506 deletions
+1
View File
@@ -1 +1,2 @@
build build
tmp
+14 -8
View File
@@ -4,23 +4,28 @@
#include <zephyr/logging/log.h> #include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(buttons, CONFIG_LOG_MAX_LEVEL); LOG_MODULE_REGISTER(buttons, CONFIG_LOG_MAX_LEVEL);
K_WORK_DELAYABLE_DEFINE(debounce_work_btn, debounce_cb);
#define DEBOUNCE_TIME_MS 100 #define DEBOUNCE_TIME_MS 100
/* Forward declarations for internal callbacks */
static void debounce_cb(struct k_work *work);
static void buttons_cb(const struct device *dev, struct gpio_callback *cb, uint32_t pins);
K_WORK_DELAYABLE_DEFINE(debounce_work_btn, debounce_cb);
static const struct gpio_dt_spec buttons[NR_BUTTONS] = { static const struct gpio_dt_spec buttons[NR_BUTTONS] = {
GPIO_DT_SPEC_GET_OR(DT_ALIAS(int_btn_1), gpios, {0}), GPIO_DT_SPEC_GET_OR(DT_ALIAS(int_btn_1), gpios, {0}),
GPIO_DT_SPEC_GET_OR(DT_ALIAS(int_btn_2), gpios, {0}), GPIO_DT_SPEC_GET_OR(DT_ALIAS(int_btn_2), gpios, {0}),
}; };
static struct gpio_callback buttons_cb_data[NR_BUTTONS]; static struct gpio_callback buttons_cb_data[NR_BUTTONS];
int buttons_init(void) { int buttons_init(void)
// BUTTON 1 {
gpio_pin_configure_dt(&buttons[BUTTON1], GPIO_INPUT); gpio_pin_configure_dt(&buttons[BUTTON1], GPIO_INPUT);
gpio_pin_interrupt_configure_dt(&buttons[BUTTON1], GPIO_INT_EDGE_TO_ACTIVE); gpio_pin_interrupt_configure_dt(&buttons[BUTTON1], GPIO_INT_EDGE_TO_ACTIVE);
gpio_init_callback(&buttons_cb_data[0], buttons_cb, BIT(buttons[BUTTON1].pin)); gpio_init_callback(&buttons_cb_data[0], buttons_cb, BIT(buttons[BUTTON1].pin));
gpio_add_callback(buttons[BUTTON1].port, &buttons_cb_data[0]); gpio_add_callback(buttons[BUTTON1].port, &buttons_cb_data[0]);
// BUTTON 2
gpio_pin_configure_dt(&buttons[BUTTON2], GPIO_INPUT); gpio_pin_configure_dt(&buttons[BUTTON2], GPIO_INPUT);
gpio_pin_interrupt_configure_dt(&buttons[BUTTON2], GPIO_INT_EDGE_TO_ACTIVE); gpio_pin_interrupt_configure_dt(&buttons[BUTTON2], GPIO_INT_EDGE_TO_ACTIVE);
gpio_init_callback(&buttons_cb_data[1], buttons_cb, BIT(buttons[BUTTON2].pin)); gpio_init_callback(&buttons_cb_data[1], buttons_cb, BIT(buttons[BUTTON2].pin));
@@ -29,15 +34,16 @@ int buttons_init(void) {
return 0; return 0;
} }
void debounce_cb(struct k_work *work) { static void debounce_cb(struct k_work *work)
{
if (gpio_pin_get_dt(&buttons[BUTTON1]) == GPIO_ACTIVE_HIGH || if (gpio_pin_get_dt(&buttons[BUTTON1]) == GPIO_ACTIVE_HIGH ||
gpio_pin_get_dt(&buttons[BUTTON2]) == GPIO_ACTIVE_HIGH) { gpio_pin_get_dt(&buttons[BUTTON2]) == GPIO_ACTIVE_HIGH) {
LOG_DBG("Callback"); LOG_DBG("Button active after debounce");
} }
} }
void buttons_cb(const struct device *dev, struct gpio_callback *cb, uint32_t pins) { static void buttons_cb(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
LOG_DBG("Button:"); {
if (!k_work_delayable_is_pending(&debounce_work_btn)) { if (!k_work_delayable_is_pending(&debounce_work_btn)) {
k_work_schedule(&debounce_work_btn, K_MSEC(DEBOUNCE_TIME_MS)); k_work_schedule(&debounce_work_btn, K_MSEC(DEBOUNCE_TIME_MS));
} }
-6
View File
@@ -1,8 +1,6 @@
#ifndef BUTTON_H #ifndef BUTTON_H
#define BUTTON_H #define BUTTON_H
#include <zephyr/drivers/gpio.h> #include <zephyr/drivers/gpio.h>
typedef enum { typedef enum {
@@ -12,9 +10,5 @@ typedef enum {
} buttons_e; } buttons_e;
int buttons_init(void); int buttons_init(void);
void buttons_cb(const struct device *dev, struct gpio_callback *cb, uint32_t pins);
void debounce_cb(struct k_work *work);
#endif // BUTTON_H #endif // BUTTON_H
+11 -15
View File
@@ -4,21 +4,19 @@
#include <zephyr/fs/nvs.h> #include <zephyr/fs/nvs.h>
#include <zephyr/storage/flash_map.h> #include <zephyr/storage/flash_map.h>
#define NVS_ID_CONFIG 1 #define NVS_ID_CONFIG 1
#define CONFIG_ID 0xDEADBEEF
#define CONFIG_VERSION 2
static struct nvs_fs nvs; static struct nvs_fs nvs;
static app_config_t ram_config; static app_config_t ram_config;
#define CONFIG_ID 0xDEADBEEF
#define CONFIG_VERSION 2
static const app_config_t default_config = { static const app_config_t default_config = {
.id = CONFIG_ID, .id = CONFIG_ID,
.version = CONFIG_VERSION, .version = CONFIG_VERSION,
.mode_config = { .mode_config = {
.phase_a_ms = (20 * 60 * 1000), .phase_a_ms = (20 * 60 * 1000),
.phase_a_ms = (20 * 1000), .phase_b_ms = (20 * 1000),
}, },
}; };
@@ -39,8 +37,11 @@ int config_init(void)
return rc; return rc;
} }
/* Load config from flash; fall back to defaults if missing or version mismatch */
ssize_t ret = nvs_read(&nvs, NVS_ID_CONFIG, &ram_config, sizeof(ram_config)); ssize_t ret = nvs_read(&nvs, NVS_ID_CONFIG, &ram_config, sizeof(ram_config));
if (ret != sizeof(ram_config) || ram_config.id != CONFIG_ID || ram_config.version != CONFIG_VERSION) { if (ret != sizeof(ram_config) ||
ram_config.id != CONFIG_ID ||
ram_config.version != CONFIG_VERSION) {
ram_config = default_config; ram_config = default_config;
nvs_write(&nvs, NVS_ID_CONFIG, &ram_config, sizeof(ram_config)); nvs_write(&nvs, NVS_ID_CONFIG, &ram_config, sizeof(ram_config));
} }
@@ -54,11 +55,6 @@ int config_save(const app_config_t *cfg)
return nvs_write(&nvs, NVS_ID_CONFIG, &ram_config, sizeof(ram_config)); return nvs_write(&nvs, NVS_ID_CONFIG, &ram_config, sizeof(ram_config));
} }
void config_update(void)
{
nvs_read(&nvs, NVS_ID_CONFIG, &ram_config, sizeof(ram_config));
}
void config_get(app_config_t *cfg) void config_get(app_config_t *cfg)
{ {
*cfg = ram_config; *cfg = ram_config;
+2 -3
View File
@@ -11,9 +11,8 @@ typedef struct {
struct mode_config mode_config; struct mode_config mode_config;
} app_config_t; } app_config_t;
int config_init(void); int config_init(void);
int config_save(const app_config_t *cfg); int config_save(const app_config_t *cfg);
void config_update(void);
void config_get(app_config_t *cfg); void config_get(app_config_t *cfg);
#endif /* CONFIG_H */ #endif /* CONFIG_H */
-50
View File
@@ -1,50 +0,0 @@
#include "mode.h"
#include "config.h"
#include <zephyr/shell/shell.h>
#include <stdlib.h>
static int cmd_start(const struct shell *sh, size_t argc, char **argv)
{
mode_start();
return 0;
}
static int cmd_stop(const struct shell *sh, size_t argc, char **argv)
{
mode_stop();
return 0;
}
static int cmd_restart(const struct shell *sh, size_t argc, char **argv)
{
mode_restart();
return 0;
}
/* mode init <phase_a_ms> <phase_b_ms> */
static int cmd_init(const struct shell *sh, size_t argc, char **argv)
{
app_config_t app_cfg;
config_get(&app_cfg);
app_cfg.mode_config.phase_a_ms = atoi(argv[1]);
app_cfg.mode_config.phase_b_ms = atoi(argv[2]);
config_save(&app_cfg);
mode_init();
mode_restart();
shell_print(sh, "Config saved. phase_a=%s ms, phase_b=%s ms. Restarting.", argv[1], argv[2]);
return 0;
}
SHELL_STATIC_SUBCMD_SET_CREATE(mode_cmds,
SHELL_CMD(start, NULL, "Start the mode thread.", cmd_start),
SHELL_CMD(stop, NULL, "Stop the mode thread.", cmd_stop),
SHELL_CMD(restart, NULL, "Restart the mode thread.", cmd_restart),
SHELL_CMD_ARG(init, NULL, "Set <phase_a_ms> <phase_b_ms>, save and restart.", cmd_init, 3, 0),
SHELL_SUBCMD_SET_END
);
SHELL_CMD_REGISTER(mode, &mode_cmds, "Mode control.", NULL);
+123
View File
@@ -0,0 +1,123 @@
// Debug shell commands: `debug mode/led/leds/imu`
// These are for development and testing; not intended for end users.
//
#include "mode.h"
#include "led.h"
#include "imu.h"
#include <zephyr/shell/shell.h>
#include <stdlib.h>
/* --- debug mode --- */
static int cmd_dbg_mode_start(const struct shell *sh, size_t argc, char **argv)
{
mode_start();
return 0;
}
static int cmd_dbg_mode_stop(const struct shell *sh, size_t argc, char **argv)
{
mode_stop();
return 0;
}
static int cmd_dbg_mode_restart(const struct shell *sh, size_t argc, char **argv)
{
mode_restart();
return 0;
}
SHELL_STATIC_SUBCMD_SET_CREATE(debug_mode_cmds,
SHELL_CMD(start, NULL, "Start mode thread.", cmd_dbg_mode_start),
SHELL_CMD(stop, NULL, "Stop mode thread.", cmd_dbg_mode_stop),
SHELL_CMD(restart, NULL, "Restart mode thread.", cmd_dbg_mode_restart),
SHELL_SUBCMD_SET_END
);
/* --- debug led (PWM bar) --- */
static int cmd_dbg_led_fade(const struct shell *sh, size_t argc, char **argv)
{
if (argc != 2) { shell_error(sh, "Usage: debug led fade <ms>"); return -EINVAL; }
return led_fade(atoi(argv[1]));
}
static int cmd_dbg_led_progress(const struct shell *sh, size_t argc, char **argv)
{
if (argc != 2) { shell_error(sh, "Usage: debug led progress <0-100>"); return -EINVAL; }
return led_set_progress(atoi(argv[1]) / 100.0f);
}
SHELL_STATIC_SUBCMD_SET_CREATE(debug_led_cmds,
SHELL_CMD(fade, NULL, "Fade PWM bar over <ms>.", cmd_dbg_led_fade),
SHELL_CMD(progress, NULL, "Set PWM bar progress <0-100>.", cmd_dbg_led_progress),
SHELL_SUBCMD_SET_END
);
/* --- debug leds (addressable strip) --- */
static int cmd_dbg_leds_all(const struct shell *sh, size_t argc, char **argv)
{
if (argc != 4) { shell_error(sh, "Usage: debug leds all <r> <g> <b> (0-255)"); return -EINVAL; }
leds_set_all(atoi(argv[1]) / 255.0f, atoi(argv[2]) / 255.0f, atoi(argv[3]) / 255.0f);
return leds_update();
}
static int cmd_dbg_leds_clear(const struct shell *sh, size_t argc, char **argv)
{
return leds_clear();
}
static int cmd_dbg_leds_fade(const struct shell *sh, size_t argc, char **argv)
{
if (argc != 5) { shell_error(sh, "Usage: debug leds fade <ms> <r> <g> <b> (0-255)"); return -EINVAL; }
return leds_fade(atoi(argv[1]),
atoi(argv[2]) / 255.0f,
atoi(argv[3]) / 255.0f,
atoi(argv[4]) / 255.0f);
}
static int cmd_dbg_leds_fade_to(const struct shell *sh, size_t argc, char **argv)
{
if (argc != 5) { shell_error(sh, "Usage: debug leds fade_to <ms> <r> <g> <b> (0-255, -1 to keep)"); return -EINVAL; }
return leds_fade_to(atoi(argv[1]),
atoi(argv[2]) < 0 ? -1.0f : atoi(argv[2]) / 255.0f,
atoi(argv[3]) < 0 ? -1.0f : atoi(argv[3]) / 255.0f,
atoi(argv[4]) < 0 ? -1.0f : atoi(argv[4]) / 255.0f);
}
SHELL_STATIC_SUBCMD_SET_CREATE(debug_leds_cmds,
SHELL_CMD(all, NULL, "Set all LEDs <r> <g> <b>.", cmd_dbg_leds_all),
SHELL_CMD(clear, NULL, "Clear all LEDs.", cmd_dbg_leds_clear),
SHELL_CMD(fade, NULL, "Fade in/out <ms> <r> <g> <b>.", cmd_dbg_leds_fade),
SHELL_CMD(fade_to, NULL, "Fade to color <ms> <r> <g> <b>.", cmd_dbg_leds_fade_to),
SHELL_SUBCMD_SET_END
);
/* --- debug imu --- */
static int cmd_dbg_imu_read(const struct shell *sh, size_t argc, char **argv)
{
struct accel_data_t data;
imu_read(&data);
shell_print(sh, "x=%d y=%d z=%d", data.x, data.y, data.z);
return 0;
}
SHELL_STATIC_SUBCMD_SET_CREATE(debug_imu_cmds,
SHELL_CMD(read, NULL, "Read accelerometer axes.", cmd_dbg_imu_read),
SHELL_SUBCMD_SET_END
);
/* --- top-level debug command --- */
SHELL_STATIC_SUBCMD_SET_CREATE(debug_cmds,
SHELL_CMD(mode, &debug_mode_cmds, "Mode thread control.", NULL),
SHELL_CMD(led, &debug_led_cmds, "PWM LED bar control.", NULL),
SHELL_CMD(leds, &debug_leds_cmds, "Addressable LED control.", NULL),
SHELL_CMD(imu, &debug_imu_cmds, "IMU read.", NULL),
SHELL_SUBCMD_SET_END
);
SHELL_CMD_REGISTER(debug, &debug_cmds, "Debug commands.", NULL);
+50 -88
View File
@@ -7,13 +7,12 @@
#include <zephyr/drivers/i2c.h> #include <zephyr/drivers/i2c.h>
LOG_MODULE_REGISTER(imu, CONFIG_LOG_MAX_LEVEL); LOG_MODULE_REGISTER(imu, CONFIG_LOG_MAX_LEVEL);
K_WORK_DELAYABLE_DEFINE(debounce_work_imu, debounce_cb);
#define DEBOUNCE_TIME_MS 100 #define DEBOUNCE_TIME_MS 100
#define DOUBLE_TAP_TIME_MS 500 #define DOUBLE_TAP_TIME_MS 500
/* Starting register for X-axis data (e.g., OUT_X_L register) */ /* Starting register for X-axis data */
#define ACCEL_REG_OUT_X_L 0x3B #define ACCEL_REG_OUT_X_L 0x3B
static const uint8_t i2c_address = 0b1101001; static const uint8_t i2c_address = 0b1101001;
@@ -23,72 +22,48 @@ static const struct device *const i2c_dev = DEVICE_DT_GET(DT_ALIAS(i2c_1));
static uint32_t last_tap = 0; static uint32_t last_tap = 0;
void imu_reset() { /* Forward declarations */
const uint8_t PWR_MGMT_1[2] = {0x6B, (uint8_t)(1 << 7)}; static void debounce_cb(struct k_work *work);
i2c_write(i2c_dev, PWR_MGMT_1, sizeof(PWR_MGMT_1), i2c_address); static void imu_cb(const struct device *dev, struct gpio_callback *cb, uint32_t pins);
k_sleep(K_MSEC(100));
} K_WORK_DELAYABLE_DEFINE(debounce_work_imu, debounce_cb);
int imu_init() { int imu_init(void)
{
if (!device_is_ready(i2c_dev)) { if (!device_is_ready(i2c_dev)) {
LOG_ERR("I2C device %s is not ready.\n", i2c_dev->name); LOG_ERR("I2C device %s is not ready", i2c_dev->name);
return 0; return -ENODEV;
} }
// imu_reset(); /* Power management: wake all axes */
const uint8_t PWR_MGMT_1[2] = {0x6B, 0x00};
const uint8_t PWR_MGMT_2[2] = {0x6C, 0x00};
// Ensure that Accelerometer is running /* Accelerometer: ±16g, no DLPF */
const uint8_t PWR_MGMT_1[2] = {0x6B, 0x00};
const uint8_t PWR_MGMT_2[2] = {0x6C, 0x00};
// Accelerometer Configuration
const uint8_t ACCEL_CONFIG_1[2] = {0x1C, 0b00011000}; const uint8_t ACCEL_CONFIG_1[2] = {0x1C, 0b00011000};
const uint8_t ACCEL_CONFIG_2[2] = {0x1D, 0b00000000}; const uint8_t ACCEL_CONFIG_2[2] = {0x1D, 0b00000000};
// Enable Motion Interrupt /* Enable wake-on-motion interrupt */
const uint8_t INT_ENABLE[2] = {0x38, 0b00100000}; const uint8_t INT_ENABLE[2] = {0x38, 0b00100000};
const uint8_t ACCEL_WOM_Z_THR[2]= {0x22, 0xff};
const uint8_t ACCEL_INTEL_CTRL[2]= {0x69, 0xc0};
// Set Motion Threshold /* Sample rate divider and low-power cycle mode */
const uint8_t ACCEL_WOM_X_THR[2] = {0x20, 0xff}; const uint8_t SMPLRT_DIV[2] = {0x19, 0x00};
const uint8_t ACCEL_WOM_Y_THR[2] = {0x21, 0x8f}; const uint8_t PWR_MGMT_1_LP[2] = {0x6B, 0x20};
const uint8_t ACCEL_WOM_Z_THR[2] = {0x22, 0xff};
// Set Interrupt Mode & Enable Accelerometer Hardware Intelligence i2c_write(i2c_dev, PWR_MGMT_1, sizeof(PWR_MGMT_1), i2c_address); k_sleep(K_MSEC(1));
const uint8_t ACCEL_INTEL_CTRL[2] = {0x69, 0xc0}; i2c_write(i2c_dev, PWR_MGMT_2, sizeof(PWR_MGMT_2), i2c_address); k_sleep(K_MSEC(1));
i2c_write(i2c_dev, ACCEL_CONFIG_1, sizeof(ACCEL_CONFIG_1), i2c_address); k_sleep(K_MSEC(1));
i2c_write(i2c_dev, ACCEL_CONFIG_2, sizeof(ACCEL_CONFIG_2), i2c_address); k_sleep(K_MSEC(1));
i2c_write(i2c_dev, INT_ENABLE, sizeof(INT_ENABLE), i2c_address); k_sleep(K_MSEC(1));
i2c_write(i2c_dev, ACCEL_WOM_Z_THR, sizeof(ACCEL_WOM_Z_THR), i2c_address); k_sleep(K_MSEC(1));
i2c_write(i2c_dev, ACCEL_INTEL_CTRL,sizeof(ACCEL_INTEL_CTRL),i2c_address); k_sleep(K_MSEC(1));
i2c_write(i2c_dev, SMPLRT_DIV, sizeof(SMPLRT_DIV), i2c_address); k_sleep(K_MSEC(1));
i2c_write(i2c_dev, PWR_MGMT_1_LP, sizeof(PWR_MGMT_1_LP), i2c_address); k_sleep(K_MSEC(100));
// Set Frequency of Wake-Up gpio_pin_configure_dt(&imu_int, GPIO_INPUT);
const uint8_t SMPLRT_DIV[2] = {0x19, 0x00}; gpio_pin_interrupt_configure_dt(&imu_int, GPIO_INT_EDGE_TO_ACTIVE);
// Enable Cycle Mode (Accelerometer Low-Power Mode)
const uint8_t PWR_MGMT_1_A[2] = {0x6B, 0x20};
int ret;
i2c_write(i2c_dev, PWR_MGMT_1, sizeof(PWR_MGMT_1), i2c_address);
k_sleep(K_MSEC(1));
i2c_write(i2c_dev, PWR_MGMT_2, sizeof(PWR_MGMT_2), i2c_address);
k_sleep(K_MSEC(1));
i2c_write(i2c_dev, ACCEL_CONFIG_1, sizeof(ACCEL_CONFIG_1), i2c_address);
k_sleep(K_MSEC(1));
i2c_write(i2c_dev, ACCEL_CONFIG_2, sizeof(ACCEL_CONFIG_2), i2c_address);
k_sleep(K_MSEC(1));
i2c_write(i2c_dev, INT_ENABLE, sizeof(INT_ENABLE), i2c_address);
k_sleep(K_MSEC(1));
// // i2c_write(i2c_dev, ACCEL_WOM_X_THR, sizeof(ACCEL_WOM_X_THR), i2c_address);
// // k_sleep(K_MSEC(1));
// i2c_write(i2c_dev, ACCEL_WOM_Y_THR, sizeof(ACCEL_WOM_Y_THR), i2c_address);
// k_sleep(K_MSEC(1));
i2c_write(i2c_dev, ACCEL_WOM_Z_THR, sizeof(ACCEL_WOM_Z_THR), i2c_address);
k_sleep(K_MSEC(1));
i2c_write(i2c_dev, ACCEL_INTEL_CTRL, sizeof(ACCEL_INTEL_CTRL), i2c_address);
k_sleep(K_MSEC(1));
i2c_write(i2c_dev, SMPLRT_DIV, sizeof(SMPLRT_DIV), i2c_address);
k_sleep(K_MSEC(1));
i2c_write(i2c_dev, PWR_MGMT_1_A, sizeof(PWR_MGMT_1_A), i2c_address);
k_sleep(K_MSEC(100));
gpio_pin_configure_dt(&(imu_int), GPIO_INPUT);
gpio_pin_interrupt_configure_dt(&(imu_int), GPIO_INT_EDGE_TO_ACTIVE);
gpio_init_callback(&imu_cb_data, imu_cb, BIT(imu_int.pin)); gpio_init_callback(&imu_cb_data, imu_cb, BIT(imu_int.pin));
gpio_add_callback(imu_int.port, &imu_cb_data); gpio_add_callback(imu_int.port, &imu_cb_data);
@@ -97,52 +72,39 @@ int imu_init() {
return 0; return 0;
} }
void imu_read(struct accel_data_t *buf) { void imu_read(struct accel_data_t *buf)
uint8_t raw_accel_data[6]; {
uint8_t raw[6];
// LIGHT
uint16_t reg = ACCEL_REG_OUT_X_L; uint16_t reg = ACCEL_REG_OUT_X_L;
/* Write register address, then read consecutive data bytes */ int ret = i2c_write_read(i2c_dev, i2c_address, &reg, sizeof(reg), raw, sizeof(raw));
int ret = i2c_write_read(i2c_dev,
i2c_address,
&reg,
sizeof(reg),
raw_accel_data,
sizeof(raw_accel_data));
if (ret) { if (ret) {
printk("Error: I2C burst read failed (%d)\n", ret); LOG_ERR("I2C burst read failed (%d)", ret);
} else { return;
/* Combine low and high bytes for each axis */
buf->x = (int16_t)((raw_accel_data[1] << 8) | raw_accel_data[0]);
buf->y = (int16_t)((raw_accel_data[3] << 8) | raw_accel_data[2]);
buf->z = (int16_t)((raw_accel_data[5] << 8) | raw_accel_data[4]);
} }
buf->x = (int16_t)((raw[1] << 8) | raw[0]);
buf->y = (int16_t)((raw[3] << 8) | raw[2]);
buf->z = (int16_t)((raw[5] << 8) | raw[4]);
} }
static void debounce_cb(struct k_work *work) { static void debounce_cb(struct k_work *work)
{
if (gpio_pin_get_dt(&imu_int) == GPIO_ACTIVE_HIGH) { if (gpio_pin_get_dt(&imu_int) == GPIO_ACTIVE_HIGH) {
if (k_uptime_get() - last_tap > DOUBLE_TAP_TIME_MS) { if (k_uptime_get() - last_tap > DOUBLE_TAP_TIME_MS) {
LOG_INF("Tap"); LOG_INF("Tap");
} } else {
else {
LOG_INF("Double tap"); LOG_INF("Double tap");
struct button_msg_t msg; struct button_msg_t msg = { .button = IMU, .function = DOUBLE_TAP };
msg.button = IMU;
msg.function = DOUBLE_TAP;
zbus_chan_pub(&buttons_data_chan, &msg, K_NO_WAIT); zbus_chan_pub(&buttons_data_chan, &msg, K_NO_WAIT);
} }
last_tap = k_uptime_get(); last_tap = k_uptime_get();
} }
} }
static void imu_cb(const struct device *dev, struct gpio_callback *cb, uint32_t pins) { static void imu_cb(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
{
/* Check if the work item is already running */ if (!k_work_delayable_is_pending(&debounce_work_imu)) {
if (k_work_delayable_is_pending(&debounce_work_imu)) {
/* Do nothing, as the work item is already running */
} else {
k_work_schedule(&debounce_work_imu, K_MSEC(DEBOUNCE_TIME_MS)); k_work_schedule(&debounce_work_imu, K_MSEC(DEBOUNCE_TIME_MS));
} }
} }
+1 -7
View File
@@ -3,19 +3,13 @@
#include <zephyr/drivers/gpio.h> #include <zephyr/drivers/gpio.h>
struct accel_data_t { struct accel_data_t {
int16_t x; int16_t x;
int16_t y; int16_t y;
int16_t z; int16_t z;
}; };
int imu_init(void);
int imu_init();
void imu_read(struct accel_data_t *buf); void imu_read(struct accel_data_t *buf);
static void imu_cb(const struct device *dev, struct gpio_callback *cb, uint32_t pins);
static void debounce_cb(struct k_work *work);
#endif // IMU_H #endif // IMU_H
+90 -120
View File
@@ -1,7 +1,5 @@
// LOCAL
#include "led.h" #include "led.h"
// ZEPHYR
#include <zephyr/kernel.h> #include <zephyr/kernel.h>
#include <zephyr/device.h> #include <zephyr/device.h>
#include <zephyr/logging/log.h> #include <zephyr/logging/log.h>
@@ -10,20 +8,20 @@
LOG_MODULE_REGISTER(leds, LOG_LEVEL_INF); LOG_MODULE_REGISTER(leds, LOG_LEVEL_INF);
#define STRIP_NODE DT_ALIAS(led_strip) #define STRIP_NODE DT_ALIAS(led_strip)
#define STRIP_NUM_PIXELS DT_PROP(STRIP_NODE, chain_length) #define STRIP_NUM_PIXELS DT_PROP(STRIP_NODE, chain_length)
#define STRIP_MAX_BRIGHTNESS 255 #define STRIP_MAX_BRIGHTNESS 255
static const struct device *const strip = DEVICE_DT_GET(STRIP_NODE); static const struct device *const strip = DEVICE_DT_GET(STRIP_NODE);
static struct led_rgb pixels[STRIP_NUM_PIXELS]; static struct led_rgb pixels[STRIP_NUM_PIXELS];
// Saved RGB state for the LED strip /* Saved strip color for fade_to interpolation */
static float saved_r = 0.0f; static float saved_r = 0.0f;
static float saved_g = 0.0f; static float saved_g = 0.0f;
static float saved_b = 0.0f; static float saved_b = 0.0f;
#define NR_LEDS 8 #define NR_LEDS 8
#define PWM_RESOLUTION 255 #define PWM_RESOLUTION 255
static const struct pwm_dt_spec led1 = PWM_DT_SPEC_GET(DT_ALIAS(pwm_led1)); static const struct pwm_dt_spec led1 = PWM_DT_SPEC_GET(DT_ALIAS(pwm_led1));
static const struct pwm_dt_spec led2 = PWM_DT_SPEC_GET(DT_ALIAS(pwm_led2)); static const struct pwm_dt_spec led2 = PWM_DT_SPEC_GET(DT_ALIAS(pwm_led2));
@@ -34,228 +32,200 @@ static const struct pwm_dt_spec led6 = PWM_DT_SPEC_GET(DT_ALIAS(pwm_led6));
static const struct pwm_dt_spec led7 = PWM_DT_SPEC_GET(DT_ALIAS(pwm_led7)); static const struct pwm_dt_spec led7 = PWM_DT_SPEC_GET(DT_ALIAS(pwm_led7));
static const struct pwm_dt_spec led8 = PWM_DT_SPEC_GET(DT_ALIAS(pwm_led8)); static const struct pwm_dt_spec led8 = PWM_DT_SPEC_GET(DT_ALIAS(pwm_led8));
static const struct pwm_dt_spec *leds[NR_LEDS] = {&led1, &led2, &led3, &led4, &led5, &led6, &led7, &led8}; static const struct pwm_dt_spec *leds[NR_LEDS] = {
&led1, &led2, &led3, &led4, &led5, &led6, &led7, &led8
};
static int set_pwm(const struct pwm_dt_spec *dev, uint32_t value, uint32_t max_brightness)
int set_pwm(const struct pwm_dt_spec *dev, uint32_t value, uint32_t max_brightness) { {
if ((value <= max_brightness) && (max_brightness > 0)) { if (value <= max_brightness && max_brightness > 0) {
uint32_t pulse_width_ns = value * (dev->period / max_brightness); uint32_t pulse_width_ns = value * (dev->period / max_brightness);
int ret = pwm_set_pulse_dt(dev, pulse_width_ns); return pwm_set_pulse_dt(dev, pulse_width_ns);
return ret;
} }
return -1; return -EINVAL;
} }
int led_init(void) { int led_init(void)
// Checking if devices are ready {
for (int i = 0; i < NR_LEDS; i++) { for (int i = 0; i < NR_LEDS; i++) {
if (!device_is_ready(leds[i]->dev)) { if (!device_is_ready(leds[i]->dev)) {
LOG_ERR("PWM LEDs not ready"); LOG_ERR("PWM LED %d not ready", i);
return -ENODEV; return -ENODEV;
} }
} }
LOG_INF("PWM LEDs initialized"); LOG_INF("PWM LEDs initialized");
if (!device_is_ready(strip)) { if (!device_is_ready(strip)) {
LOG_ERR("LED strip device not ready"); LOG_ERR("LED strip device not ready");
return -ENODEV; return -ENODEV;
} }
LOG_INF("LED strip initialized with %d pixels", STRIP_NUM_PIXELS); LOG_INF("LED strip initialized with %d pixels", STRIP_NUM_PIXELS);
return 0; return 0;
} }
int led_fade(uint32_t duration) { /* Fade all PWM LEDs in then out over duration ms */
uint32_t step_duration = (duration * 1000) / (PWM_RESOLUTION * 2); int led_fade(uint32_t duration)
{
uint32_t step = (duration * 1000) / (PWM_RESOLUTION * 2);
for (int i = 0; i < PWM_RESOLUTION; i++) { for (int i = 0; i < PWM_RESOLUTION; i++) {
for (int j = 0; j < NR_LEDS; j++) { for (int j = 0; j < NR_LEDS; j++) { set_pwm(leds[j], i, PWM_RESOLUTION); }
set_pwm(leds[j], i, PWM_RESOLUTION); k_sleep(K_USEC(step));
}
k_sleep(K_USEC(step_duration));
} }
for (int i = 0; i < PWM_RESOLUTION; i++) { for (int i = 0; i < PWM_RESOLUTION; i++) {
for (int j = 0; j < NR_LEDS; j++) { for (int j = 0; j < NR_LEDS; j++) { set_pwm(leds[j], PWM_RESOLUTION - i - 1, PWM_RESOLUTION); }
set_pwm(leds[j], (PWM_RESOLUTION - i - 1), PWM_RESOLUTION); k_sleep(K_USEC(step));
}
k_sleep(K_USEC(step_duration));
} }
return 0;
return 0;
} }
int led_fade_in(uint32_t duration) { int led_fade_in(uint32_t duration)
uint32_t step_duration = (duration * 1000) / (PWM_RESOLUTION); {
uint32_t step = (duration * 1000) / PWM_RESOLUTION;
for (int i = 0; i < PWM_RESOLUTION; i++) { for (int i = 0; i < PWM_RESOLUTION; i++) {
for (int j = 0; j < NR_LEDS; j++) { for (int j = 0; j < NR_LEDS; j++) { set_pwm(leds[j], i, PWM_RESOLUTION); }
set_pwm(leds[j], i, PWM_RESOLUTION); k_sleep(K_USEC(step));
}
k_sleep(K_USEC(step_duration));
} }
return 0; return 0;
} }
int led_fade_out(uint32_t duration) { int led_fade_out(uint32_t duration)
uint32_t step_duration = (duration * 1000) / (PWM_RESOLUTION); {
uint32_t step = (duration * 1000) / PWM_RESOLUTION;
for (int i = 0; i < PWM_RESOLUTION; i++) { for (int i = 0; i < PWM_RESOLUTION; i++) {
for (int j = 0; j < NR_LEDS; j++) { for (int j = 0; j < NR_LEDS; j++) { set_pwm(leds[j], PWM_RESOLUTION - i - 1, PWM_RESOLUTION); }
set_pwm(leds[j], (PWM_RESOLUTION - i - 1), PWM_RESOLUTION); k_sleep(K_USEC(step));
}
k_sleep(K_USEC(step_duration));
} }
return 0;
return 0;
} }
int led_set_progress(float progress) { /* Light N+fraction LEDs to represent progress [0.0, 1.0] */
uint32_t total_progress = (progress * NR_LEDS * PWM_RESOLUTION); int led_set_progress(float progress)
{
uint32_t total = (uint32_t)(progress * NR_LEDS * PWM_RESOLUTION);
for (int i = 0; i < NR_LEDS; i++) { for (int i = 0; i < NR_LEDS; i++) {
if (total_progress > PWM_RESOLUTION) { if (total > PWM_RESOLUTION) {
set_pwm(leds[i], PWM_RESOLUTION, PWM_RESOLUTION); set_pwm(leds[i], PWM_RESOLUTION, PWM_RESOLUTION);
total_progress -= PWM_RESOLUTION; total -= PWM_RESOLUTION;
} } else {
else { set_pwm(leds[i], total, PWM_RESOLUTION);
set_pwm(leds[i], total_progress, PWM_RESOLUTION); total = 0;
total_progress = 0;
} }
} }
return 0;
} }
/* --- Addressable LED strip --- */
/* LED strip */ int leds_set_color(uint8_t led_index, float r, float g, float b)
{
int leds_set_color(uint8_t led_index, float r, float g, float b) {
if (led_index >= STRIP_NUM_PIXELS) { if (led_index >= STRIP_NUM_PIXELS) {
LOG_ERR("LED index %d out of range (max %d)", led_index, STRIP_NUM_PIXELS - 1); LOG_ERR("LED index %d out of range (max %d)", led_index, STRIP_NUM_PIXELS - 1);
return -EINVAL; return -EINVAL;
} }
pixels[led_index].r = r * STRIP_MAX_BRIGHTNESS; pixels[led_index].r = r * STRIP_MAX_BRIGHTNESS;
pixels[led_index].g = g * STRIP_MAX_BRIGHTNESS; pixels[led_index].g = g * STRIP_MAX_BRIGHTNESS;
pixels[led_index].b = b * STRIP_MAX_BRIGHTNESS; pixels[led_index].b = b * STRIP_MAX_BRIGHTNESS;
return 0; return 0;
} }
int leds_set_all(float r, float g, float b) { int leds_set_all(float r, float g, float b)
{
for (int i = 0; i < STRIP_NUM_PIXELS; i++) { for (int i = 0; i < STRIP_NUM_PIXELS; i++) {
pixels[i].r = r * STRIP_MAX_BRIGHTNESS; pixels[i].r = r * STRIP_MAX_BRIGHTNESS;
pixels[i].g = g * STRIP_MAX_BRIGHTNESS; pixels[i].g = g * STRIP_MAX_BRIGHTNESS;
pixels[i].b = b * STRIP_MAX_BRIGHTNESS; pixels[i].b = b * STRIP_MAX_BRIGHTNESS;
} }
saved_r = r; saved_r = r;
saved_g = g; saved_g = g;
saved_b = b; saved_b = b;
return 0; return 0;
} }
int leds_update(void) { int leds_update(void)
{
int ret = led_strip_update_rgb(strip, pixels, STRIP_NUM_PIXELS); int ret = led_strip_update_rgb(strip, pixels, STRIP_NUM_PIXELS);
if (ret) { if (ret) {
LOG_ERR("Failed to update LED strip: %d", ret); LOG_ERR("Failed to update LED strip: %d", ret);
return ret;
} }
return ret;
return 0;
} }
int leds_clear(void) { int leds_clear(void)
{
return leds_set_all(0, 0, 0) || leds_update(); return leds_set_all(0, 0, 0) || leds_update();
} }
int leds_fade(uint32_t duration, float r, float g, float b)
int leds_fade(uint32_t duration, float r, float g, float b) { {
uint32_t step_duration = (duration * 1000) / (STRIP_MAX_BRIGHTNESS * 2); uint32_t step = (duration * 1000) / (STRIP_MAX_BRIGHTNESS * 2);
for (int i = 0; i < STRIP_MAX_BRIGHTNESS; i++) { for (int i = 0; i < STRIP_MAX_BRIGHTNESS; i++) {
float value = (float)i / STRIP_MAX_BRIGHTNESS; float v = (float)i / STRIP_MAX_BRIGHTNESS;
leds_set_all((value * r), (value * g), (value * b)); leds_set_all(v * r, v * g, v * b);
leds_update(); leds_update();
k_sleep(K_USEC(step_duration)); k_sleep(K_USEC(step));
} }
for (int i = STRIP_MAX_BRIGHTNESS - 1; i >= 0; i--) { for (int i = STRIP_MAX_BRIGHTNESS - 1; i >= 0; i--) {
float value = (float)i / STRIP_MAX_BRIGHTNESS; float v = (float)i / STRIP_MAX_BRIGHTNESS;
leds_set_all((value * r), (value * g), (value * b)); leds_set_all(v * r, v * g, v * b);
leds_update(); leds_update();
k_sleep(K_USEC(step_duration)); k_sleep(K_USEC(step));
} }
saved_r = 0.0f; saved_r = 0.0f;
saved_g = 0.0f; saved_g = 0.0f;
saved_b = 0.0f; saved_b = 0.0f;
return 0; return 0;
} }
int leds_fade_in(uint32_t duration, float r, float g, float b) { int leds_fade_in(uint32_t duration, float r, float g, float b)
uint32_t step_duration = (duration * 1000) / (STRIP_MAX_BRIGHTNESS); {
uint32_t step = (duration * 1000) / STRIP_MAX_BRIGHTNESS;
for (int i = 0; i < STRIP_MAX_BRIGHTNESS; i++) { for (int i = 0; i < STRIP_MAX_BRIGHTNESS; i++) {
float value = (float)i / STRIP_MAX_BRIGHTNESS; float v = (float)i / STRIP_MAX_BRIGHTNESS;
leds_set_all((value * r), (value * g), (value * b)); leds_set_all(v * r, v * g, v * b);
leds_update(); leds_update();
k_sleep(K_USEC(step_duration)); k_sleep(K_USEC(step));
} }
saved_r = r; saved_g = g; saved_b = b;
saved_r = r;
saved_g = g;
saved_b = b;
return 0; return 0;
} }
int leds_fade_out(uint32_t duration, float r, float g, float b) { int leds_fade_out(uint32_t duration, float r, float g, float b)
uint32_t step_duration = (duration * 1000) / (STRIP_MAX_BRIGHTNESS); {
uint32_t step = (duration * 1000) / STRIP_MAX_BRIGHTNESS;
for (int i = STRIP_MAX_BRIGHTNESS - 1; i >= 0; i--) { for (int i = STRIP_MAX_BRIGHTNESS - 1; i >= 0; i--) {
float value = (float)i / STRIP_MAX_BRIGHTNESS; float v = (float)i / STRIP_MAX_BRIGHTNESS;
leds_set_all((value * r), (value * g), (value * b)); leds_set_all(v * r, v * g, v * b);
leds_update(); leds_update();
k_sleep(K_USEC(step_duration)); k_sleep(K_USEC(step));
} }
saved_r = 0.0f; saved_g = 0.0f; saved_b = 0.0f;
saved_r = 0.0f;
saved_g = 0.0f;
saved_b = 0.0f;
return 0; return 0;
} }
int leds_fade_to(uint32_t duration, float r, float g, float b) { /* Fade from current saved color to target; pass -1.0 to keep a channel unchanged */
// Resolve target channels — -1 means keep the saved value int leds_fade_to(uint32_t duration, float r, float g, float b)
{
float target_r = (r < 0.0f) ? saved_r : r; float target_r = (r < 0.0f) ? saved_r : r;
float target_g = (g < 0.0f) ? saved_g : g; float target_g = (g < 0.0f) ? saved_g : g;
float target_b = (b < 0.0f) ? saved_b : b; float target_b = (b < 0.0f) ? saved_b : b;
float from_r = saved_r; float from_r = saved_r, from_g = saved_g, from_b = saved_b;
float from_g = saved_g; uint32_t step = (duration * 1000) / STRIP_MAX_BRIGHTNESS;
float from_b = saved_b;
uint32_t step_duration = (duration * 1000) / STRIP_MAX_BRIGHTNESS;
for (int i = 0; i <= STRIP_MAX_BRIGHTNESS; i++) { for (int i = 0; i <= STRIP_MAX_BRIGHTNESS; i++) {
float t = (float)i / STRIP_MAX_BRIGHTNESS; float t = (float)i / STRIP_MAX_BRIGHTNESS;
leds_set_all( leds_set_all(from_r + t * (target_r - from_r),
from_r + t * (target_r - from_r), from_g + t * (target_g - from_g),
from_g + t * (target_g - from_g), from_b + t * (target_b - from_b));
from_b + t * (target_b - from_b)
);
leds_update(); leds_update();
k_sleep(K_USEC(step_duration)); k_sleep(K_USEC(step));
} }
// leds_set_all already saved the final color, but set explicitly for clarity
saved_r = target_r; saved_r = target_r;
saved_g = target_g; saved_g = target_g;
saved_b = target_b; saved_b = target_b;
return 0; return 0;
} }
+1 -3
View File
@@ -1,15 +1,14 @@
#ifndef LED_H #ifndef LED_H
#define LED_H #define LED_H
#include <stdint.h> #include <stdint.h>
int led_init(void); int led_init(void);
int led_fade(uint32_t duration); int led_fade(uint32_t duration);
int led_fade_in(uint32_t duration); int led_fade_in(uint32_t duration);
int led_fade_out(uint32_t duration); int led_fade_out(uint32_t duration);
int led_set_progress(float progress); int led_set_progress(float progress);
int leds_set_color(uint8_t led_index, float r, float g, float b); int leds_set_color(uint8_t led_index, float r, float g, float b);
int leds_set_all(float r, float g, float b); int leds_set_all(float r, float g, float b);
int leds_update(void); int leds_update(void);
@@ -19,5 +18,4 @@ int leds_fade_in(uint32_t duration, float r, float g, float b);
int leds_fade_out(uint32_t duration, float r, float g, float b); int leds_fade_out(uint32_t duration, float r, float g, float b);
int leds_fade_to(uint32_t duration, float r, float g, float b); int leds_fade_to(uint32_t duration, float r, float g, float b);
#endif // LED_H #endif // LED_H
-65
View File
@@ -1,65 +0,0 @@
#include <zephyr/shell/shell.h>
#include "led.h"
/* single led */
static int cmd_led_fade(const struct shell *sh, size_t argc, char **argv)
{
if (argc != 2) { shell_error(sh, "Usage: led fade <ms>"); return -EINVAL; }
return led_fade(atoi(argv[1]));
}
static int cmd_led_progress(const struct shell *sh, size_t argc, char **argv)
{
if (argc != 2) { shell_error(sh, "Usage: led progress <0-100>"); return -EINVAL; }
return led_set_progress(atoi(argv[1]) / 100.0f);
}
SHELL_STATIC_SUBCMD_SET_CREATE(led_cmds,
SHELL_CMD(fade, NULL, "Fade over <ms>", cmd_led_fade),
SHELL_CMD(progress, NULL, "Set progress <0.0-1.0>", cmd_led_progress),
SHELL_SUBCMD_SET_END
);
SHELL_CMD_REGISTER(led, &led_cmds, "Single LED commands", NULL);
/* addressable leds */
static int cmd_leds_all(const struct shell *sh, size_t argc, char **argv)
{
if (argc != 4) { shell_error(sh, "Usage: leds all <r> <g> <b> (0-255)"); return -EINVAL; }
leds_set_all(atoi(argv[1]) / 255.0f, atoi(argv[2]) / 255.0f, atoi(argv[3]) / 255.0f);
return leds_update();
}
static int cmd_leds_fade(const struct shell *sh, size_t argc, char **argv)
{
if (argc != 5) { shell_error(sh, "Usage: leds fade <ms> <r> <g> <b> (0-255)"); return -EINVAL; }
return leds_fade(atoi(argv[1]),
atoi(argv[2]) / 255.0f,
atoi(argv[3]) / 255.0f,
atoi(argv[4]) / 255.0f);
}
static int cmd_leds_clear(const struct shell *sh, size_t argc, char **argv)
{
return leds_clear();
}
static int cmd_leds_fade_to(const struct shell *sh, size_t argc, char **argv)
{
if (argc != 5) { shell_error(sh, "Usage: leds fade_to <ms> <r> <g> <b> (0-255, -1 to keep)"); return -EINVAL; }
return leds_fade_to(atoi(argv[1]),
atoi(argv[2]) < 0 ? -1.0f : atoi(argv[2]) / 255.0f,
atoi(argv[3]) < 0 ? -1.0f : atoi(argv[3]) / 255.0f,
atoi(argv[4]) < 0 ? -1.0f : atoi(argv[4]) / 255.0f);
}
SHELL_STATIC_SUBCMD_SET_CREATE(leds_cmds,
SHELL_CMD(all, NULL, "Set all <r> <g> <b>", cmd_leds_all),
SHELL_CMD(clear, NULL, "Clear all", cmd_leds_clear),
SHELL_CMD(fade, NULL, "Fade in/out <ms> <r> <g> <b>", cmd_leds_fade),
SHELL_CMD(fade_to, NULL, "Fade to color <ms> <r> <g> <b>", cmd_leds_fade_to),
SHELL_SUBCMD_SET_END
);
SHELL_CMD_REGISTER(leds, &leds_cmds, "Addressable LED commands", NULL);
+11 -11
View File
@@ -1,15 +1,11 @@
#include <stdio.h>
#include <zephyr/kernel.h> #include <zephyr/kernel.h>
#include <zephyr/usb/usb_device.h> #include <zephyr/usb/usb_device.h>
#include <zephyr/logging/log.h> #include <zephyr/logging/log.h>
// LOCAL
#include "led.h" #include "led.h"
#include "config.h" #include "config.h"
#include "imu.h" #include "imu.h"
#include "mode.h"
/* 1000 msec = 1 sec */
#define SLEEP_TIME_MS 1000
LOG_MODULE_REGISTER(main, LOG_LEVEL_INF); LOG_MODULE_REGISTER(main, LOG_LEVEL_INF);
@@ -30,18 +26,22 @@ int main(void)
} }
ret = led_init(); ret = led_init();
if (ret != 0) {
LOG_ERR("Failed to init LEDs: %d", ret);
return ret;
}
ret = imu_init(); ret = imu_init();
if (ret != 0) {
LOG_ERR("Failed to init IMU: %d", ret);
return ret;
}
mode_init(); mode_init();
mode_start(); mode_start();
while (1) { while (1) {
// for (int i = 0; i < 10000; i++) { k_msleep(1000);
// led_set_progress((float)i / 10000.0);
// k_msleep(1);
// }
// leds_fade(1000, 0.1, 0.0, 0.05);
k_msleep(SLEEP_TIME_MS);
} }
return 0; return 0;
} }
+4 -13
View File
@@ -7,7 +7,7 @@
LOG_MODULE_REGISTER(mode, LOG_LEVEL_INF); LOG_MODULE_REGISTER(mode, LOG_LEVEL_INF);
#define POLL_MS 100 #define POLL_MS 100
K_THREAD_STACK_DEFINE(mode_stack, 1024); K_THREAD_STACK_DEFINE(mode_stack, 1024);
static struct k_thread mode_thread; static struct k_thread mode_thread;
@@ -18,43 +18,34 @@ static struct mode_config cfg;
static void mode_thread_fn(void *p1, void *p2, void *p3) static void mode_thread_fn(void *p1, void *p2, void *p3)
{ {
while (atomic_get(&running)) { while (atomic_get(&running)) {
/* --- Phase A --- */ /* Phase A: ramp LED progress bar over phase_a_ms */
int64_t start = k_uptime_get(); int64_t start = k_uptime_get();
while (atomic_get(&running) && k_uptime_get() - start < cfg.phase_a_ms) { while (atomic_get(&running) && k_uptime_get() - start < cfg.phase_a_ms) {
float progress = (float)(k_uptime_get() - start) / cfg.phase_a_ms; float progress = (float)(k_uptime_get() - start) / cfg.phase_a_ms;
LOG_DBG("Phase A: %.2f", (double)progress);
led_set_progress(progress); led_set_progress(progress);
/* do phase A work here */
k_msleep(POLL_MS); k_msleep(POLL_MS);
} }
led_set_progress(0); led_set_progress(0);
/* --- Phase B --- */ /* Phase B: color animation over phase_b_ms */
start = k_uptime_get(); start = k_uptime_get();
while (atomic_get(&running) && k_uptime_get() - start < cfg.phase_b_ms) { while (atomic_get(&running) && k_uptime_get() - start < cfg.phase_b_ms) {
float progress = (float)(k_uptime_get() - start) / cfg.phase_b_ms;
LOG_DBG("Phase B: %.2f", (double)progress);
leds_fade_to(500, 1, -1, -1); leds_fade_to(500, 1, -1, -1);
leds_fade_to(500, -1, 1, -1); leds_fade_to(500, -1, 1, -1);
leds_fade_to(500, -1, 0, -1); leds_fade_to(500, -1, 0, -1);
leds_fade_to(500, 0, -1, -1); leds_fade_to(500, 0, -1, -1);
/* do phase B work here */
// k_msleep(POLL_MS);
} }
} }
LOG_INF("Mode thread stopped."); LOG_INF("Mode thread stopped.");
} }
/* Load mode config from NVS. Must be called after config_init(). */
void mode_init(void) void mode_init(void)
{ {
app_config_t app_cfg; app_config_t app_cfg;
config_init();
config_get(&app_cfg); config_get(&app_cfg);
cfg = app_cfg.mode_config; cfg = app_cfg.mode_config;
LOG_INF("Mode init: phase_a=%d ms, phase_b=%d ms", cfg.phase_a_ms, cfg.phase_b_ms); LOG_INF("Mode init: phase_a=%d ms, phase_b=%d ms", cfg.phase_a_ms, cfg.phase_b_ms);
} }
-5
View File
@@ -1,11 +1,8 @@
#ifndef MODE_H #ifndef MODE_H
#define MODE_H #define MODE_H
#include <stdint.h> #include <stdint.h>
struct mode_config { struct mode_config {
int32_t phase_a_ms; int32_t phase_a_ms;
int32_t phase_b_ms; int32_t phase_b_ms;
@@ -16,6 +13,4 @@ void mode_start(void);
void mode_stop(void); void mode_stop(void);
void mode_restart(void); void mode_restart(void);
#endif /* MODE_H */ #endif /* MODE_H */
-50
View File
@@ -1,50 +0,0 @@
#include "mode.h"
#include "config.h"
#include <zephyr/shell/shell.h>
#include <stdlib.h>
static int cmd_start(const struct shell *sh, size_t argc, char **argv)
{
mode_start();
return 0;
}
static int cmd_stop(const struct shell *sh, size_t argc, char **argv)
{
mode_stop();
return 0;
}
static int cmd_restart(const struct shell *sh, size_t argc, char **argv)
{
mode_restart();
return 0;
}
/* mode init <phase_a_ms> <phase_b_ms> */
static int cmd_init(const struct shell *sh, size_t argc, char **argv)
{
app_config_t app_cfg;
config_get(&app_cfg);
app_cfg.mode_config.phase_a_ms = atoi(argv[1]);
app_cfg.mode_config.phase_b_ms = atoi(argv[2]);
config_save(&app_cfg);
mode_init();
mode_restart();
shell_print(sh, "Config saved. phase_a=%s ms, phase_b=%s ms. Restarting.", argv[1], argv[2]);
return 0;
}
SHELL_STATIC_SUBCMD_SET_CREATE(mode_cmds,
SHELL_CMD(start, NULL, "Start the mode thread.", cmd_start),
SHELL_CMD(stop, NULL, "Stop the mode thread.", cmd_stop),
SHELL_CMD(restart, NULL, "Restart the mode thread.", cmd_restart),
SHELL_CMD_ARG(init, NULL, "Set <phase_a_ms> <phase_b_ms>, save and restart.", cmd_init, 3, 0),
SHELL_SUBCMD_SET_END
);
SHELL_CMD_REGISTER(mode, &mode_cmds, "Mode control.", NULL);
+40
View File
@@ -0,0 +1,40 @@
// User-facing shell commands.
// mode set <phase_a_ms> <phase_b_ms> — save config and restart
// mode status — show current config
//
#include "mode.h"
#include "config.h"
#include <zephyr/shell/shell.h>
#include <stdlib.h>
static int cmd_mode_set(const struct shell *sh, size_t argc, char **argv)
{
app_config_t cfg;
config_get(&cfg);
cfg.mode_config.phase_a_ms = atoi(argv[1]);
cfg.mode_config.phase_b_ms = atoi(argv[2]);
config_save(&cfg);
mode_init();
mode_restart();
shell_print(sh, "Config saved: phase_a=%s ms, phase_b=%s ms. Restarting.", argv[1], argv[2]);
return 0;
}
static int cmd_mode_status(const struct shell *sh, size_t argc, char **argv)
{
app_config_t cfg;
config_get(&cfg);
shell_print(sh, "phase_a=%d ms, phase_b=%d ms",
cfg.mode_config.phase_a_ms,
cfg.mode_config.phase_b_ms);
return 0;
}
SHELL_STATIC_SUBCMD_SET_CREATE(mode_cmds,
SHELL_CMD_ARG(set, NULL, "Set <phase_a_ms> <phase_b_ms>, save and restart.", cmd_mode_set, 3, 0),
SHELL_CMD( status, NULL, "Show current config.", cmd_mode_status),
SHELL_SUBCMD_SET_END
);
SHELL_CMD_REGISTER(mode, &mode_cmds, "Mode control.", NULL);
-18
View File
@@ -1,18 +0,0 @@
#include <zephyr/logging/log.h>
#include <zephyr/shell/shell.h>
#include "config.h"
LOG_MODULE_REGISTER(commands);
void foo(const struct shell *sh, size_t argc, char **argv)
{
LOG_INF("info message");
LOG_WRN("warning message");
LOG_ERR("err message");
ARG_UNUSED(argc);
ARG_UNUSED(argv);
shell_print(sh, "foo executed");
}
SHELL_CMD_REGISTER(foo, NULL, "foo command", foo);
+12 -15
View File
@@ -1,20 +1,17 @@
#include "zbus_channels.h" #include "zbus_channels.h"
ZBUS_CHAN_DEFINE(buttons_data_chan,
ZBUS_CHAN_DEFINE(buttons_data_chan, /* Name */ struct button_msg_t,
struct button_msg_t, /* Message type */ NULL,
NULL,
NULL, /* Validator */ ZBUS_OBSERVERS(),
NULL, /* User data */ ZBUS_MSG_INIT(.button = ERROR, .function = NONE)
ZBUS_OBSERVERS(), /* observers */
ZBUS_MSG_INIT(.button = ERROR, .function = NONE) /* Initial value */
); );
ZBUS_CHAN_DEFINE(geiger_data_chan, /* Name */ ZBUS_CHAN_DEFINE(geiger_data_chan,
struct geiger_msg_t, /* Message type */ struct geiger_msg_t,
NULL,
NULL, /* Validator */ NULL,
NULL, /* User data */ ZBUS_OBSERVERS(),
ZBUS_OBSERVERS(), /* observers */ ZBUS_MSG_INIT(.cps = 0)
ZBUS_MSG_INIT(.cps = 0) /* Initial value */
); );
+7 -13
View File
@@ -1,39 +1,33 @@
#ifndef ZBUS_CHANNEL #ifndef ZBUS_CHANNEL_H
#define ZBUS_CHANNEL #define ZBUS_CHANNEL_H
#include <zephyr/kernel.h> #include <zephyr/kernel.h>
#include <zephyr/zbus/zbus.h> #include <zephyr/zbus/zbus.h>
#include <stdint.h> #include <stdint.h>
typedef enum { typedef enum {
NONE, NONE,
TAP, TAP,
DOUBLE_TAP DOUBLE_TAP,
} function_e; } function_e;
typedef enum { typedef enum {
ERROR = -1, ERROR = -1,
BTN1, BTN1,
BTN2, BTN2,
IMU IMU,
} buttons_e; } buttons_e;
struct button_msg_t { struct button_msg_t {
buttons_e button; buttons_e button;
function_e function; function_e function;
}; };
struct geiger_msg_t { struct geiger_msg_t {
uint32_t cps; // clicks per second uint32_t cps; /* counts per second */
}; };
ZBUS_CHAN_DECLARE(buttons_data_chan); ZBUS_CHAN_DECLARE(buttons_data_chan);
ZBUS_CHAN_DECLARE(geiger_data_chan); ZBUS_CHAN_DECLARE(geiger_data_chan);
#endif // ZBUS_CHANNEL_H
#endif // ZBUS_CHANNEL