feat: LED-Treiber, Licht-Task und UART-Testkonsole
This commit is contained in:
+10
-3
@@ -28,13 +28,20 @@ set(NL_FW_SOURCES
|
|||||||
src/app_main.c
|
src/app_main.c
|
||||||
src/util/nl_sha256.c
|
src/util/nl_sha256.c
|
||||||
src/util/nl_crc.c
|
src/util/nl_crc.c
|
||||||
src/sys/fwup_hook_default.c
|
|
||||||
src/sys/sdk_stubs.c
|
|
||||||
src/board/nl_board.c
|
src/board/nl_board.c
|
||||||
src/light/nl_color.c
|
src/light/nl_color.c
|
||||||
src/light/nl_engine.c
|
src/light/nl_engine.c
|
||||||
src/light/nl_control.c
|
src/light/nl_control.c
|
||||||
src/light/nl_boot_state.c)
|
src/light/nl_boot_state.c
|
||||||
|
src/config/nl_settings.c
|
||||||
|
src/config/nl_flash_w600.c
|
||||||
|
src/drivers/nl_led.c
|
||||||
|
src/drivers/nl_pwm_leds.c
|
||||||
|
src/drivers/nl_sm2135eh.c
|
||||||
|
src/sys/nl_console_cmd.c
|
||||||
|
src/sys/nl_console.c
|
||||||
|
src/sys/fwup_hook_default.c
|
||||||
|
src/sys/sdk_stubs.c)
|
||||||
|
|
||||||
set(NL_FW ninlight_${NINLIGHT_DEVICE})
|
set(NL_FW ninlight_${NINLIGHT_DEVICE})
|
||||||
add_executable(${NL_FW} ${NL_SDK_BOOT_SOURCES} ${NL_FW_SOURCES} ${NL_SDK_OBJECTS})
|
add_executable(${NL_FW} ${NL_SDK_BOOT_SOURCES} ${NL_FW_SOURCES} ${NL_SDK_OBJECTS})
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# Hardware-Checkliste (EVK)
|
||||||
|
|
||||||
|
Konsole: `tools/monitor.sh /dev/cu.<port>` (115200 8N1). Flashen: `tools/flash.sh evk <port>`.
|
||||||
|
|
||||||
|
## Licht (Plan 1, Task 11)
|
||||||
|
- [ ] Nach dem Boot blendet warmweiß 100 % in 0,5 s ein
|
||||||
|
- [ ] `rgb 255 0 0` → nur Rot, `rgb 0 255 0` → nur Grün, `rgb 0 0 255` → nur Blau
|
||||||
|
- [ ] `ct 2700` → nur Warmweiß, `ct 6500` → nur Kaltweiß, `ct 4000` → Mischung
|
||||||
|
- [ ] `bri 1` sichtbar sehr dunkel, `bri 100` hell; `bri 1 3000` → gleichmäßig wirkender Fade
|
||||||
|
- [ ] `off 2000` → blendet mit aktueller Farbe aus; `on 2000` → blendet ein
|
||||||
|
- [ ] `rgb 255 0 0` dann `ct 3000 2000` → erst dunkel, dann weiß (Moduswechsel)
|
||||||
|
- [ ] `blink 3` → 3× Blinken, danach alter Zustand; `pulse on` / `pulse off`
|
||||||
|
- [ ] Kein sichtbares Flackern bei konstanten Werten (5 kHz)
|
||||||
|
|
||||||
|
## Persistenz und Boot (Plan 1, Task 12)
|
||||||
|
- [ ] `pob last`: Farbe setzen, 4 s warten, Strom aus/an → gleicher Zustand, mit Fade
|
||||||
|
- [ ] `pob off`: Strom aus/an → bleibt aus; `on` → letzte Farbe
|
||||||
|
- [ ] `pob on` bei ausgeschaltetem Licht: Strom aus/an → an
|
||||||
|
- [ ] `fade 2000 2000` bleibt nach Reboot erhalten (`state`)
|
||||||
|
- [ ] 5× Strom an/aus mit jeweils < 5 s Laufzeit → 3× Blinken, danach Defaults (`state`)
|
||||||
|
- [ ] Normaler Boot nach > 5 s Laufzeit → kein Werksreset
|
||||||
|
- [ ] Watchdog: `reboot` funktioniert; nach einem Hänger (nicht provozierbar) wäre Reset nach 20 s
|
||||||
|
|
||||||
|
## Später (Lampen)
|
||||||
|
- [ ] E27 Color (SM2135EH): RGB und WY getrennt, Ströme plausibel (nicht zu heiß)
|
||||||
|
- [ ] E27 CW: Gegenphase CW sichtbar flackerfrei
|
||||||
|
- [ ] G95: Pinbelegung WW=PB15/CW=PB13 prüfen
|
||||||
|
- [ ] Farbtemperaturbereiche aller Varianten
|
||||||
+87
-7
@@ -2,21 +2,101 @@
|
|||||||
|
|
||||||
#include "wm_include.h"
|
#include "wm_include.h"
|
||||||
|
|
||||||
#define NL_APP_TASK_PRIO 40
|
#include "board/nl_board.h"
|
||||||
static u32 s_app_stack[512];
|
#include "config/nl_settings.h"
|
||||||
|
#include "drivers/nl_led.h"
|
||||||
|
#include "light/nl_boot_state.h"
|
||||||
|
#include "light/nl_control.h"
|
||||||
|
#include "light/nl_engine.h"
|
||||||
|
#include "sys/nl_app.h"
|
||||||
|
#include "sys/nl_console.h"
|
||||||
|
|
||||||
|
#define NL_LIGHT_PRIO 30
|
||||||
|
#define NL_APP_PRIO 40
|
||||||
|
|
||||||
|
static tls_os_mutex_t *s_lock;
|
||||||
|
static nl_settings_t s_settings;
|
||||||
|
static volatile uint32_t s_light_beat;
|
||||||
|
static u32 s_app_stack[1024];
|
||||||
|
static u32 s_light_stack[512];
|
||||||
|
|
||||||
|
void nl_app_lock(void) { tls_os_mutex_acquire(s_lock, 0); }
|
||||||
|
void nl_app_unlock(void) { tls_os_mutex_release(s_lock); }
|
||||||
|
|
||||||
|
uint32_t nl_app_now_ms(void)
|
||||||
|
{
|
||||||
|
return (uint32_t)((uint64_t)tls_os_get_time() * 1000u / HZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
nl_settings_t *nl_app_settings(void) { return &s_settings; }
|
||||||
|
|
||||||
|
int nl_app_save_settings(void)
|
||||||
|
{
|
||||||
|
return 0; /* persistence follows in task 12 */
|
||||||
|
}
|
||||||
|
|
||||||
|
void nl_app_factory_reset(void)
|
||||||
|
{
|
||||||
|
printf("factory reset: not implemented yet\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void led_out(const uint8_t ch[NL_CH_COUNT], void *ctx)
|
||||||
|
{
|
||||||
|
(void)ctx;
|
||||||
|
nl_led_set(ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void light_task(void *arg)
|
||||||
|
{
|
||||||
|
uint32_t last = nl_app_now_ms();
|
||||||
|
(void)arg;
|
||||||
|
for (;;) {
|
||||||
|
uint32_t now;
|
||||||
|
tls_os_time_delay(HZ / 100 ? HZ / 100 : 1); /* ~10 ms */
|
||||||
|
now = nl_app_now_ms();
|
||||||
|
nl_app_lock();
|
||||||
|
nl_engine_tick(now - last);
|
||||||
|
nl_app_unlock();
|
||||||
|
last = now;
|
||||||
|
s_light_beat++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void app_task(void *arg)
|
static void app_task(void *arg)
|
||||||
{
|
{
|
||||||
unsigned int n = 0;
|
const nl_board_t *board = nl_board_get();
|
||||||
|
nl_engine_cfg_t cfg;
|
||||||
|
nl_light_state_t initial;
|
||||||
|
|
||||||
(void)arg;
|
(void)arg;
|
||||||
for (;;) {
|
nl_settings_defaults(&s_settings);
|
||||||
printf("ninlight %s alive %u\r\n", NINLIGHT_DEVICE_ID, n++);
|
|
||||||
|
nl_led_init(board);
|
||||||
|
cfg.ct_min = board->ct_min;
|
||||||
|
cfg.ct_max = board->ct_max;
|
||||||
|
cfg.output = led_out;
|
||||||
|
cfg.ctx = NULL;
|
||||||
|
nl_app_lock();
|
||||||
|
nl_engine_init(&cfg);
|
||||||
|
nl_ctrl_init(board, s_settings.fade_in_ms, s_settings.fade_out_ms);
|
||||||
|
initial = nl_boot_default_state(board);
|
||||||
|
nl_ctrl_boot(&initial);
|
||||||
|
nl_app_unlock();
|
||||||
|
|
||||||
|
tls_os_task_create(NULL, "nl_light", light_task, NULL, (u8 *)s_light_stack, sizeof(s_light_stack), NL_LIGHT_PRIO, 0);
|
||||||
|
nl_console_start();
|
||||||
|
|
||||||
|
for (;;)
|
||||||
tls_os_time_delay(HZ);
|
tls_os_time_delay(HZ);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void UserMain(void)
|
void UserMain(void)
|
||||||
{
|
{
|
||||||
printf("\r\nninlight %s for %s (built %s)\r\n", NINLIGHT_FW_VERSION, NINLIGHT_DEVICE_ID, NINLIGHT_BUILD_DATE);
|
printf("\r\nninlight %s for %s (built %s)\r\n", NINLIGHT_FW_VERSION, NINLIGHT_DEVICE_ID, NINLIGHT_BUILD_DATE);
|
||||||
tls_os_task_create(NULL, "nl_app", app_task, NULL, (u8 *)s_app_stack, sizeof(s_app_stack), NL_APP_TASK_PRIO, 0);
|
if (nl_board_get() == NULL) {
|
||||||
|
printf("FATAL: unknown board %s\r\n", NINLIGHT_DEVICE_ID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tls_os_mutex_create(0, &s_lock);
|
||||||
|
tls_os_task_create(NULL, "nl_app", app_task, NULL, (u8 *)s_app_stack, sizeof(s_app_stack), NL_APP_PRIO, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#include "config/nl_flash.h"
|
||||||
|
|
||||||
|
/* Temporary stub, replaced by the real W600 implementation in task 12. */
|
||||||
|
int nl_flash_read(uint32_t addr, void *buf, uint32_t len) { (void)addr; (void)buf; (void)len; return -1; }
|
||||||
|
int nl_flash_write(uint32_t addr, const void *buf, uint32_t len) { (void)addr; (void)buf; (void)len; return -1; }
|
||||||
|
int nl_flash_erase_sector(uint32_t addr) { (void)addr; return -1; }
|
||||||
|
uint32_t nl_flash_region_base(void) { return 0; }
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
#include "drivers/nl_led.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
static const nl_board_t *s_board;
|
||||||
|
|
||||||
|
void nl_led_init(const nl_board_t *board)
|
||||||
|
{
|
||||||
|
s_board = board;
|
||||||
|
if (board->driver == NL_DRV_PWM)
|
||||||
|
nl_pwm_leds_init(board);
|
||||||
|
else
|
||||||
|
nl_sm2135eh_init(board);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nl_led_set(const uint8_t ch[NL_CH_COUNT])
|
||||||
|
{
|
||||||
|
if (s_board == NULL)
|
||||||
|
return;
|
||||||
|
if (s_board->driver == NL_DRV_PWM)
|
||||||
|
nl_pwm_leds_set(ch);
|
||||||
|
else
|
||||||
|
nl_sm2135eh_set(ch);
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
#ifndef NL_LED_H
|
||||||
|
#define NL_LED_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "board/nl_board.h"
|
||||||
|
|
||||||
|
void nl_led_init(const nl_board_t *board);
|
||||||
|
void nl_led_set(const uint8_t ch[NL_CH_COUNT]);
|
||||||
|
|
||||||
|
/* back ends */
|
||||||
|
void nl_pwm_leds_init(const nl_board_t *board);
|
||||||
|
void nl_pwm_leds_set(const uint8_t ch[NL_CH_COUNT]);
|
||||||
|
void nl_sm2135eh_init(const nl_board_t *board);
|
||||||
|
void nl_sm2135eh_set(const uint8_t ch[NL_CH_COUNT]);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "wm_include.h"
|
||||||
|
#include "wm_gpio_afsel.h"
|
||||||
|
|
||||||
|
#include "drivers/nl_led.h"
|
||||||
|
|
||||||
|
static const nl_board_t *s_board;
|
||||||
|
static bool s_on_pwm[NL_CH_COUNT]; /* pin currently routed to the PWM unit */
|
||||||
|
static uint8_t s_last[NL_CH_COUNT];
|
||||||
|
static bool s_have_last;
|
||||||
|
|
||||||
|
static void route_to_pwm(int8_t ch, uint8_t pin)
|
||||||
|
{
|
||||||
|
enum tls_io_name io = (enum tls_io_name)pin;
|
||||||
|
switch (ch) {
|
||||||
|
case 0: wm_pwm1_config(io); break;
|
||||||
|
case 1: wm_pwm2_config(io); break;
|
||||||
|
case 2: wm_pwm3_config(io); break;
|
||||||
|
case 3: wm_pwm4_config(io); break;
|
||||||
|
case 4: wm_pwm5_config(io); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drive_gpio(const nl_pwm_chan_t *c, bool led_on)
|
||||||
|
{
|
||||||
|
bool level = c->active_low ? !led_on : led_on;
|
||||||
|
tls_gpio_cfg((enum tls_io_name)c->pin, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
|
||||||
|
tls_gpio_write((enum tls_io_name)c->pin, level ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nl_pwm_leds_init(const nl_board_t *board)
|
||||||
|
{
|
||||||
|
s_board = board;
|
||||||
|
s_have_last = false;
|
||||||
|
for (int i = 0; i < NL_CH_COUNT; i++) {
|
||||||
|
const nl_pwm_chan_t *c = &board->pwm[i];
|
||||||
|
s_on_pwm[i] = false;
|
||||||
|
if (c->pwm_ch < 0)
|
||||||
|
continue;
|
||||||
|
if (c->antiphase)
|
||||||
|
tls_pwm_ineverse_init((u8)c->pwm_ch, board->pwm_freq_hz, 128, 0);
|
||||||
|
else
|
||||||
|
tls_pwm_init((u8)c->pwm_ch, board->pwm_freq_hz, 128, 0);
|
||||||
|
tls_pwm_start((u8)c->pwm_ch);
|
||||||
|
drive_gpio(c, false); /* dark until the engine sets a value */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void nl_pwm_leds_set(const uint8_t ch[NL_CH_COUNT])
|
||||||
|
{
|
||||||
|
u32 cpu_sr;
|
||||||
|
uint32_t cmp, ch4;
|
||||||
|
|
||||||
|
if (s_have_last && memcmp(ch, s_last, NL_CH_COUNT) == 0)
|
||||||
|
return;
|
||||||
|
memcpy(s_last, ch, NL_CH_COUNT);
|
||||||
|
s_have_last = true;
|
||||||
|
|
||||||
|
/* 1. update all duty cycles at once */
|
||||||
|
cpu_sr = tls_os_set_critical();
|
||||||
|
cmp = tls_reg_read32(HR_PWM_CMPDAT);
|
||||||
|
ch4 = tls_reg_read32(HR_PWM_CH4_REG2);
|
||||||
|
for (int i = 0; i < NL_CH_COUNT; i++) {
|
||||||
|
const nl_pwm_chan_t *c = &s_board->pwm[i];
|
||||||
|
uint8_t v = ch[i], duty;
|
||||||
|
if (c->pwm_ch < 0 || v == 0 || v == 255)
|
||||||
|
continue;
|
||||||
|
duty = (c->active_low != c->antiphase) ? (uint8_t)(255 - v) : v;
|
||||||
|
if (c->pwm_ch == 4)
|
||||||
|
ch4 = (ch4 & ~0x0000FF00u) | ((uint32_t)duty << 8);
|
||||||
|
else
|
||||||
|
cmp = (cmp & ~(0xFFu << (c->pwm_ch * 8))) | ((uint32_t)duty << (c->pwm_ch * 8));
|
||||||
|
}
|
||||||
|
tls_reg_write32(HR_PWM_CMPDAT, cmp);
|
||||||
|
tls_reg_write32(HR_PWM_CH4_REG2, ch4);
|
||||||
|
tls_os_release_critical(cpu_sr);
|
||||||
|
|
||||||
|
/* 2. switch pins between GPIO (0 / 255) and PWM */
|
||||||
|
for (int i = 0; i < NL_CH_COUNT; i++) {
|
||||||
|
const nl_pwm_chan_t *c = &s_board->pwm[i];
|
||||||
|
uint8_t v = ch[i];
|
||||||
|
if (c->pwm_ch < 0)
|
||||||
|
continue;
|
||||||
|
if (v == 0 || v == 255) {
|
||||||
|
drive_gpio(c, v == 255);
|
||||||
|
s_on_pwm[i] = false;
|
||||||
|
} else if (!s_on_pwm[i]) {
|
||||||
|
route_to_pwm(c->pwm_ch, c->pin);
|
||||||
|
s_on_pwm[i] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "wm_include.h"
|
||||||
|
|
||||||
|
#include "drivers/nl_led.h"
|
||||||
|
|
||||||
|
#define SM_ADDR_CURRENT 0xC0u
|
||||||
|
#define SM_ADDR_WY 0xC5u
|
||||||
|
#define SM_CHANNEL_WY 0x80u /* channel select bit 7: 0 = RGB, 1 = WY */
|
||||||
|
|
||||||
|
extern void delay_us(unsigned int us); /* provided by libwlan.a */
|
||||||
|
|
||||||
|
static uint8_t s_clk, s_dat, s_current;
|
||||||
|
static uint8_t s_last[NL_CH_COUNT];
|
||||||
|
static bool s_have_last;
|
||||||
|
|
||||||
|
static void pin(uint8_t p, int v)
|
||||||
|
{
|
||||||
|
tls_gpio_write((enum tls_io_name)p, (u8)v);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bus_start(void)
|
||||||
|
{
|
||||||
|
pin(s_clk, 1); pin(s_dat, 1); delay_us(1);
|
||||||
|
pin(s_dat, 0); delay_us(1);
|
||||||
|
pin(s_clk, 0); delay_us(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bus_stop(void)
|
||||||
|
{
|
||||||
|
pin(s_clk, 0); pin(s_dat, 0); delay_us(1);
|
||||||
|
pin(s_clk, 1); delay_us(1);
|
||||||
|
pin(s_dat, 1); delay_us(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_byte(uint8_t b)
|
||||||
|
{
|
||||||
|
for (uint8_t m = 0x80; m; m >>= 1) {
|
||||||
|
pin(s_dat, (b & m) ? 1 : 0); delay_us(1);
|
||||||
|
pin(s_clk, 1); delay_us(1);
|
||||||
|
pin(s_clk, 0); delay_us(1);
|
||||||
|
}
|
||||||
|
/* ack clock; the SM2135EH does not drive an ack */
|
||||||
|
pin(s_dat, 0); delay_us(1);
|
||||||
|
pin(s_clk, 1); delay_us(1);
|
||||||
|
pin(s_clk, 0); pin(s_dat, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sm_send(const uint8_t *d, int n)
|
||||||
|
{
|
||||||
|
bus_start();
|
||||||
|
for (int i = 0; i < n; i++)
|
||||||
|
write_byte(d[i]);
|
||||||
|
bus_stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void nl_sm2135eh_init(const nl_board_t *board)
|
||||||
|
{
|
||||||
|
uint8_t off[NL_CH_COUNT] = {0};
|
||||||
|
s_clk = board->sm_clk_pin;
|
||||||
|
s_dat = board->sm_dat_pin;
|
||||||
|
s_current = board->sm_current;
|
||||||
|
s_have_last = false;
|
||||||
|
tls_gpio_cfg((enum tls_io_name)s_clk, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH);
|
||||||
|
tls_gpio_cfg((enum tls_io_name)s_dat, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH);
|
||||||
|
nl_sm2135eh_set(off);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nl_sm2135eh_set(const uint8_t ch[NL_CH_COUNT])
|
||||||
|
{
|
||||||
|
bool white = ch[NL_CH_CW] || ch[NL_CH_WW];
|
||||||
|
|
||||||
|
if (s_have_last && memcmp(ch, s_last, NL_CH_COUNT) == 0)
|
||||||
|
return;
|
||||||
|
memcpy(s_last, ch, NL_CH_COUNT);
|
||||||
|
s_have_last = true;
|
||||||
|
|
||||||
|
if (!white) {
|
||||||
|
uint8_t d[6] = {SM_ADDR_CURRENT, s_current, 0x00, ch[NL_CH_B], ch[NL_CH_G], ch[NL_CH_R]};
|
||||||
|
sm_send(d, 6);
|
||||||
|
} else {
|
||||||
|
uint8_t h[3] = {SM_ADDR_CURRENT, s_current, SM_CHANNEL_WY};
|
||||||
|
uint8_t d[3] = {SM_ADDR_WY, ch[NL_CH_WW], ch[NL_CH_CW]};
|
||||||
|
sm_send(h, 3);
|
||||||
|
sm_send(d, 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#ifndef NL_APP_H
|
||||||
|
#define NL_APP_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "config/nl_settings.h"
|
||||||
|
|
||||||
|
void nl_app_lock(void);
|
||||||
|
void nl_app_unlock(void);
|
||||||
|
uint32_t nl_app_now_ms(void);
|
||||||
|
nl_settings_t *nl_app_settings(void);
|
||||||
|
int nl_app_save_settings(void);
|
||||||
|
void nl_app_factory_reset(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "wm_include.h"
|
||||||
|
#include "wm_watchdog.h"
|
||||||
|
|
||||||
|
#include "light/nl_control.h"
|
||||||
|
#include "light/nl_engine.h"
|
||||||
|
#include "sys/nl_app.h"
|
||||||
|
#include "sys/nl_console.h"
|
||||||
|
#include "sys/nl_console_cmd.h"
|
||||||
|
|
||||||
|
#define NL_CONSOLE_PRIO 45
|
||||||
|
static u32 s_stack[768];
|
||||||
|
|
||||||
|
static void print_state(void)
|
||||||
|
{
|
||||||
|
nl_light_state_t s;
|
||||||
|
nl_settings_t *cfg = nl_app_settings();
|
||||||
|
nl_app_lock();
|
||||||
|
nl_ctrl_get(&s);
|
||||||
|
nl_app_unlock();
|
||||||
|
printf("state: %s bri=%u mode=%s rgb=%u,%u,%u ct=%u | pob=%u fade=%u/%u\r\n",
|
||||||
|
s.on ? "on" : "off", s.brightness, s.mode == NL_MODE_COLOR ? "color" : "white",
|
||||||
|
s.r, s.g, s.b, s.ct, cfg->power_on_behaviour, cfg->fade_in_ms, cfg->fade_out_ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_transition(nl_light_change_t *ch, const nl_cmd_t *c, uint8_t index)
|
||||||
|
{
|
||||||
|
if (c->argc > index) {
|
||||||
|
ch->has_transition = true;
|
||||||
|
ch->transition_ms = (uint32_t)c->arg[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void exec(const nl_cmd_t *c)
|
||||||
|
{
|
||||||
|
nl_light_change_t ch;
|
||||||
|
nl_ctrl_err_t err;
|
||||||
|
nl_settings_t *cfg = nl_app_settings();
|
||||||
|
|
||||||
|
memset(&ch, 0, sizeof ch);
|
||||||
|
switch (c->type) {
|
||||||
|
case NL_CMD_NONE:
|
||||||
|
return;
|
||||||
|
case NL_CMD_ON:
|
||||||
|
case NL_CMD_OFF:
|
||||||
|
ch.has_on = true;
|
||||||
|
ch.on = c->type == NL_CMD_ON;
|
||||||
|
set_transition(&ch, c, 0);
|
||||||
|
break;
|
||||||
|
case NL_CMD_BRI:
|
||||||
|
ch.has_brightness = true;
|
||||||
|
ch.brightness = (uint8_t)c->arg[0];
|
||||||
|
set_transition(&ch, c, 1);
|
||||||
|
break;
|
||||||
|
case NL_CMD_RGB:
|
||||||
|
ch.has_color = true;
|
||||||
|
ch.r = (uint8_t)c->arg[0];
|
||||||
|
ch.g = (uint8_t)c->arg[1];
|
||||||
|
ch.b = (uint8_t)c->arg[2];
|
||||||
|
set_transition(&ch, c, 3);
|
||||||
|
break;
|
||||||
|
case NL_CMD_CT:
|
||||||
|
ch.has_ct = true;
|
||||||
|
ch.ct = (uint16_t)c->arg[0];
|
||||||
|
set_transition(&ch, c, 1);
|
||||||
|
break;
|
||||||
|
case NL_CMD_POB:
|
||||||
|
nl_app_lock();
|
||||||
|
cfg->power_on_behaviour = (uint8_t)c->arg[0];
|
||||||
|
nl_app_unlock();
|
||||||
|
printf(nl_app_save_settings() == 0 ? "ok\r\n" : "error: save failed\r\n");
|
||||||
|
print_state();
|
||||||
|
return;
|
||||||
|
case NL_CMD_FADE:
|
||||||
|
nl_app_lock();
|
||||||
|
cfg->fade_in_ms = (uint16_t)c->arg[0];
|
||||||
|
cfg->fade_out_ms = (uint16_t)c->arg[1];
|
||||||
|
nl_ctrl_set_fades(cfg->fade_in_ms, cfg->fade_out_ms);
|
||||||
|
nl_app_unlock();
|
||||||
|
printf(nl_app_save_settings() == 0 ? "ok\r\n" : "error: save failed\r\n");
|
||||||
|
print_state();
|
||||||
|
return;
|
||||||
|
case NL_CMD_STATE:
|
||||||
|
print_state();
|
||||||
|
return;
|
||||||
|
case NL_CMD_BLINK:
|
||||||
|
nl_app_lock();
|
||||||
|
nl_engine_blink((uint8_t)c->arg[0]);
|
||||||
|
nl_app_unlock();
|
||||||
|
return;
|
||||||
|
case NL_CMD_PULSE:
|
||||||
|
nl_app_lock();
|
||||||
|
nl_engine_pulse(c->arg[0] != 0);
|
||||||
|
nl_app_unlock();
|
||||||
|
return;
|
||||||
|
case NL_CMD_FACTORY:
|
||||||
|
nl_app_factory_reset();
|
||||||
|
return;
|
||||||
|
case NL_CMD_REBOOT:
|
||||||
|
tls_sys_reset();
|
||||||
|
return;
|
||||||
|
case NL_CMD_HELP:
|
||||||
|
printf("%s", nl_console_help);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
printf("error: unknown command or bad argument (try help)\r\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nl_app_lock();
|
||||||
|
err = nl_ctrl_apply(&ch, nl_app_now_ms());
|
||||||
|
nl_app_unlock();
|
||||||
|
if (err == NL_CTRL_OK)
|
||||||
|
printf("ok\r\n");
|
||||||
|
else
|
||||||
|
printf("error %d\r\n", (int)err);
|
||||||
|
print_state();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void console_task(void *arg)
|
||||||
|
{
|
||||||
|
char line[64];
|
||||||
|
int len = 0;
|
||||||
|
u8 buf[16];
|
||||||
|
|
||||||
|
(void)arg;
|
||||||
|
printf("console ready, type help\r\n");
|
||||||
|
for (;;) {
|
||||||
|
int n = tls_uart_read(TLS_UART_0, buf, sizeof buf);
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
char c = (char)buf[i];
|
||||||
|
if (c == '\r' || c == '\n') {
|
||||||
|
if (len) {
|
||||||
|
nl_cmd_t cmd;
|
||||||
|
line[len] = '\0';
|
||||||
|
cmd = nl_console_parse(line);
|
||||||
|
exec(&cmd);
|
||||||
|
len = 0;
|
||||||
|
}
|
||||||
|
} else if (len < (int)sizeof(line) - 1) {
|
||||||
|
line[len++] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tls_os_time_delay(HZ / 50); /* 20 ms */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void nl_console_start(void)
|
||||||
|
{
|
||||||
|
tls_uart_port_init(TLS_UART_0, NULL, 0);
|
||||||
|
tls_os_task_create(NULL, "nl_con", console_task, NULL, (u8 *)s_stack, sizeof(s_stack), NL_CONSOLE_PRIO, 0);
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#ifndef NL_CONSOLE_H
|
||||||
|
#define NL_CONSOLE_H
|
||||||
|
|
||||||
|
/* Line based test console on UART0 (115200 8N1), shares the port with printf. */
|
||||||
|
void nl_console_start(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user