diff --git a/lib/pbio/drv/display/display_ev3.c b/lib/pbio/drv/display/display_ev3.c index f87f4ac54..abcc32fef 100644 --- a/lib/pbio/drv/display/display_ev3.c +++ b/lib/pbio/drv/display/display_ev3.c @@ -492,12 +492,17 @@ static pbio_error_t pbdrv_display_ev3_process_thread(pbio_os_state_t *state, voi // Staying in data mode from here. pbdrv_gpio_out_high(&pin_lcd_a0); - // Initial splash screen. + // Briefly show initial splash screen. REVISIT: Move boot animation to sys/hmi. pbdrv_display_load_indexed_bitmap(pbdrv_display_pybricks_logo); pbdrv_display_st7586s_encode_user_frame(); pbdrv_display_st7586s_write_data_begin(st7586s_send_buf, sizeof(st7586s_send_buf)); PBIO_OS_AWAIT_UNTIL(state, spi_status == SPI_STATUS_COMPLETE); pbdrv_gpio_out_high(&pin_lcd_cs); + PBIO_OS_AWAIT_MS(state, &timer, 500); + + // Clear display to start with. + memset(&pbdrv_display_user_frame, 0, sizeof(pbdrv_display_user_frame)); + pbdrv_display_user_frame_update_requested = true; // Done initializing. pbio_busy_count_down(); diff --git a/lib/pbio/include/pbio/image.h b/lib/pbio/include/pbio/image.h index 6b9a7a649..669000414 100644 --- a/lib/pbio/include/pbio/image.h +++ b/lib/pbio/include/pbio/image.h @@ -11,8 +11,6 @@ #include -#if PBIO_CONFIG_IMAGE - #include /** @@ -53,6 +51,8 @@ typedef struct _pbio_image_t { int stride; } pbio_image_t; +#if PBIO_CONFIG_IMAGE + void pbio_image_init(pbio_image_t *image, uint8_t *pixels, int width, int height, int stride); diff --git a/lib/pbio/platform/ev3/pbioconfig.h b/lib/pbio/platform/ev3/pbioconfig.h index 3b9ae25d7..aa0c2301d 100644 --- a/lib/pbio/platform/ev3/pbioconfig.h +++ b/lib/pbio/platform/ev3/pbioconfig.h @@ -8,6 +8,7 @@ #define PBIO_CONFIG_IMAGE (1) #define PBIO_CONFIG_IMU (0) #define PBIO_CONFIG_LIGHT (1) +#define PBIO_CONFIG_LIGHT_MATRIX (1) #define PBIO_CONFIG_LOGGER (1) #define PBIO_CONFIG_MOTOR_PROCESS (1) #define PBIO_CONFIG_PORT (1) diff --git a/lib/pbio/platform/ev3/pbsysconfig.h b/lib/pbio/platform/ev3/pbsysconfig.h index 5cb33f9db..319833243 100644 --- a/lib/pbio/platform/ev3/pbsysconfig.h +++ b/lib/pbio/platform/ev3/pbsysconfig.h @@ -6,16 +6,20 @@ #define PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_IMU_CALIBRATION (0) #define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6 (1) #define PBSYS_CONFIG_FEATURE_PROGRAM_FORMAT_MULTI_MPY_V6_3_NATIVE (0) +#define PBSYS_CONFIG_HMI_NUM_SLOTS (5) +#define PBSYS_CONFIG_HMI_SLOT_0_STARTS_REPL (1) #define PBSYS_CONFIG_HOST (1) #define PBSYS_CONFIG_HOST_STDIN_BUF_SIZE (21) +#define PBSYS_CONFIG_HUB_LIGHT_MATRIX (1) +#define PBSYS_CONFIG_HUB_LIGHT_MATRIX_DISPLAY (1) #define PBSYS_CONFIG_MAIN (1) #define PBSYS_CONFIG_STORAGE (1) -#define PBSYS_CONFIG_STORAGE_NUM_SLOTS (1) +#define PBSYS_CONFIG_STORAGE_NUM_SLOTS (5) #define PBSYS_CONFIG_STORAGE_USER_DATA_SIZE (512) #define PBSYS_CONFIG_STATUS_LIGHT (1) #define PBSYS_CONFIG_STATUS_LIGHT_BATTERY (0) #define PBSYS_CONFIG_STATUS_LIGHT_BLUETOOTH (0) #define PBSYS_CONFIG_STATUS_LIGHT_STATE_ANIMATIONS (0) #define PBSYS_CONFIG_USER_PROGRAM (1) -#define PBSYS_CONFIG_USER_PROGRAM_AUTO_START (1) +#define PBSYS_CONFIG_USER_PROGRAM_AUTO_START (0) #define PBSYS_CONFIG_PROGRAM_STOP (1) diff --git a/lib/pbio/platform/prime_hub/pbsysconfig.h b/lib/pbio/platform/prime_hub/pbsysconfig.h index ad54ab504..3faf52067 100644 --- a/lib/pbio/platform/prime_hub/pbsysconfig.h +++ b/lib/pbio/platform/prime_hub/pbsysconfig.h @@ -12,6 +12,7 @@ #define PBSYS_CONFIG_BLUETOOTH_TOGGLE_BUTTON (512) // PBIO_BUTTON_RIGHT_UP, but enum value cannot be used here. #define PBSYS_CONFIG_HMI_NUM_SLOTS (5) #define PBSYS_CONFIG_HUB_LIGHT_MATRIX (1) +#define PBSYS_CONFIG_HUB_LIGHT_MATRIX_LED_ARRAY (1) #define PBSYS_CONFIG_HOST (1) #define PBSYS_CONFIG_HOST_STDIN_BUF_SIZE (64) #define PBSYS_CONFIG_MAIN (1) diff --git a/lib/pbio/sys/hmi.c b/lib/pbio/sys/hmi.c index 86671d36d..b0837ff07 100644 --- a/lib/pbio/sys/hmi.c +++ b/lib/pbio/sys/hmi.c @@ -109,7 +109,16 @@ static pbio_error_t pbsys_hmi_launch_program_with_button(pbio_os_state_t *state) } if (pressed & PBIO_BUTTON_CENTER) { - pbio_error_t err = pbsys_main_program_request_start(selected_slot, PBSYS_MAIN_PROGRAM_START_REQUEST_TYPE_HUB_UI); + + uint8_t slot = selected_slot; + #if PBSYS_CONFIG_HMI_SLOT_0_STARTS_REPL + // HACK: This is useful for testing a new hub until some + // download-and-run mechanism is implemented. + if (slot == 0) { + slot = PBIO_PYBRICKS_USER_PROGRAM_ID_REPL; + } + #endif + pbio_error_t err = pbsys_main_program_request_start(slot, PBSYS_MAIN_PROGRAM_START_REQUEST_TYPE_HUB_UI); if (err == PBIO_SUCCESS) { // Program is available so we can leave this UI thread and @@ -142,16 +151,6 @@ static pbio_error_t pbsys_hmi_launch_program_with_button(pbio_os_state_t *state) PBIO_OS_ASYNC_END(PBIO_SUCCESS); } -#if PBSYS_CONFIG_BLUETOOTH_TOGGLE -static bool pbsys_hmi_bluetooth_button_is_pressed() { - return pbdrv_button_get_pressed() & PBSYS_CONFIG_BLUETOOTH_TOGGLE_BUTTON; -} -#else -static inline bool pbsys_hmi_bluetooth_button_is_pressed() { - return false; -} -#endif - /** * Monitors Bluetooth enable button and starts/stops advertising as needed. * @@ -159,6 +158,16 @@ static inline bool pbsys_hmi_bluetooth_button_is_pressed() { */ static pbio_error_t pbsys_hmi_monitor_bluetooth_state(pbio_os_state_t *state) { + #if !PBSYS_CONFIG_BLUETOOTH + return PBIO_ERROR_NOT_SUPPORTED; + #endif + + #if PBSYS_CONFIG_BLUETOOTH_TOGGLE + bool bluetooth_button_is_pressed = pbdrv_button_get_pressed() & PBSYS_CONFIG_BLUETOOTH_TOGGLE_BUTTON; + #else + bool bluetooth_button_is_pressed = false; + #endif + PBIO_OS_ASYNC_BEGIN(state); for (;;) { @@ -192,7 +201,7 @@ static pbio_error_t pbsys_hmi_monitor_bluetooth_state(pbio_os_state_t *state) { PBIO_OS_AWAIT_WHILE(state, pbdrv_button_get_pressed()); PBIO_OS_AWAIT_UNTIL(state, pbsys_storage_settings_bluetooth_enabled_get() || - pbsys_hmi_bluetooth_button_is_pressed() || + bluetooth_button_is_pressed || pbsys_main_program_start_is_requested() ); if (pbsys_main_program_start_is_requested()) { @@ -210,7 +219,7 @@ static pbio_error_t pbsys_hmi_monitor_bluetooth_state(pbio_os_state_t *state) { // Wait for connection, program run, or bluetooth toggle. PBIO_OS_AWAIT_WHILE(state, pbdrv_button_get_pressed()); PBIO_OS_AWAIT_UNTIL(state, - pbsys_hmi_bluetooth_button_is_pressed() || + bluetooth_button_is_pressed || pbsys_main_program_start_is_requested() || pbdrv_bluetooth_is_connected(PBDRV_BLUETOOTH_CONNECTION_LE) ); diff --git a/lib/pbio/sys/light_matrix.c b/lib/pbio/sys/light_matrix.c index db564871a..43f96c691 100644 --- a/lib/pbio/sys/light_matrix.c +++ b/lib/pbio/sys/light_matrix.c @@ -9,7 +9,9 @@ #include +#include #include +#include #include #include #include @@ -32,14 +34,24 @@ static pbsys_hub_light_matrix_t pbsys_hub_light_matrix_instance; pbio_light_matrix_t *pbsys_hub_light_matrix = &pbsys_hub_light_matrix_instance.light_matrix; static pbio_error_t pbsys_hub_light_matrix_set_pixel(pbio_light_matrix_t *light_matrix, uint8_t row, uint8_t col, uint8_t brightness) { + #if PBSYS_CONFIG_HUB_LIGHT_MATRIX_LED_ARRAY // REVISIT: currently hub light matrix is hard-coded as LED array at index 0 // on all platforms pbdrv_led_array_dev_t *array; if (pbdrv_led_array_get_dev(0, &array) == PBIO_SUCCESS) { return pbdrv_led_array_set_brightness(array, row * light_matrix->size + col, brightness); } - + #elif PBSYS_CONFIG_HUB_LIGHT_MATRIX_DISPLAY + pbio_image_t *display = pbdrv_display_get_image(); + uint8_t value = brightness * (pbdrv_display_get_max_value() + 1) / 100; + const uint32_t size = PBDRV_CONFIG_DISPLAY_NUM_ROWS / PBSYS_CONFIG_HMI_NUM_SLOTS; + const uint32_t width = size * 4 / 5; + const uint32_t offset = (PBDRV_CONFIG_DISPLAY_NUM_COLS - (PBSYS_CONFIG_HMI_NUM_SLOTS * size)) / 2; + pbio_image_fill_rect(display, col * size + offset, row * size, width, width, value); + pbdrv_display_update(); return PBIO_SUCCESS; + #endif + return PBIO_ERROR_NOT_SUPPORTED; } static const pbio_light_matrix_funcs_t pbsys_hub_light_matrix_funcs = { @@ -126,19 +138,16 @@ static uint32_t pbsys_hub_light_matrix_user_program_animation_next(pbio_light_an // which we can cycle in 256 steps. static uint8_t cycle = 0; - pbdrv_led_array_dev_t *array; - if (pbdrv_led_array_get_dev(0, &array) == PBIO_SUCCESS) { - for (size_t i = 0; i < PBIO_ARRAY_SIZE(indexes); i++) { - // The pixels are spread equally across the pattern. - uint8_t offset = cycle + i * (UINT8_MAX / PBIO_ARRAY_SIZE(indexes)); - uint8_t brightness = offset > 200 ? 0 : (offset < 100 ? offset : 200 - offset); + for (size_t i = 0; i < PBIO_ARRAY_SIZE(indexes); i++) { + // The pixels are spread equally across the pattern. + uint8_t offset = cycle + i * (UINT8_MAX / PBIO_ARRAY_SIZE(indexes)); + uint8_t brightness = offset > 200 ? 0 : (offset < 100 ? offset : 200 - offset); - // Set the brightness for this pixel - pbdrv_led_array_set_brightness(array, indexes[i], brightness); - } - // This increment controls the speed of the pattern - cycle += 9; + // Set the brightness for this pixel + pbsys_hub_light_matrix_set_pixel(pbsys_hub_light_matrix, indexes[i] / 5, indexes[i] % 5, brightness); } + // This increment controls the speed of the pattern + cycle += 9; return 40; }