Skip to content

Commit

Permalink
Changes for demonstration
Browse files Browse the repository at this point in the history
- Fixed bug which can break the graph visualization due to potential overflow
- Changed the trigger timings to be usable for a solenoid
- Changed the UI to better focus on the input delay values
- Force re-enumeration when the detection mode or interface is changed
  • Loading branch information
RockyZeroFour committed Jun 19, 2024
1 parent 2166074 commit c3fee4a
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 38 deletions.
10 changes: 5 additions & 5 deletions src/config/lv_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/
# define lv_snprintf snprintf
# define lv_vsnprintf vsnprintf
#else /*LV_SPRINTF_CUSTOM*/
# define LV_SPRINTF_USE_FLOAT 0
# define LV_SPRINTF_USE_FLOAT 1
#endif /*LV_SPRINTF_CUSTOM*/

#define LV_USE_USER_DATA 1
Expand Down Expand Up @@ -326,12 +326,12 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/
/*Montserrat fonts with ASCII range and some symbols using bpp = 4
*https://fonts.google.com/specimen/Montserrat*/
#define LV_FONT_MONTSERRAT_8 0
#define LV_FONT_MONTSERRAT_10 0
#define LV_FONT_MONTSERRAT_12 1
#define LV_FONT_MONTSERRAT_10 1
#define LV_FONT_MONTSERRAT_12 0
#define LV_FONT_MONTSERRAT_14 1
#define LV_FONT_MONTSERRAT_16 1
#define LV_FONT_MONTSERRAT_16 0
#define LV_FONT_MONTSERRAT_18 0
#define LV_FONT_MONTSERRAT_20 0
#define LV_FONT_MONTSERRAT_20 1
#define LV_FONT_MONTSERRAT_22 0
#define LV_FONT_MONTSERRAT_24 0
#define LV_FONT_MONTSERRAT_26 0
Expand Down
152 changes: 123 additions & 29 deletions src/gfx_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,28 @@
#include "stdio_glue.h"
#include "usb_host.h"

#define Y_CHART_SIZE_X 410
#define Y_CHART_SIZE_X 310
#define Y_CHART_SIZE_Y 130

#define X_CHART_RANGE 1000
#define Y_CHART_TICK_MAJOR 5
#define Y_CHART_TICK_MINOR 10

#define Y_CHART_RANGE 2000
#define X_CHART_COUNT ((Y_CHART_TICK_MAJOR - 1) * Y_CHART_TICK_MINOR + 1)

lv_color_t lv_color_lightblue = LV_COLOR_MAKE(0xa6, 0xd1, 0xd1);

static lv_obj_t * chart;
static lv_obj_t * latency_label;
static lv_obj_t * latency_last_label;
static lv_obj_t * latency_average_label;
static lv_obj_t * latency_deviation_label;
static lv_obj_t * productname_label;
static lv_obj_t * manufacturer_label;
static lv_obj_t * vidpid_label;
static lv_obj_t * hid_offsets_label;
static lv_obj_t * trigger_label;
static lv_obj_t * trigger_ready_cb;

static size_t chart_point_count = 0;
static lv_coord_t chart_y_range = 0;

static lv_timer_t * trigger_timer = NULL;
Expand All @@ -54,13 +58,9 @@ LV_IMG_DECLARE(xlat_logo);

static void latency_label_update(void)
{
lv_label_set_text_fmt(latency_label, "#%lu: %ldus, avg %ldus, stdev %ldus",
xlat_get_latency_count(LATENCY_GPIO_TO_USB),
xlat_get_latency_us(LATENCY_GPIO_TO_USB),
xlat_get_average_latency(LATENCY_GPIO_TO_USB),
xlat_get_latency_standard_deviation(LATENCY_GPIO_TO_USB)
);
lv_obj_align_to(latency_label, chart, LV_ALIGN_OUT_TOP_MID, 0, 0);
lv_label_set_text_fmt(latency_last_label, "%0.3f ms", xlat_get_latency_us(LATENCY_GPIO_TO_USB) / 1000.0F);
lv_label_set_text_fmt(latency_average_label, "%0.3f ms", xlat_get_average_latency(LATENCY_GPIO_TO_USB) / 1000.0F);
lv_label_set_text_fmt(latency_deviation_label, "%ld us", xlat_get_latency_standard_deviation(LATENCY_GPIO_TO_USB));
}

