From d59dec50a88db4ee104118fa17dbd6f1aec701df Mon Sep 17 00:00:00 2001 From: Rodrigo Arias Mallo Date: Sun, 2 Nov 2025 19:24:02 +0100 Subject: [PATCH] Implement led control in another module --- barista/Makefile | 3 ++ barista/barista.ino | 50 +++++++++++++++-------------- barista/led.c | 71 +++++++++++++++++++++++++++++++++++++++++ barista/led.h | 35 ++++++++++++++++++++ barista/test/compat.c | 13 ++++++++ barista/test/compat.h | 17 ++++++++++ barista/test/test_led.c | 42 ++++++++++++++++++++++++ 7 files changed, 207 insertions(+), 24 deletions(-) create mode 100644 barista/led.c create mode 100644 barista/led.h create mode 100644 barista/test/compat.c create mode 100644 barista/test/compat.h create mode 100644 barista/test/test_led.c diff --git a/barista/Makefile b/barista/Makefile index 6112408..019710d 100644 --- a/barista/Makefile +++ b/barista/Makefile @@ -39,6 +39,9 @@ test_ntc: test/test_ntc.o ntc.o test_overheat: test/test_overheat.o overheat.o gcc $^ -o $@ $(LIBS) +test_led: test/test_led.o test/compat.o led.o + gcc $^ -o $@ $(LIBS) + clean: rm -f test/test_ntc.o ntc.o diff --git a/barista/barista.ino b/barista/barista.ino index 8909e48..d608590 100644 --- a/barista/barista.ino +++ b/barista/barista.ino @@ -3,6 +3,7 @@ #include "ntc.h" #include "overheat.h" +#include "led.h" #include "pinout.h" #include @@ -90,6 +91,9 @@ struct state { struct overheat overheat; unsigned long overheat_t0; + + struct led red_led; + struct led green_led; } g_st; int read_input(int pin) @@ -235,7 +239,7 @@ void proc_machine(struct state *st) Serial.println("heating"); } } else if (st->mstate == HEATING) { - if (temp > TEMP_MAX) { + if (temp > TEMP_MIN) { st->mstate = HOT; st->hot_t0 = millis(); st->buzz_state = BUZZ_HEY; @@ -313,35 +317,33 @@ void do_proc(struct state *st, const struct input *input) void output_leds(const struct state *st) { - static int r = 0; - static int g = 0; + unsigned long t = millis(); - if (st->mstate == HEATING || st->mstate == COOLING) { - analogWrite(PIN_LED_RED, r); - setled(PIN_LED_GREEN, 0); - if (r >= 255) - r = 0; - else - r += 5; + if (st->mstate == SLEEPING) { + led_off(&st->red_led); + led_off(&st->green_led); + } else if (st->mstate == HEATING) { + led_off(&st->red_led); + led_pattern(&st->green_led, t, 1000UL, "000123456789abcdefff"); + } else if (st->mstate == COOLING) { + led_off(&st->red_led); + led_pattern(&st->green_led, t, 1000UL, "fffedcba987654321000"); } else if (st->mstate == HOT) { - setled(PIN_LED_RED, 0); - setled(PIN_LED_GREEN, 1); - r = 0; + led_off(&st->red_led); + led_on(&st->green_led); } else if (st->mstate == PANIC_OVERHEAT) { - setled(PIN_LED_RED, 1); - setled(PIN_LED_GREEN, 0); + led_pattern(&st->red_led, t, 3000UL, "f0f0f0000000"); + led_pattern(&st->green_led, t, 3000UL, "000000f0f0f0"); } else if (st->mstate == BREWING_HOT || st->mstate == BREWING_COLD) { - setled(PIN_LED_RED, 0); - analogWrite(PIN_LED_GREEN, g); - if (g >= 255) - g = 0; - else - g += 5; + led_off(&st->red_led); + led_pattern(&st->green_led, millis(), 2000UL, "0123456789abcdefedcba9876543210"); } else { - setled(PIN_LED_RED, 0); - setled(PIN_LED_GREEN, 0); - r = 0; + led_off(&st->red_led); + led_off(&st->green_led); } + + analogWrite(PIN_LED_RED, led_level(&st->red_led, t)); + analogWrite(PIN_LED_GREEN, led_level(&st->green_led, t)); } void diff --git a/barista/led.c b/barista/led.c new file mode 100644 index 0000000..7d9658c --- /dev/null +++ b/barista/led.c @@ -0,0 +1,71 @@ +/* Copyright (c) 2025 Rodrigo Arias Mallo + * SPDX-License-Identifier: GPL-3.0-or-later */ + +#include "led.h" +#include + +void led_on(struct led *led) +{ + led->mode = LED_ON; +} + +void led_off(struct led *led) +{ + led->mode = LED_OFF; +} + +void led_pattern(struct led *led, unsigned long t_ms, unsigned long period_ms, const char *pattern) +{ + int n = strlen(pattern); + unsigned long step_ms = period_ms / n; + + /* Don't change the current state */ + if (led->mode == LED_PATTERN && + led->step_ms == step_ms && + led->pattern == pattern) + return; + + led->mode = LED_PATTERN; + led->pat_i = 0; + led->pat_n = n; + led->pattern = pattern; + led->step_ms = step_ms; + led->t_ms = t_ms; +} + +/* Return led level brightness in [0, 255] at current time */ +int led_level(struct led *led, unsigned long t_ms) +{ + if (led->mode == LED_OFF) + return 0; + + if (led->mode == LED_ON) + return 255; + + if (led->mode == LED_PATTERN) { + while (led->t_ms + led->step_ms < t_ms) { + led->t_ms += led->step_ms; + led->pat_i++; + if (led->pat_i >= led->pat_n) + led->pat_i = 0; + } + + int c = led->pattern[led->pat_i]; + int level; + + if (c >= '0' && c <= '9') + level = 17 * (c - '0'); + else + level = 17 * (10 + (c - 'a')); + + if (level < 0) + level = 0; + else if (level > 255) + level = 255; + + return level; + } + + /* Unknown mode, turn off */ + return 0; +} diff --git a/barista/led.h b/barista/led.h new file mode 100644 index 0000000..dd52d67 --- /dev/null +++ b/barista/led.h @@ -0,0 +1,35 @@ +/* Copyright (c) 2025 Rodrigo Arias Mallo + * SPDX-License-Identifier: GPL-3.0-or-later */ + +#ifndef BARISTA_LED_H +#define BARISTA_LED_H + +#ifdef __cplusplus +extern "C" { +#endif + +enum led_mode { + LED_OFF = 0, + LED_ON, + LED_PATTERN, +}; + +struct led { + enum led_mode mode; + const char *pattern; + int pat_i; + int pat_n; + unsigned long step_ms; + unsigned long t_ms; +}; + +void led_on(struct led *led); +void led_off(struct led *led); +void led_pattern(struct led *led, unsigned long t_ms, unsigned long period_ms, const char *pattern); +int led_level(struct led *led, unsigned long t_ms); + +#ifdef __cplusplus +} +#endif + +#endif /* BARISTA_LED_H */ diff --git a/barista/test/compat.c b/barista/test/compat.c new file mode 100644 index 0000000..08bcc5f --- /dev/null +++ b/barista/test/compat.c @@ -0,0 +1,13 @@ +/* Copyright (c) 2025 Rodrigo Arias Mallo + * SPDX-License-Identifier: GPL-3.0-or-later */ + +#include "compat.h" +#include + +unsigned long millis(void) +{ + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + + return ts.tv_sec * 1000UL + ts.tv_nsec / 1000000UL; +} diff --git a/barista/test/compat.h b/barista/test/compat.h new file mode 100644 index 0000000..f1d83c5 --- /dev/null +++ b/barista/test/compat.h @@ -0,0 +1,17 @@ +/* Copyright (c) 2025 Rodrigo Arias Mallo + * SPDX-License-Identifier: GPL-3.0-or-later */ + +#ifndef BARISTA_COMPAT_H +#define BARISTA_COMPAT_H + +#ifdef __cplusplus +extern "C" { +#endif + +unsigned long millis(void); + +#ifdef __cplusplus +} +#endif + +#endif /* BARISTA_COMPAT_H */ diff --git a/barista/test/test_led.c b/barista/test/test_led.c new file mode 100644 index 0000000..41a36e2 --- /dev/null +++ b/barista/test/test_led.c @@ -0,0 +1,42 @@ +/* Copyright (c) 2025 Rodrigo Arias Mallo + * SPDX-License-Identifier: GPL-3.0-or-later */ + +#include +#include "led.h" +#include "compat.h" + +int main(void) +{ + struct led led; + unsigned long t0 = millis(); + unsigned long step = 1000UL; + + led_pattern(&led, t0, step, "000123456789abcdefff"); + + int last_level = -1; + + unsigned long last_t = millis(); + while (1) { + unsigned long t = millis(); + + if (t - t0 >= 10000UL) + break; + + if (t - last_t < 50UL) + continue; + + int level = led_level(&led, millis()); + printf("|"); + for (int i = 0; i < 256; i+=4) { + if (i < level) + printf("="); + else + printf(" "); + } + printf("|\n"); + last_level = level; + last_t = t; + } + + return 0; +}