99#if PBSYS_CONFIG_HMI_EV3_UI
1010
1111#include <pbsys/main.h>
12- #include "storage.h"
12+ #include <pbsys/status.h>
1313
1414#include <pbdrv/display.h>
1515
1616#include <pbio/light_animation.h>
17+ #include <pbio/battery.h>
1718#include <pbio/button.h>
1819#include <pbio/image.h>
1920#include <pbio/version.h>
21+ #include <pbio/int_math.h>
2022
2123#include "hmi_ev3_ui.h"
2224#include "pbio_image_media.h"
25+ #include "storage.h"
2326
2427#define BLACK (3)
2528#define WHITE (0)
@@ -299,6 +302,22 @@ void pbsys_hmi_ev3_ui_handle_error(pbio_error_t err) {
299302// Draw the UI from the state without modifying it.
300303// -----------------------------------------------------------------------------
301304
305+ /**
306+ * Draw text relative to the horizontal center.
307+ *
308+ * @param [in] font Font to use for drawing.
309+ * @param [in] x X coordinate of the baseline relative to if centered text.
310+ * @param [in] y Y coordinate of the baseline.
311+ * @param [in] text Text string.
312+ */
313+ static void pbsys_hmi_ev3_ui_draw_centered_text (const pbio_font_t * font , const char * text , int x_offset , int y ) {
314+ pbio_image_t * display = pbdrv_display_get_image ();
315+ pbio_image_rect_t rect ;
316+ pbio_image_bbox_text (font , text , strlen (text ), & rect );
317+ int x = (display -> width - rect .width ) / 2 + x_offset ;
318+ pbio_image_draw_text (display , & pbio_font_terminus_normal_16 , x , y , text , strlen (text ), BLACK );
319+ }
320+
302321/**
303322 * Draws the overlay.
304323 *
@@ -345,10 +364,7 @@ static void pbsys_hmi_ev3_ui_draw_overlay(pbsys_hmi_ev3_ui_overlay_type_t overla
345364 case PBSYS_HMI_EV3_UI_OVERLAY_COMING_SOON :
346365 pbio_image_draw_image_transparent_from_monochrome (display , & pbio_image_media_accept24_fill , 76 , bar_y + 3 , BLACK );
347366 const char * text = overlay == PBSYS_HMI_EV3_UI_OVERLAY_NO_PROGRAM ? "No program!" : "Coming soon!" ;
348- pbio_image_rect_t rect ;
349- pbio_image_bbox_text (& pbio_font_liberationsans_regular_14 , text , strlen (text ), & rect );
350- pbio_image_draw_text (display , & pbio_font_liberationsans_regular_14 ,
351- (178 - rect .width ) / 2 , bar_y - 16 , text , strlen (text ), BLACK );
367+ pbsys_hmi_ev3_ui_draw_centered_text (& pbio_font_liberationsans_regular_14 , text , 0 , bar_y - 16 );
352368 default :
353369 break ;
354370 }
@@ -374,9 +390,6 @@ void pbsys_hmi_ev3_ui_draw(void) {
374390 pbio_image_fill_rect (display , 172 , 41 , 6 , 20 * 4 , WHITE );
375391 }
376392
377- // Draw upper status bar.
378- pbio_image_draw_hline (display , 0 , 10 , 178 , BLACK );
379-
380393 // Draw box around tab entries.
381394 pbio_image_draw_rect (display , 1 , 38 , 176 , 89 , BLACK );
382395 pbio_image_draw_rounded_rect (display , 0 , 37 , 178 , 91 , 1 , BLACK );
@@ -421,6 +434,24 @@ void pbsys_hmi_ev3_ui_draw(void) {
421434 // Settings icon.
422435 pbio_image_draw_image_transparent_from_monochrome (display , & pbio_image_media_wrench17 , 101 , 16 , BLACK );
423436
437+ // Draw upper status bar.
438+ pbio_image_draw_hline (display , 0 , 10 , 178 , BLACK );
439+
440+ // Battery indicator: REVISIT: better percentage estimation at driver level.
441+ const int vmin = 5800 ;
442+ const int vmax = 8000 ;
443+ int voltage = pbio_int_math_bind (pbio_battery_get_average_voltage (), vmin , vmax );
444+ int bars = (voltage - vmin ) * 11 / (vmax - vmin );
445+ pbio_image_draw_rect (display , 160 , 1 , 15 , 8 , BLACK );
446+ pbio_image_draw_vline (display , 174 , 4 , 2 , WHITE );
447+ pbio_image_draw_vline (display , 175 , 3 , 4 , BLACK );
448+ pbio_image_fill_rect (display , 162 , 3 , bars , 4 , BLACK );
449+
450+ // USB if connected.
451+ if (pbsys_status_test (PBIO_PYBRICKS_STATUS_USB_HOST_CONNECTED )) {
452+ pbio_image_draw_image_transparent_from_monochrome (display , & pbio_image_media_usb_host , 130 , 2 , BLACK );
453+ }
454+
424455 // Draw the overlay on top of everything else.
425456 pbsys_hmi_ev3_ui_draw_overlay (state .overlay );
426457
@@ -485,7 +516,7 @@ static void pbsys_hmi_ev3_ui_draw_pybricks_logo(uint32_t x, uint32_t y, uint32_t
485516#define ANIMATION_BLINK_MS (300)
486517#define ANIMATION_BLINK_AT_MS (2000)
487518#define ANIMATION_UP_MS (800 / 2)
488- #define ANIMATION_DY (15 )
519+ #define ANIMATION_DY (12 )
489520
490521/**
491522 * Elapsed time in animation.
@@ -546,11 +577,7 @@ void pbsys_hmi_ev3_ui_run_animation_start(void) {
546577 pbsys_main_program_get_info (& id , & type );
547578 if (id < PBSYS_CONFIG_HMI_NUM_SLOTS ) {
548579 const char * name = pbsys_hmi_ev3_ui_get_program_name_at_slot (id );
549- pbio_image_rect_t rect ;
550- pbio_image_bbox_text (& pbio_font_terminus_normal_16 , name , strlen (name ), & rect );
551- uint8_t x = rect .width > 178 ? 0 : (178 - rect .width ) / 2 ;
552- x = x < 10 ? x : x - 10 ;
553- pbio_image_draw_text (display , & pbio_font_terminus_normal_16 , x , 116 , name , strlen (name ), BLACK );
580+ pbsys_hmi_ev3_ui_draw_centered_text (& pbio_font_terminus_normal_16 , name , -10 , 116 );
554581 }
555582 // Not updating display here. First animation frame will do that.
556583}
0 commit comments