void gfx_set_device_label(const char * manufacturer, const char * productname, const char *vidpid)
Expand Down Expand Up @@ -176,7 +176,6 @@ static void chart_reset(void)
lv_chart_add_series(chart, lv_color_lightblue, LV_CHART_AXIS_PRIMARY_Y);
lv_chart_set_x_start_point(chart, ser, 0);

chart_point_count = 0;
chart_y_range = Y_CHART_RANGE;
lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_Y, 0, chart_y_range);

Expand All @@ -185,11 +184,16 @@ static void chart_reset(void)

static void chart_update(uint32_t value)
{
lv_chart_set_next_value(chart, lv_chart_get_series_next(chart, NULL), (lv_coord_t)value);
// clip to the nearest rounded down 1000
#if LV_USE_LARGE_COORD
value = value > (INT32_MAX / 1000 * 1000) ? (INT32_MAX / 1000 * 1000) : value;
#else
value = value > (INT16_MAX / 1000 * 1000) ? (INT16_MAX / 1000 * 1000) : value;
#endif

chart_point_count++;
lv_chart_set_next_value(chart, lv_chart_get_series_next(chart, NULL), (lv_coord_t)value);

value = value > INT16_MAX ? INT16_MAX : value; // clip to 16-bit signed (lv_coord_t)
// can't overflow because we clipped down to the nearest 1000 within signed while value is unsigned
value = (value + 999) / 1000 * 1000; // round up to nearest 1000

// update y-axis range if needed
Expand All @@ -204,27 +208,52 @@ static void chart_update(uint32_t value)
}

/**
* Display 1000 data points with zooming and scrolling.
* See how the chart changes drawing mode (draw only vertical lines) when
* the points get too crowded.
* Override the drawing of the axis label
*/
void lv_chart_new(lv_coord_t xrange, lv_coord_t yrange)
static void chart_draw_event_cb(lv_event_t * e)
{
lv_obj_draw_part_dsc_t * dsc = lv_event_get_draw_part_dsc(e);

if (!lv_obj_draw_part_check_type(dsc, &lv_chart_class, LV_CHART_DRAW_PART_TICK_LABEL)) return;

// Change the drawing of the Y axis legend
if (dsc->id == LV_CHART_AXIS_PRIMARY_Y && dsc->text) {
lv_snprintf(dsc->text, dsc->text_length, "%0.1f", dsc->value / 1000.0F);
}
// Change the drawing of the Y axis legend
else if (dsc->id == LV_CHART_AXIS_PRIMARY_X && dsc->text) {
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));
//lv_snprintf(dsc->text, dsc->text_length, "%ld", -dsc->value);
}
}

/**
* Creates a line chart with a custom Y-axis labeling
*/
void lv_chart_new(lv_coord_t xcount, lv_coord_t yrange)
{
// Create a chart
chart = lv_chart_create(lv_scr_act());
lv_obj_set_size(chart, Y_CHART_SIZE_X, Y_CHART_SIZE_Y);
lv_obj_align(chart, LV_ALIGN_CENTER, 20, 10);
lv_obj_align(chart, LV_ALIGN_RIGHT_MID, 0, 0);
lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_Y, 0, yrange);
lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_X, 0, xrange);

// Custom axis labeling
lv_obj_add_event_cb(chart, chart_draw_event_cb, LV_EVENT_DRAW_PART_BEGIN, NULL);

// Set the amout of data points
lv_chart_set_point_count(chart, xcount);

// Do not display points on the data
lv_obj_set_style_size(chart, 0, LV_PART_INDICATOR);

lv_chart_add_series(chart, lv_color_lightblue, LV_CHART_AXIS_PRIMARY_Y);

lv_chart_set_axis_tick(chart, LV_CHART_AXIS_PRIMARY_X, 10, 5, 11, 2, true, 20);
// Y-axis: major tick every 1ms
lv_chart_set_axis_tick(chart, LV_CHART_AXIS_PRIMARY_Y, 10, 5, 5 + 1, 2, true, 60);
// Ticks & subticks for the X-axis, starts & ends with a major tick
lv_chart_set_axis_tick(chart, LV_CHART_AXIS_PRIMARY_X, 10, 5, Y_CHART_TICK_MAJOR, Y_CHART_TICK_MINOR, true, 20);

