2525#include "stdio_glue.h"
2626#include "usb_host.h"
2727
28- #define Y_CHART_SIZE_X 410
28+ #define Y_CHART_SIZE_X 310
2929#define Y_CHART_SIZE_Y 130
3030
3131#define Y_CHART_RANGE 2000
32+ #define Y_CHART_TICK_MAJOR 5
33+ #define Y_CHART_TICK_MINOR 10
3234
3335#define X_CHART_TICKS_MAJOR 11
3436#define X_CHART_TICKS_MINOR 1
3537#define Y_CHART_TICKS_MAJOR 6
3638#define Y_CHART_TICKS_MINOR 2
3739
40+ #define X_CHART_COUNT ((Y_CHART_TICK_MAJOR - 1) * Y_CHART_TICK_MINOR + 1)
41+
3842lv_color_t lv_color_lightblue = LV_COLOR_MAKE (0xa6 , 0xd1 , 0xd1 );
3943
4044static lv_obj_t * chart ;
41- static lv_obj_t * latency_label ;
45+ static lv_obj_t * latency_last_label ;
46+ static lv_obj_t * latency_average_label ;
47+ static lv_obj_t * latency_deviation_label ;
4248static lv_obj_t * productname_label ;
4349static lv_obj_t * manufacturer_label ;
4450static lv_obj_t * vidpid_label ;
4551static lv_obj_t * hid_offsets_label ;
4652static lv_obj_t * trigger_label ;
4753static lv_obj_t * trigger_ready_cb ;
4854
49- static size_t chart_point_count = 0 ;
5055static lv_coord_t chart_y_range = 0 ;
5156
5257static lv_timer_t * trigger_timer = NULL ;
@@ -58,13 +63,9 @@ LV_IMG_DECLARE(xlat_logo);
5863
5964static void latency_label_update (void )
6065{
61- lv_label_set_text_fmt (latency_label , "#%lu: %ldus, avg %ldus, stdev %ldus" ,
62- xlat_get_latency_count (LATENCY_GPIO_TO_USB ),
63- xlat_get_latency_us (LATENCY_GPIO_TO_USB ),
64- xlat_get_average_latency (LATENCY_GPIO_TO_USB ),
65- xlat_get_latency_standard_deviation (LATENCY_GPIO_TO_USB )
66- );
67- lv_obj_align_to (latency_label , chart , LV_ALIGN_OUT_TOP_MID , 0 , 0 );
66+ lv_label_set_text_fmt (latency_last_label , "%0.3f ms" , xlat_get_latency_us (LATENCY_GPIO_TO_USB ) / 1000.0F );
67+ lv_label_set_text_fmt (latency_average_label , "%0.3f ms" , xlat_get_average_latency (LATENCY_GPIO_TO_USB ) / 1000.0F );
68+ lv_label_set_text_fmt (latency_deviation_label , "%ld us" , xlat_get_latency_standard_deviation (LATENCY_GPIO_TO_USB ));
6869}
6970
7071void gfx_set_device_label (const char * manufacturer , const char * productname , const char * vidpid )
@@ -73,7 +74,7 @@ void gfx_set_device_label(const char * manufacturer, const char * productname, c
7374 lv_label_set_text (manufacturer_label , manufacturer );
7475 lv_label_set_text (productname_label , productname );
7576
76- lv_obj_align (manufacturer_label , LV_ALIGN_TOP_RIGHT , -5 , 5 );
77+ lv_obj_align (manufacturer_label , LV_ALIGN_TOP_RIGHT , 0 , 0 );
7778 lv_obj_align_to (vidpid_label , manufacturer_label , LV_ALIGN_OUT_LEFT_BOTTOM , -5 , 0 );
7879 lv_obj_align_to (productname_label , manufacturer_label , LV_ALIGN_OUT_BOTTOM_RIGHT , 0 , 5 );
7980}
@@ -180,7 +181,6 @@ static void chart_reset(void)
180181 lv_chart_add_series (chart , lv_color_lightblue , LV_CHART_AXIS_PRIMARY_Y );
181182 lv_chart_set_x_start_point (chart , ser , 0 );
182183
183- chart_point_count = 0 ;
184184 chart_y_range = Y_CHART_RANGE ;
185185 lv_chart_set_range (chart , LV_CHART_AXIS_PRIMARY_Y , 0 , chart_y_range );
186186
@@ -189,8 +189,6 @@ static void chart_reset(void)
189189
190190static void chart_update (uint32_t value )
191191{
192- chart_point_count ++ ;
193-
194192 // clip to the nearest rounded down 1000
195193#if LV_USE_LARGE_COORD
196194 value = value > (INT32_MAX / 1000 * 1000 ) ? (INT32_MAX / 1000 * 1000 ) : value ;
@@ -215,28 +213,50 @@ static void chart_update(uint32_t value)
215213}
216214
217215/**
218- * Display 1000 data points with zooming and scrolling.
219- * See how the chart changes drawing mode (draw only vertical lines) when
220- * the points get too crowded.
216+ * Override the drawing of the axis label
217+ */
218+ static void chart_draw_event_cb (lv_event_t * e )
219+ {
220+ lv_obj_draw_part_dsc_t * dsc = lv_event_get_draw_part_dsc (e );
221+ if (!lv_obj_draw_part_check_type (dsc , & lv_chart_class , LV_CHART_DRAW_PART_TICK_LABEL )) return ;
222+ // Change the drawing of the Y axis legend
223+ if (dsc -> id == LV_CHART_AXIS_PRIMARY_Y && dsc -> text ) {
224+ lv_snprintf (dsc -> text , dsc -> text_length , "%0.1f" , dsc -> value / 1000.0F );
225+ }
226+ // Change the drawing of the Y axis legend
227+ else if (dsc -> id == LV_CHART_AXIS_PRIMARY_X && dsc -> text ) {
228+ lv_snprintf (dsc -> text , dsc -> text_length , "%ld" , xlat_get_latency_count (LATENCY_GPIO_TO_USB ) + dsc -> value * Y_CHART_TICK_MINOR - ((Y_CHART_TICK_MAJOR - 1 ) * Y_CHART_TICK_MINOR ));
229+ //lv_snprintf(dsc->text, dsc->text_length, "%ld", -dsc->value);
230+ }
231+ }
232+
233+ /**
234+ * Creates a line chart with a custom Y-axis labeling
221235 */
222- void lv_chart_new (lv_coord_t yrange )
236+ void lv_chart_new (lv_coord_t xcount , lv_coord_t yrange )
223237{
224238 // Create a chart
225239 chart = lv_chart_create (lv_scr_act ());
226240 lv_obj_set_size (chart , Y_CHART_SIZE_X , Y_CHART_SIZE_Y );
227- lv_obj_align (chart , LV_ALIGN_CENTER , 20 , 10 );
241+ lv_obj_align (chart , LV_ALIGN_RIGHT_MID , 0 , 0 );
228242 lv_chart_set_range (chart , LV_CHART_AXIS_PRIMARY_Y , 0 , yrange );
229243
230244 // Do not display points on the data
231245 lv_obj_set_style_size (chart , 0 , LV_PART_INDICATOR );
232246
233247 lv_chart_add_series (chart , lv_color_lightblue , LV_CHART_AXIS_PRIMARY_Y );
234248
235- lv_chart_set_axis_tick (chart , LV_CHART_AXIS_PRIMARY_X , 10 , 5 , X_CHART_TICKS_MAJOR , X_CHART_TICKS_MINOR , true, 20 );
236- lv_chart_set_axis_tick (chart , LV_CHART_AXIS_PRIMARY_Y , 10 , 5 , Y_CHART_TICKS_MAJOR , Y_CHART_TICKS_MINOR , true, 60 );
249+ // Ticks & subticks for the X-axis, starts & ends with a major tick
250+ lv_chart_set_axis_tick (chart , LV_CHART_AXIS_PRIMARY_X , 10 , 5 , Y_CHART_TICK_MAJOR , Y_CHART_TICK_MINOR , true, 20 );
251+
252+ // Ticks & subticks for the Y-axis, starts & ends with a major tick
253+ lv_chart_set_axis_tick (chart , LV_CHART_AXIS_PRIMARY_Y , 10 , 5 , 6 , 2 , true, 60 );
237254
238- // Set the amount of data points according to the X axis tick count
239- lv_chart_set_point_count (chart , (X_CHART_TICKS_MAJOR - 1 ) * X_CHART_TICKS_MINOR + 1 );
255+ // Custom axis labeling
256+ lv_obj_add_event_cb (chart , chart_draw_event_cb , LV_EVENT_DRAW_PART_BEGIN , NULL );
257+
258+ // Set the amout of data points
259+ lv_chart_set_point_count (chart , xcount );
240260
241261 chart_y_range = yrange ;
242262}
@@ -245,6 +265,9 @@ void lv_chart_new(lv_coord_t yrange)
245265
246266static lv_style_t style_btn ;
247267static lv_style_t style_chart ;
268+ static lv_style_t style_text_small ;
269+ static lv_style_t style_text_large ;
270+ static lv_style_t style_box ;
248271
249272/*Will be called when the styles of the base theme are already added
250273 to add new styles*/
@@ -287,6 +310,22 @@ static void new_theme_init_and_set(void)
287310 lv_style_set_border_width (& style_chart , 1 );
288311 lv_style_set_text_color (& style_chart , lv_color_white ());
289312
313+ // Initialize small text
314+ lv_style_init (& style_text_small );
315+ lv_style_set_text_font (& style_text_small , & lv_font_montserrat_10 );
316+
317+ // Initialize large text
318+ lv_style_init (& style_text_large );
319+ lv_style_set_text_font (& style_text_large , & lv_font_montserrat_20 );
320+
321+ // Initialize box style
322+ lv_style_init (& style_box );
323+ lv_style_set_radius (& style_box , 5 );
324+ lv_style_set_width (& style_box , 115 );
325+ lv_style_set_height (& style_box , 50 );
326+ lv_style_set_pad_all (& style_box , 5 );
327+ lv_style_set_border_color (& style_box , lv_color_white ());
328+
290329 /*Initialize the new theme from the current theme*/
291330 lv_theme_t * th_act = lv_disp_get_theme (NULL );
292331 static lv_theme_t th_new ;
@@ -302,19 +341,33 @@ static void new_theme_init_and_set(void)
302341
303342void gfx_set_byte_offsets_text (void )
304343{
305- char text [100 ];
344+ char text [100 ];
306345 hid_data_location_t * button = xlat_get_button_location ();
307346 hid_data_location_t * x = xlat_get_x_location ();
308347 hid_data_location_t * y = xlat_get_y_location ();
309348 hid_data_location_t * key = xlat_get_key_location ();
310349 uint8_t interface = xlat_get_found_interface ();
350+ uint16_t polling_time = usb_host_get_polling_time_in_micro_frames ();
351+ char time [8 ];
352+
353+ // Get the polling time
354+ if (polling_time < 8 )
355+ {
356+ // Print out the fraction of the millisecond
357+ sprintf (time , "%dus" , polling_time * 125 );
358+ }
359+ else
360+ {
361+ // Here it should be only full millisecond
362+ sprintf (time , "%dms" , polling_time / 8 );
363+ }
311364
312365 if (x -> found && y -> found && XLAT_MODE_MOTION == xlat_get_mode ()) {
313- sprintf (text , "Motion Data (#%d): id%d motion@%d,%d" , interface , xlat_get_reportid (), x -> byte_offset , y -> byte_offset );
366+ sprintf (text , "Motion Data (#%d@%s ): id%d motion@%d,%d" , interface , time , xlat_get_reportid (), x -> byte_offset , y -> byte_offset );
314367 } else if (button -> found && XLAT_MODE_CLICK == xlat_get_mode ()) {
315- sprintf (text , "Button Data (#%d): id%d click@%d" , interface , xlat_get_reportid (), button -> byte_offset );
368+ sprintf (text , "Button Data (#%d@%s ): id%d click@%d" , interface , time , xlat_get_reportid (), button -> byte_offset );
316369 } else if (key -> found && XLAT_MODE_KEY == xlat_get_mode ()) {
317- sprintf (text , "Keyboard Data (#%d): id%d pressed@%d" , interface , xlat_get_reportid (), key -> byte_offset );
370+ sprintf (text , "Keyboard Data (#%d@%s ): id%d pressed@%d" , interface , time , xlat_get_reportid (), key -> byte_offset );
318371 } else {
319372 // offsets not found
320373 sprintf (text , (XLAT_MODE_KEY == xlat_get_mode ()) ? "Keyboard Data: offsets not found" : "Mouse Data: offsets not found" );
@@ -335,7 +388,7 @@ static void gfx_xlat_gui(void)
335388 // Draw logo
336389 lv_obj_t * logo = lv_img_create (lv_scr_act ());
337390 lv_img_set_src (logo , & xlat_logo );
338- lv_obj_align (logo , LV_ALIGN_TOP_LEFT , 12 , 5 );
391+ lv_obj_align (logo , LV_ALIGN_TOP_LEFT , 10 , 10 );
339392
340393 ///////////////////////////
341394 // DEVICE INFO TOP RIGHT //
@@ -407,15 +460,61 @@ static void gfx_xlat_gui(void)
407460 lv_label_set_text (trigger_label , "TRIGGER" );
408461 lv_obj_center (trigger_label );
409462
410- // Latency label
411- latency_label = lv_label_create (lv_scr_act ());
412- lv_label_set_text (latency_label , "Click to start measurement..." );
413- lv_obj_align_to (latency_label , chart , LV_ALIGN_OUT_TOP_MID , 0 , 0 );
463+ // Latency last average box
464+ lv_obj_t * latency_average_box = lv_obj_create (lv_scr_act ());
465+ lv_obj_add_style (latency_average_box , & style_box , 0 );
466+ lv_obj_align (latency_average_box , LV_ALIGN_LEFT_MID , 0 , 10 );
467+
468+ // Latency last average label
469+ latency_average_label = lv_label_create (latency_average_box );
470+ lv_obj_add_style (latency_average_label , & style_text_large , 0 );
471+ lv_obj_align (latency_average_label , LV_ALIGN_TOP_RIGHT , 0 , 0 );
472+ lv_label_set_text (latency_average_label , "0.000 ms" );
473+
474+ // Description average label
475+ lv_obj_t * description_average_label = lv_label_create (latency_average_box );
476+ lv_obj_add_style (description_average_label , & style_text_small , 0 );
477+ lv_obj_align (description_average_label , LV_ALIGN_BOTTOM_MID , 0 , 0 );
478+ lv_label_set_text (description_average_label , "Average input" );
479+
480+ // Latency last measurement box
481+ lv_obj_t * latency_last_box = lv_obj_create (lv_scr_act ());
482+ lv_obj_add_style (latency_last_box , & style_box , 0 );
483+ lv_obj_align_to (latency_last_box , latency_average_box , LV_ALIGN_OUT_TOP_LEFT , 0 , -5 );
484+
485+ // Latency last measurement label
486+ latency_last_label = lv_label_create (latency_last_box );
487+ lv_obj_add_style (latency_last_label , & style_text_large , 0 );
488+ lv_obj_align (latency_last_label , LV_ALIGN_TOP_RIGHT , 0 , 0 );
489+ lv_label_set_text (latency_last_label , "0.000 ms" );
490+
491+ // Description last label
492+ lv_obj_t * description_last_label = lv_label_create (latency_last_box );
493+ lv_obj_add_style (description_last_label , & style_text_small , 0 );
494+ lv_obj_align (description_last_label , LV_ALIGN_BOTTOM_MID , 0 , 0 );
495+ lv_label_set_text (description_last_label , "Latest input" );
496+
497+ // Latency standard deviation box
498+ lv_obj_t * latency_deviation_box = lv_obj_create (lv_scr_act ());
499+ lv_obj_add_style (latency_deviation_box , & style_box , 0 );
500+ lv_obj_align_to (latency_deviation_box , latency_average_box , LV_ALIGN_OUT_BOTTOM_LEFT , 0 , 5 );
501+
502+ // Latency standard deviation label
503+ latency_deviation_label = lv_label_create (latency_deviation_box );
504+ lv_obj_add_style (latency_deviation_label , & style_text_large , 0 );
505+ lv_obj_align (latency_deviation_label , LV_ALIGN_TOP_RIGHT , 0 , 0 );
506+ lv_label_set_text (latency_deviation_label , "0 us" );
507+
508+ // Description last label
509+ lv_obj_t * description_deviation_label = lv_label_create (latency_deviation_box );
510+ lv_obj_add_style (description_deviation_label , & style_text_small , 0 );
511+ lv_obj_align (description_deviation_label , LV_ALIGN_BOTTOM_MID , 0 , 0 );
512+ lv_label_set_text (description_deviation_label , "Standard deviation" );
414513
415514 ///////////
416515 // CHART //
417516 ///////////
418- lv_chart_new (Y_CHART_RANGE );
517+ lv_chart_new (X_CHART_COUNT , Y_CHART_RANGE );
419518 lv_chart_add_cursor (chart , lv_color_white (), LV_DIR_TOP );
420519}
421520
0 commit comments