Skip to content

Commit d82e4f4

Browse files
committed
pbio/hmi: Use init and deinit for boot animations.
This lets us run it to completion before showing the UI, and keep variant-specific statuses like BLE_ADVERTISING in a dedicated deinit. Also drop the pbio/sys/light_matrix abstraction as explained in the prior commits. The HMI and user applications are now just users of the pbio/light_matrix device. For EV3, this means we can drop the depency of the light matrix. Instead, it will have its dedicated UI. To have something in place, we'll keep the grid-like display for now, but in hmi_lcd so we can easily replace it.
1 parent 4aa5f49 commit d82e4f4

File tree

11 files changed

+165
-174
lines changed

11 files changed

+165
-174
lines changed

bricks/_common/sources.mk

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,6 @@ PBIO_SRC_C = $(addprefix lib/pbio/,\
239239
sys/hmi_pup.c \
240240
sys/hmi_none.c \
241241
sys/host.c \
242-
sys/light_matrix.c \
243242
sys/light.c \
244243
sys/main.c \
245244
sys/program_stop.c \

lib/pbio/platform/ev3/pbsysconfig.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313
#define PBSYS_CONFIG_HMI_NUM_SLOTS (5)
1414
#define PBSYS_CONFIG_HOST (1)
1515
#define PBSYS_CONFIG_HOST_STDIN_BUF_SIZE (21)
16-
#define PBSYS_CONFIG_HUB_LIGHT_MATRIX (1)
17-
#define PBSYS_CONFIG_HUB_LIGHT_MATRIX_DISPLAY (1)
1816
#define PBSYS_CONFIG_MAIN (1)
1917
#define PBSYS_CONFIG_STORAGE (1)
2018
#define PBSYS_CONFIG_STORAGE_NUM_SLOTS (5)

lib/pbio/platform/prime_hub/pbsysconfig.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#define PBSYS_CONFIG_HMI_STOP_BUTTON (1 << 5) // center
1414
#define PBSYS_CONFIG_HMI_NUM_SLOTS (5)
1515
#define PBSYS_CONFIG_HMI_PUP (1)
16+
#define PBSYS_CONFIG_HMI_PUP_LIGHT_MATRIX_INDEX (0)
1617
#define PBSYS_CONFIG_HMI_PUP_BLUETOOTH_BUTTON (1 << 9) // right up
1718
#define PBSYS_CONFIG_HMI_PUP_LEFT_RIGHT_ENABLE (1)
1819
#define PBSYS_CONFIG_HUB_LIGHT_MATRIX (1)

lib/pbio/sys/core.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
#include "hmi.h"
1818
#include "light.h"
19-
#include "light_matrix.h"
2019
#include "storage.h"
2120
#include "program_stop.h"
2221

@@ -52,9 +51,9 @@ void pbsys_init(void) {
5251
pbsys_storage_init();
5352

5453
pbsys_battery_init();
54+
pbsys_hmi_init();
5555
pbsys_host_init();
5656
pbsys_status_light_init();
57-
pbsys_hub_light_matrix_init();
5857

5958
process_start(&pbsys_system_process);
6059

@@ -65,11 +64,8 @@ void pbsys_init(void) {
6564

6665
void pbsys_deinit(void) {
6766

68-
pbsys_status_clear(PBIO_PYBRICKS_STATUS_BLE_ADVERTISING);
69-
pbsys_status_clear(PBIO_PYBRICKS_STATUS_BLE_HOST_CONNECTED);
70-
7167
pbsys_storage_deinit();
72-
pbsys_hub_light_matrix_deinit();
68+
pbsys_hmi_deinit();
7369

7470
uint32_t start = pbdrv_clock_get_ms();
7571

lib/pbio/sys/hmi.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,18 @@
1111

1212
#if PBSYS_CONFIG_HMI
1313

14+
void pbsys_hmi_init(void);
15+
void pbsys_hmi_deinit(void);
16+
1417
pbio_error_t pbsys_hmi_await_program_selection(void);
1518

1619
#else
1720

21+
static inline void pbsys_hmi_init(void) {
22+
}
23+
static inline void pbsys_hmi_deinit(void) {
24+
}
25+
1826
static inline pbio_error_t pbsys_hmi_await_program_selection(void) {
1927
return PBIO_ERROR_NOT_SUPPORTED;
2028
}

lib/pbio/sys/hmi_lcd.c

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
#include <pbsys/storage_settings.h>
2626

2727
#include "hmi.h"
28-
#include "light_matrix.h"
2928

3029
#define DEBUG 0
3130

@@ -36,6 +35,39 @@
3635
#define DEBUG_PRINT(...)
3736
#endif
3837

38+
static void hmi_lcd_grid_show_pixel(uint8_t row, uint8_t col, bool on) {
39+
pbio_image_t *display = pbdrv_display_get_image();
40+
uint8_t value = on ? pbdrv_display_get_max_value(): 0;
41+
const uint32_t size = PBDRV_CONFIG_DISPLAY_NUM_ROWS / PBSYS_CONFIG_HMI_NUM_SLOTS;
42+
const uint32_t width = size * 4 / 5;
43+
const uint32_t offset = (PBDRV_CONFIG_DISPLAY_NUM_COLS - (PBSYS_CONFIG_HMI_NUM_SLOTS * size)) / 2;
44+
pbio_image_fill_rect(display, col * size + offset, row * size, width, width, value);
45+
pbdrv_display_update();
46+
}
47+
48+
static void hmi_lcd_show_program_slot(void) {
49+
pbio_image_t *display = pbdrv_display_get_image();
50+
pbio_image_fill(display, 0);
51+
52+
for (uint8_t r = 0; r < PBSYS_CONFIG_HMI_NUM_SLOTS; r++) {
53+
for (uint8_t c = 0; c < PBSYS_CONFIG_HMI_NUM_SLOTS; c++) {
54+
bool is_on = r < 3 && c > 0 && c < 4;
55+
is_on |= (r == 4 && c == pbsys_status_get_selected_slot());
56+
hmi_lcd_grid_show_pixel(r, c, is_on);
57+
}
58+
}
59+
}
60+
61+
void pbsys_hmi_init(void) {
62+
63+
}
64+
65+
void pbsys_hmi_deinit(void) {
66+
pbio_image_t *display = pbdrv_display_get_image();
67+
pbio_image_fill(display, 0);
68+
pbdrv_display_update();
69+
}
70+
3971
static pbio_error_t run_ui(pbio_os_state_t *state, pbio_os_timer_t *timer) {
4072

4173
PBIO_OS_ASYNC_BEGIN(state);
@@ -45,7 +77,7 @@ static pbio_error_t run_ui(pbio_os_state_t *state, pbio_os_timer_t *timer) {
4577
DEBUG_PRINT("Start HMI loop\n");
4678

4779
// Visually indicate current state on supported hubs.
48-
pbsys_hub_light_matrix_update_program_slot();
80+
hmi_lcd_show_program_slot();
4981

5082
// Buttons could be pressed at the end of the user program, so wait for
5183
// a release and then a new press, or until we have to exit early.

lib/pbio/sys/hmi_none.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@
1717
#include <pbsys/main.h>
1818
#include <pbsys/status.h>
1919

20+
void pbsys_hmi_init(void) {
21+
}
22+
23+
void pbsys_hmi_deinit(void) {
24+
}
25+
2026
pbio_error_t pbsys_hmi_await_program_selection(void) {
2127

2228
while (pbdrv_button_get_pressed()) {

lib/pbio/sys/hmi_pup.c

Lines changed: 114 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,11 @@
1313
#include <stdint.h>
1414

1515
#include <pbdrv/bluetooth.h>
16+
#include <pbdrv/led.h>
1617

1718
#include <pbio/button.h>
19+
#include <pbio/busy_count.h>
20+
#include <pbio/light_matrix.h>
1821
#include <pbio/os.h>
1922
#include <pbsys/host.h>
2023
#include <pbsys/light.h>
@@ -23,7 +26,6 @@
2326
#include <pbsys/storage_settings.h>
2427

2528
#include "hmi.h"
26-
#include "light_matrix.h"
2729

2830
#define DEBUG 0
2931

@@ -34,6 +36,110 @@
3436
#define DEBUG_PRINT(...)
3537
#endif
3638

39+
#if PBIO_CONFIG_LIGHT_MATRIX
40+
41+
pbio_light_matrix_t *pbsys_hub_light_matrix;
42+
43+
/**
44+
* Displays the idle UI. Has a square stop sign and selected slot on bottom row.
45+
*
46+
* @param brightness Brightness (0--100%).
47+
*/
48+
static void light_matrix_show_idle_ui(uint8_t brightness) {
49+
for (uint8_t r = 0; r < PBSYS_CONFIG_HMI_NUM_SLOTS; r++) {
50+
for (uint8_t c = 0; c < PBSYS_CONFIG_HMI_NUM_SLOTS; c++) {
51+
bool is_on = r < 3 && c > 0 && c < 4;
52+
is_on |= (r == 4 && c == pbsys_status_get_selected_slot());
53+
pbio_light_matrix_set_pixel(pbsys_hub_light_matrix, r, c, is_on ? brightness : 0, true);
54+
}
55+
}
56+
}
57+
58+
/**
59+
* Bootup and shutdown animation. This is a process rather than an animation
60+
* process so we can await completion, and later add sound.
61+
*/
62+
static pbio_error_t boot_animation_process_boot_thread(pbio_os_state_t *state, void *context) {
63+
64+
static pbio_os_timer_t timer;
65+
static uint8_t step;
66+
67+
const int num_steps = 10;
68+
69+
// Makes the brightness increment or decrement.
70+
bool booting = context;
71+
72+
PBIO_OS_ASYNC_BEGIN(state);
73+
74+
for (step = 1; step <= num_steps; step++) {
75+
uint8_t brightness = booting ? step * (100 / num_steps) : 100 - (100 / num_steps) * step;
76+
light_matrix_show_idle_ui(brightness);
77+
PBIO_OS_AWAIT_MS(state, &timer, 200 / num_steps);
78+
}
79+
pbio_busy_count_down();
80+
81+
PBIO_OS_ASYNC_END(PBIO_SUCCESS);
82+
}
83+
84+
/**
85+
* Animation frame for program running animation.
86+
*/
87+
static uint32_t pbio_light_matrix_5x5_spinner_animation_next(pbio_light_animation_t *animation) {
88+
89+
// The indexes of pixels to light up
90+
static const uint8_t indexes[] = { 1, 2, 3, 8, 13, 12, 11, 6 };
91+
92+
// Each pixel has a repeating brightness pattern of the form /\_ through
93+
// which we can cycle in 256 steps.
94+
static uint8_t cycle = 0;
95+
96+
for (size_t i = 0; i < PBIO_ARRAY_SIZE(indexes); i++) {
97+
// The pixels are spread equally across the pattern.
98+
uint8_t offset = cycle + i * (UINT8_MAX / PBIO_ARRAY_SIZE(indexes));
99+
uint8_t brightness = offset > 200 ? 0 : (offset < 100 ? offset : 200 - offset);
100+
101+
// Set the brightness for this pixel
102+
pbio_light_matrix_set_pixel(pbsys_hub_light_matrix, indexes[i] / 5, indexes[i] % 5, brightness, false);
103+
}
104+
// This increment controls the speed of the pattern
105+
cycle += 9;
106+
107+
return 40;
108+
}
109+
110+
static void light_matrix_start_run_animation(void) {
111+
// Central pixel in spinner is off and will not be updated.
112+
pbio_light_matrix_set_pixel(pbsys_hub_light_matrix, 1, 2, 0, true);
113+
pbio_light_animation_init(&pbsys_hub_light_matrix->animation, pbio_light_matrix_5x5_spinner_animation_next);
114+
pbio_light_animation_start(&pbsys_hub_light_matrix->animation);
115+
}
116+
117+
static pbio_os_process_t boot_animation_process;
118+
119+
#endif
120+
121+
void pbsys_hmi_init(void) {
122+
#if PBIO_CONFIG_LIGHT_MATRIX
123+
pbio_busy_count_up();
124+
pbio_error_t err = pbio_light_matrix_get_dev(0, 5, &pbsys_hub_light_matrix);
125+
if (err != PBIO_SUCCESS) {
126+
// Effectively stopping boot if we can't get hardware.
127+
return;
128+
}
129+
pbio_os_process_start(&boot_animation_process, boot_animation_process_boot_thread, (void *)true);
130+
#endif
131+
}
132+
133+
void pbsys_hmi_deinit(void) {
134+
pbsys_status_clear(PBIO_PYBRICKS_STATUS_BLE_ADVERTISING);
135+
pbsys_status_clear(PBIO_PYBRICKS_STATUS_BLE_HOST_CONNECTED);
136+
137+
#if PBIO_CONFIG_LIGHT_MATRIX
138+
pbio_busy_count_up();
139+
pbio_os_process_start(&boot_animation_process, boot_animation_process_boot_thread, (void *)false);
140+
#endif
141+
}
142+
37143
/**
38144
* The HMI is a loop running the following steps:
39145
*
@@ -67,7 +173,9 @@ static pbio_error_t run_ui(pbio_os_state_t *state, pbio_os_timer_t *timer) {
67173
DEBUG_PRINT("Start HMI loop\n");
68174

69175
// Visually indicate current state on supported hubs.
70-
pbsys_hub_light_matrix_update_program_slot();
176+
#if PBIO_CONFIG_LIGHT_MATRIX
177+
light_matrix_show_idle_ui(100);
178+
#endif
71179

72180
// Initialize Bluetooth depending on current state.
73181
if (pbdrv_bluetooth_is_connected(PBDRV_BLUETOOTH_CONNECTION_LE)) {
@@ -215,7 +323,10 @@ static pbio_error_t run_ui(pbio_os_state_t *state, pbio_os_timer_t *timer) {
215323
pbsys_status_clear(PBIO_PYBRICKS_STATUS_BLE_ADVERTISING);
216324

217325
// Start run animations
218-
pbsys_hub_light_matrix_handle_user_program_start();
326+
#if PBIO_CONFIG_LIGHT_MATRIX
327+
light_matrix_start_run_animation();
328+
#endif
329+
219330
#if PBSYS_CONFIG_STATUS_LIGHT_STATE_ANIMATIONS
220331
pbio_color_light_start_breathe_animation(pbsys_status_light_main, PBSYS_CONFIG_STATUS_LIGHT_STATE_ANIMATIONS_HUE);
221332
#else

0 commit comments

Comments
 (0)