// Ticks & subticks for the Y-axis, starts & ends with a major tick
lv_chart_set_axis_tick(chart, LV_CHART_AXIS_PRIMARY_Y, 10, 5, 6, 2, true, 60);

chart_y_range = yrange;
}
Expand All @@ -233,6 +262,9 @@ void lv_chart_new(lv_coord_t xrange, lv_coord_t yrange)

static lv_style_t style_btn;
static lv_style_t style_chart;
static lv_style_t style_text_small;
static lv_style_t style_text_large;
static lv_style_t style_box;

/*Will be called when the styles of the base theme are already added
to add new styles*/
Expand Down Expand Up @@ -275,6 +307,22 @@ static void new_theme_init_and_set(void)
lv_style_set_border_width(&style_chart, 1);
lv_style_set_text_color(&style_chart, lv_color_white());

// Initialize small text
lv_style_init(&style_text_small);
lv_style_set_text_font(&style_text_small, &lv_font_montserrat_10);

// Initialize large text
lv_style_init(&style_text_large);
lv_style_set_text_font(&style_text_large, &lv_font_montserrat_20);

// Initialize box style
lv_style_init(&style_box);
lv_style_set_radius(&style_box, 5);
lv_style_set_width(&style_box, 115);
lv_style_set_height(&style_box, 50);
lv_style_set_pad_all(&style_box, 5);
lv_style_set_border_color(&style_box, lv_color_white());

/*Initialize the new theme from the current theme*/
lv_theme_t * th_act = lv_disp_get_theme(NULL);
static lv_theme_t th_new;
Expand Down Expand Up @@ -393,15 +441,61 @@ static void gfx_xlat_gui(void)
lv_label_set_text(trigger_label, "TRIGGER");
lv_obj_center(trigger_label);

// Latency label
latency_label = lv_label_create(lv_scr_act());
lv_label_set_text(latency_label, "Click to start measurement...");
lv_obj_align_to(latency_label, chart, LV_ALIGN_OUT_TOP_MID, 0, 0);
// Latency last average box
lv_obj_t * latency_average_box = lv_obj_create(lv_scr_act());
lv_obj_add_style(latency_average_box, &style_box, 0);
lv_obj_align(latency_average_box, LV_ALIGN_LEFT_MID, 0, 10);

// Latency last average label
latency_average_label = lv_label_create(latency_average_box);
lv_obj_add_style(latency_average_label, &style_text_large, 0);
lv_obj_align(latency_average_label, LV_ALIGN_TOP_RIGHT, 0, 0);
lv_label_set_text(latency_average_label, "0.000 ms");

// Description average label
lv_obj_t * description_average_label = lv_label_create(latency_average_box);
lv_obj_add_style(description_average_label, &style_text_small, 0);
lv_obj_align(description_average_label, LV_ALIGN_BOTTOM_MID, 0, 0);
lv_label_set_text(description_average_label, "Average input");

// Latency last measurement box
lv_obj_t * latency_last_box = lv_obj_create(lv_scr_act());
lv_obj_add_style(latency_last_box, &style_box, 0);
lv_obj_align_to(latency_last_box, latency_average_box, LV_ALIGN_OUT_TOP_LEFT, 0, -5);

// Latency last measurement label
latency_last_label = lv_label_create(latency_last_box);
lv_obj_add_style(latency_last_label, &style_text_large, 0);
lv_obj_align(latency_last_label, LV_ALIGN_TOP_RIGHT, 0, 0);
lv_label_set_text(latency_last_label, "0.000 ms");

// Description last label
lv_obj_t * description_last_label = lv_label_create(latency_last_box);
lv_obj_add_style(description_last_label, &style_text_small, 0);
lv_obj_align(description_last_label, LV_ALIGN_BOTTOM_MID, 0, 0);
lv_label_set_text(description_last_label, "Latest input");

// Latency standard deviation box
lv_obj_t * latency_deviation_box = lv_obj_create(lv_scr_act());
lv_obj_add_style(latency_deviation_box, &style_box, 0);
lv_obj_align_to(latency_deviation_box, latency_average_box, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 5);

// Latency standard deviation label
latency_deviation_label = lv_label_create(latency_deviation_box);
lv_obj_add_style(latency_deviation_label, &style_text_large, 0);
lv_obj_align(latency_deviation_label, LV_ALIGN_TOP_RIGHT, 0, 0);
lv_label_set_text(latency_deviation_label, "0 us");

// Description last label
lv_obj_t * description_deviation_label = lv_label_create(latency_deviation_box);
lv_obj_add_style(description_deviation_label, &style_text_small, 0);
lv_obj_align(description_deviation_label, LV_ALIGN_BOTTOM_MID, 0, 0);
lv_label_set_text(description_deviation_label, "Standard deviation");

///////////
// CHART //
///////////
lv_chart_new(X_CHART_RANGE, Y_CHART_RANGE);
lv_chart_new(X_CHART_COUNT, Y_CHART_RANGE);
lv_chart_add_cursor(chart, lv_color_white(), LV_DIR_TOP);
}

Expand Down
5 changes: 5 additions & 0 deletions src/usb/usb_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ void MX_USB_HOST_Init(void)
}
}

void MX_USB_HOST_ReEnumeration(void)
{
USBH_ReEnumerate(&hUsbHostHS);
}

/*
* user callback definition
*/
Expand Down
1 change: 1 addition & 0 deletions src/usb/usb_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ typedef enum {

/** @brief USB Host initialization function. */
void MX_USB_HOST_Init(void);
void MX_USB_HOST_ReEnumeration(void);

void usb_host_set_product_string(const char * product);
char * usb_host_get_product_string(void);
Expand Down
9 changes: 7 additions & 2 deletions src/xlat.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "stm32f7xx_hal_tim.h"
#include "hardware_config.h"
#include "stdio_glue.h"
#include "usb_host.h"

// LUFA HID Parser
#define __INCLUDE_FROM_USB_DRIVER // NOLINT(*-reserved-identifier)
Expand All @@ -44,7 +45,7 @@ static volatile uint_fast8_t gpio_irq_consumer = 0;

// SETTINGS
volatile bool xlat_initialized = false;
static xlat_mode_t xlat_mode = XLAT_MODE_CLICK;
static xlat_mode_t xlat_mode = XLAT_MODE_KEY;
static uint8_t hid_reportid = 0;
static bool auto_trigger_level_high = false;
static xlat_interface_t xlat_interface = XLAT_INTERFACE_AUTO;
Expand All @@ -58,7 +59,7 @@ static uint8_t found_interface = 0xFF;
// \__/ \__/ \__/ \__/
//
// Therefore, take a large enough time window to debounce the GPIO interrupt.
#define GPIO_IRQ_HOLDOFF_US (50 * 1000) // 20ms;
#define GPIO_IRQ_HOLDOFF_US (200 * 1000) // 200 ms;
static uint32_t gpio_irq_holdoff_us = GPIO_IRQ_HOLDOFF_US;
static TimerHandle_t xlat_timer_handle;

Expand Down Expand Up @@ -660,6 +661,8 @@ static void xlat_timer_callback(TimerHandle_t xTimer)
void xlat_set_mode(enum xlat_mode mode)
{
xlat_mode = mode;

MX_USB_HOST_ReEnumeration();
}

enum xlat_mode xlat_get_mode(void)
Expand Down Expand Up @@ -696,6 +699,8 @@ bool xlat_auto_trigger_level_is_high(void)
void xlat_set_interface_selection(xlat_interface_t number)
{
xlat_interface = number;

MX_USB_HOST_ReEnumeration();
}

xlat_interface_t xlat_get_interface_selection()
Expand Down
4 changes: 2 additions & 2 deletions src/xlat.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
#include <stdint.h>
#include "src/usb/usbh_def.h"

#define AUTO_TRIGGER_PERIOD_MS (150)
#define AUTO_TRIGGER_PRESSED_PERIOD_MS (30)
#define AUTO_TRIGGER_PERIOD_MS (500)
#define AUTO_TRIGGER_PRESSED_PERIOD_MS (100)

typedef struct hid_event {
USBH_HandleTypeDef *phost;
Expand Down

0 comments on commit c3fee4a

Please sign in to comment.