From ffe8130e34b51c5b6ba07fb3799650ac8b5e13c3 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 28 Sep 2019 17:31:36 -0600 Subject: [PATCH 001/175] Invert color feature is an option --- opendps/Makefile | 4 ++++ opendps/opendps.c | 2 ++ 2 files changed, 6 insertions(+) diff --git a/opendps/Makefile b/opendps/Makefile index 44fd065e..f3ef7808 100644 --- a/opendps/Makefile +++ b/opendps/Makefile @@ -52,6 +52,9 @@ CL_ENABLE ?= 1 # Enable function generator mode FUNCGEN_ENABLE ?= 1 +# Enable invert color feature +CONFIG_INVERT_ENABLE ?= 0 + GIT_VERSION := $(shell git describe --abbrev=4 --dirty --always --tags) CFLAGS = -I. -DGIT_VERSION=\"$(GIT_VERSION)\" -Wno-missing-braces @@ -65,6 +68,7 @@ CFLAGS += \ -DCOLOR_VOLTAGE=$(COLOR_VOLTAGE) \ -DCOLOR_AMPERAGE=$(COLOR_AMPERAGE) \ -DCOLOR_INPUT=$(COLOR_INPUT) \ + -DCONFIG_INVERT_ENABLE=$(CONFIG_INVERT_ENABLE) \ -D$(MODEL) # Application linker script diff --git a/opendps/opendps.c b/opendps/opendps.c index 784843e7..756cd4db 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -470,10 +470,12 @@ static void ui_handle_event(event_t event, uint8_t data) if (event == event_rot_press && data == press_long) { opendps_lock(!is_locked); return; +#ifdef CONFIG_INVERT_ENABLE } else if (event == event_button_sel && data == press_long) { tft_invert(!tft_is_inverted()); write_past_settings(); return; +#endif // CONFIG_INVERT_ENABLE } if (is_locked) { From 66067c5160441c4b9e2dbe26974e0cf20b869c2c Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 28 Sep 2019 18:16:22 -0600 Subject: [PATCH 002/175] Added custom event handler for screens --- opendps/uui.c | 24 ++++++++++++++++++++++++ opendps/uui.h | 32 +++++++++++++++++++++----------- 2 files changed, 45 insertions(+), 11 deletions(-) diff --git a/opendps/uui.c b/opendps/uui.c index f44d0ef7..05943b90 100644 --- a/opendps/uui.c +++ b/opendps/uui.c @@ -129,6 +129,26 @@ static void focus_switch(ui_item_t *item) } } +/** + * @brief Focus on a given user interface item + * + * @param ui The user interface + * @param item The user interface item to focus on + */ +void uui_focus(uui_t *ui, ui_item_t *item) { + ui_screen_t *screen = ui->screens[ui->cur_screen]; + + for (uint8_t i = 0; i < screen->num_items; i++) { + if (screen->items[i] == item) { + screen->cur_item = i; + break; + } + } + + focus_switch(item); +} + + void uui_handle_screen_event(uui_t *ui, event_t event) { assert(ui); @@ -141,6 +161,10 @@ void uui_handle_screen_event(uui_t *ui, event_t event) return; } + // If the screen handled the event, do nothing. + if (ui->screens[ui->cur_screen]->event && ui->screens[ui->cur_screen]->event(ui, event)) + return; + switch(event) { case event_rot_left_set: uui_prev_screen(ui); diff --git a/opendps/uui.h b/opendps/uui.h index f4c4b2d1..979dc939 100644 --- a/opendps/uui.h +++ b/opendps/uui.h @@ -149,6 +149,17 @@ typedef struct ui_item_t { */ #define MCALL(item, operation, ...) ((ui_item_t*) (item))->operation((ui_item_t*) item, ##__VA_ARGS__) +/** + * A UI consists of several screens + */ +typedef struct { + uint8_t num_screens; + uint8_t cur_screen; + bool is_visible; + ui_screen_t *screens[MAX_SCREENS]; + past_t *past; +} uui_t; + /** * A screen has a name and holds num_items UI items */ @@ -166,6 +177,7 @@ struct ui_screen { void (*activated)(void); /** Called when the screen is switched to */ void (*deactivated)(void); /** Called when the screen is about to be changed from */ void (*enable)(bool _enable); /** Called when the enable button is pressed */ + bool (*event)(uui_t *ui, event_t event); /** Called when an event occurs (eg. button press). Return false if unhandled so main UI can handle it */ void (*tick)(void); /** Called periodically allowing the UI to do house keeping */ void (*past_save)(past_t *past); void (*past_restore)(past_t *past); @@ -174,17 +186,6 @@ struct ui_screen { ui_item_t *items[]; }; -/** - * A UI consists of several screens - */ -typedef struct { - uint8_t num_screens; - uint8_t cur_screen; - bool is_visible; - ui_screen_t *screens[MAX_SCREENS]; - past_t *past; -} uui_t; - /** * @brief Initialize the UUI instance * @@ -273,4 +274,13 @@ void uui_show(uui_t *ui, bool show); */ void uui_disable_cur_screen(uui_t *ui); +/** + * @brief Focus on a given user interface item + * + * @param ui The user interface + * @param item The user interface item to focus on + */ +void uui_focus(uui_t *ui, ui_item_t *item); + + #endif // __UUI_H__ From 788d6964b852553be8e83340a2592187f2db5b62 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 28 Sep 2019 20:27:26 -0600 Subject: [PATCH 003/175] Added func_dpsmode display feature --- opendps/Makefile | 15 +- opendps/func_dpsmode.c | 585 ++++++++++++++++++++++++++++++++++ opendps/func_dpsmode.h | 38 +++ opendps/gen_lookup.py | 2 +- opendps/gfx-ccbar.c | 38 +++ opendps/gfx-ccbar.h | 13 + opendps/gfx-cvbar.c | 38 +++ opendps/gfx-cvbar.h | 13 + opendps/gfx-iconpower.c | 38 +++ opendps/gfx-iconpower.h | 13 + opendps/gfx/png/ccbar.png | Bin 0 -> 993 bytes opendps/gfx/png/cvbar.png | Bin 0 -> 1012 bytes opendps/gfx/png/iconpower.png | Bin 0 -> 1204 bytes opendps/opendps.c | 9 +- opendps/opendps.h | 4 + opendps/uui_number.c | 4 + 16 files changed, 805 insertions(+), 5 deletions(-) create mode 100644 opendps/func_dpsmode.c create mode 100644 opendps/func_dpsmode.h create mode 100644 opendps/gfx-ccbar.c create mode 100644 opendps/gfx-ccbar.h create mode 100644 opendps/gfx-cvbar.c create mode 100644 opendps/gfx-cvbar.h create mode 100644 opendps/gfx-iconpower.c create mode 100644 opendps/gfx-iconpower.h create mode 100644 opendps/gfx/png/ccbar.png create mode 100644 opendps/gfx/png/cvbar.png create mode 100644 opendps/gfx/png/iconpower.png diff --git a/opendps/Makefile b/opendps/Makefile index 44fd065e..b92fd799 100644 --- a/opendps/Makefile +++ b/opendps/Makefile @@ -28,7 +28,7 @@ DEBUG ?= 0 METER_FONT_FILE ?= gfx/Ubuntu-C.ttf METER_FONT_SMALL_SIZE ?= 18 METER_FONT_MEDIUM_SIZE ?= 24 -METER_FONT_LARGE_SIZE ?= 48 +METER_FONT_LARGE_SIZE ?= 38 FULL_FONT_FILE ?= gfx/ProggyClean.ttf FULL_FONT_SMALL_SIZE ?= 16 @@ -38,11 +38,15 @@ COLORSPACE ?= 0 # Colors for the main UI elements -- see ili9163c.h for list of colors COLOR_VOLTAGE ?= WHITE COLOR_AMPERAGE ?= WHITE +COLOR_WATTAGE ?= WHITE COLOR_INPUT ?= WHITE # Optional tinting for UI elements TINT ?= ffffff +# Enable DPS-look-alike mode +DPSMODE_ENABLE ?= 1 + # Enable CC mode CC_ENABLE ?= 1 @@ -64,6 +68,7 @@ CFLAGS += \ -DCOLORSPACE=$(COLORSPACE) \ -DCOLOR_VOLTAGE=$(COLOR_VOLTAGE) \ -DCOLOR_AMPERAGE=$(COLOR_AMPERAGE) \ + -DCOLOR_WATTAGE=$(COLOR_WATTAGE) \ -DCOLOR_INPUT=$(COLOR_INPUT) \ -D$(MODEL) @@ -97,6 +102,9 @@ OBJS = \ gfx-crosshair.o \ gfx-cv.o \ gfx-cl.o \ + gfx-iconpower.o \ + gfx-cvbar.o \ + gfx-ccbar.o \ gfx-padlock.o \ gfx-power.o \ gfx-thermometer.o \ @@ -122,6 +130,11 @@ ifeq ($(CL_ENABLE),1) OBJS += func_cl.o endif +ifeq ($(DPSMODE_ENABLE),1) + CFLAGS +=-DCONFIG_DPSMODE_ENABLE + OBJS += func_dpsmode.o +endif + ifeq ($(FUNCGEN_ENABLE),1) CFLAGS +=-DCONFIG_FUNCGEN_ENABLE OBJS += func_gen.o uui_icon.o gfx-square.o gfx-saw.o gfx-sin.o diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c new file mode 100644 index 00000000..ccb45dcc --- /dev/null +++ b/opendps/func_dpsmode.c @@ -0,0 +1,585 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Johan Kanflo (github.com/kanflo) + * Modifications made by Leo Leung + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include +#include +#include "gfx-iconpower.h" +#include "gfx-cvbar.h" +#include "gfx-ccbar.h" +#include "font-meter_large.h" +#include "hw.h" +#include "func_dpsmode.h" +#include "uui.h" +#include "uui_number.h" +#include "dbg_printf.h" +#include "mini-printf.h" +#include "dps-model.h" +#include "ili9163c.h" +#include "opendps.h" + +/* + * This is the implementation of the CV screen. It has two editable values, + * constant voltage and current limit. When power is enabled it will continously + * display the current output voltage and current draw. If the user edits one + * of the values when power is eabled, the other will continue to be updated. + * Thid allows for ramping the voltage and obsering the current increase. + */ + +static void dpsmode_enable(bool _enable); +static void voltage_changed(ui_number_t *item); +static void current_changed(ui_number_t *item); +static void dpsmode_tick(void); +static void activated(void); +static void deactivated(void); +static bool event(uui_t *ui, event_t event); +static void past_save(past_t *past); +static void past_restore(past_t *past); +static set_param_status_t set_parameter(char *name, char *value); +static set_param_status_t get_parameter(char *name, char *value, uint32_t value_len); + +static void clear_bars(void); +static void clear_ccbar(void); +static void clear_cvbar(void); + +/* We need to keep copies of the user settings as the value in the UI will + * be replaced with measurements when output is active + */ +static int32_t saved_v, saved_i; + +// single edit mode, with M1/M2 buttons, not select. +// pressing any other button when in this mode will exit the edit mode +static bool single_edit_mode; +static bool select_mode; + +enum { + CUR_GFX_NOT_DRAWN = 0, + CUR_GFX_CV = 1, + CUR_GFX_CC = 2, +} dpsmode_graphics; + +#define SCREEN_ID (6) +#define PAST_U (0) +#define PAST_I (1) +#define XPOS_CCCV (25) + +#define XPOS_METER (117) +#define YPOS_VOLTAGE (10) +#define YPOS_CURRENT (45) +#define YPOS_POWER (80) + +/* Overriding white color */ +#define COLOR_VOLTAGE GREEN +#define COLOR_AMPERAGE YELLOW +#define COLOR_WATTAGE MAGENTA + +/* This is the definition of the voltage item in the UI */ +ui_number_t dpsmode_voltage = { + { + .type = ui_item_number, + .id = 10, + .x = XPOS_METER, + .y = YPOS_VOLTAGE, + .can_focus = true, + }, + .font_size = FONT_METER_LARGE, + .alignment = ui_text_right_aligned, + .pad_dot = false, + .color = COLOR_VOLTAGE, + .value = 0, + .min = 0, + .max = 0, /** Set at init, continously updated in the tick callback */ + .si_prefix = si_milli, + .num_digits = 2, + .num_decimals = 2, + .unit = unit_volt, /** Affects the unit printed on screen */ + .changed = &voltage_changed, +}; + +ui_number_t dpsmode_current = { + { + .type = ui_item_number, + .id = 11, + .x = XPOS_METER, + .y = YPOS_CURRENT, + .can_focus = true, + }, + .font_size = FONT_METER_LARGE, + .alignment = ui_text_right_aligned, + .pad_dot = false, + .color = COLOR_AMPERAGE, + .value = 0, + .min = 0, + .max = CONFIG_DPS_MAX_CURRENT, + .si_prefix = si_milli, + .num_digits = 1, + .num_decimals = 3, + .unit = unit_ampere, + .changed = ¤t_changed, +}; + +ui_number_t dpsmode_power = { + { + .type = ui_item_number, + .id = 12, + .x = XPOS_METER, + .y = YPOS_POWER, + .can_focus = false, // TODO: OPP feature, with warning bar when approaching power limit + }, + .font_size = FONT_METER_LARGE, + .alignment = ui_text_right_aligned, + .pad_dot = false, + .color = COLOR_WATTAGE, + .value = 0, + .min = 0, + .max = 0, + .si_prefix = si_micro, + .num_digits = 2, + .num_decimals = 2, + .unit = unit_watt, + .changed = NULL, +}; + + + +/* This is the screen definition */ +ui_screen_t dpsmode_screen = { + .id = SCREEN_ID, + .name = "dpsmode", + .icon_data = (uint8_t *) gfx_iconpower, + .icon_data_len = sizeof(gfx_iconpower), + .icon_width = GFX_ICONPOWER_WIDTH, + .icon_height = GFX_ICONPOWER_HEIGHT, + .event = &event, + .activated = &activated, + .deactivated = &deactivated, + .enable = &dpsmode_enable, + .past_save = &past_save, + .past_restore = &past_restore, + .tick = &dpsmode_tick, + .set_parameter = &set_parameter, + .get_parameter = &get_parameter, + .num_items = 3, + .parameters = { + { + .name = "voltage", + .unit = unit_volt, + .prefix = si_milli + }, + { + .name = "current", + .unit = unit_ampere, + .prefix = si_milli + }, + { + .name = "power", + .unit = unit_watt, + .prefix = si_milli + }, + { + .name = {'\0'} /** Terminator */ + }, + }, + .items = { + (ui_item_t*) &dpsmode_voltage, + (ui_item_t*) &dpsmode_current, + (ui_item_t*) &dpsmode_power + } +}; + +/** + * @brief Set function parameter + * + * @param[in] name name of parameter + * @param[in] value value of parameter as a string - always in SI units + * + * @retval set_param_status_t status code + */ +static set_param_status_t set_parameter(char *name, char *value) +{ + int32_t ivalue = atoi(value); + if (strcmp("voltage", name) == 0 || strcmp("u", name) == 0) { + if (ivalue < dpsmode_voltage.min || ivalue > dpsmode_voltage.max) { + emu_printf("[CL] Voltage %d is out of range (min:%d max:%d)\n", ivalue, dpsmode_voltage.min, dpsmode_voltage.max); + return ps_range_error; + } + emu_printf("[CL] Setting voltage to %d\n", ivalue); + dpsmode_voltage.value = ivalue; + voltage_changed(&dpsmode_voltage); + return ps_ok; + } else if (strcmp("current", name) == 0 || strcmp("i", name) == 0) { + if (ivalue < dpsmode_current.min || ivalue > dpsmode_current.max) { + emu_printf("[CL] Current %d is out of range (min:%d max:%d)\n", ivalue, dpsmode_current.min, dpsmode_current.max); + return ps_range_error; + } + emu_printf("[CL] Setting current to %d\n", ivalue); + dpsmode_current.value = ivalue; + current_changed(&dpsmode_current); + return ps_ok; + } + return ps_unknown_name; +} + +/** + * @brief Get function parameter + * + * @param[in] name name of parameter + * @param[in] value value of parameter as a string - always in SI units + * @param[in] value_len length of value buffer + * + * @retval set_param_status_t status code + */ +static set_param_status_t get_parameter(char *name, char *value, uint32_t value_len) +{ + if (strcmp("voltage", name) == 0 || strcmp("u", name) == 0) { + /** value returned in millivolt, module internal representation is centivolt */ + (void) mini_snprintf(value, value_len, "%d", (pwrctl_vout_enabled() ? saved_v : dpsmode_voltage.value)); + return ps_ok; + } else if (strcmp("current", name) == 0 || strcmp("i", name) == 0) { + (void) mini_snprintf(value, value_len, "%d", pwrctl_vout_enabled() ? saved_i : dpsmode_current.value); + return ps_ok; + } + return ps_unknown_name; +} + +/** + * @brief Callback for when the function is enabled + * + * @param[in] enabled true when function is enabled + */ +static void dpsmode_enable(bool enabled) +{ + emu_printf("[CL] %s output\n", enabled ? "Enable" : "Disable"); + + if (enabled) { + /** Display will now show the current values, keep the user setting saved */ + saved_v = dpsmode_voltage.value; + saved_i = dpsmode_current.value; + (void) pwrctl_set_vout(dpsmode_voltage.value); + (void) pwrctl_set_iout(dpsmode_current.value); + (void) pwrctl_set_ilimit(0xFFFF); /** Set the current limit to the maximum to prevent OCP (over current protection) firing */ + pwrctl_enable_vout(true); + + } else { + pwrctl_enable_vout(false); + /** Make sure we're displaying the settings and not the current + * measurements when the power output is switched off */ + + dpsmode_voltage.value = saved_v; + dpsmode_voltage.color = COLOR_VOLTAGE; + dpsmode_voltage.ui.draw(&dpsmode_voltage.ui); + + dpsmode_current.value = saved_i; + dpsmode_current.color = COLOR_AMPERAGE; + dpsmode_current.ui.draw(&dpsmode_current.ui); + + dpsmode_power.value = 0; + dpsmode_power.color = COLOR_WATTAGE; + dpsmode_power.ui.draw(&dpsmode_power.ui); + + clear_bars(); + } +} + +/** + * @brief Callback for when value of the voltage item is changed + * + * @param item The voltage item + */ +static void voltage_changed(ui_number_t *item) +{ + saved_v = item->value; + (void) pwrctl_set_vout(item->value); +} + +/** + * @brief Callback for when value of the current item is changed + * + * @param item The current item + */ +static void current_changed(ui_number_t *item) +{ + saved_i = item->value; + (void) pwrctl_set_iout(item->value); +} + + +static bool event(uui_t *ui, event_t event) { + + switch(event) { + case event_button_m1: + case event_button_m2: + case event_button_sel: + + if (single_edit_mode) { + single_edit_mode = false; + + // toggle focus on anything that is in focus + if (dpsmode_voltage.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_voltage); + if (dpsmode_current.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_current); + return true; + } + + default: + break; + } + + + switch(event) { + case event_button_m1: + // if in normal select mode, let parent handle it + if (select_mode) return false; + + // otherwise, enter single edit mode + single_edit_mode = true; + + // focus on voltage if not already focused + if ( ! dpsmode_voltage.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_voltage); + + // we handled it, parent should do nothing + return true; + + case event_button_m2: + if (select_mode) return false; + single_edit_mode = true; + if ( ! dpsmode_current.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_current); + return true; + + case event_button_sel: + // toggle select mode, so parent can deal with other UI elements + // keep track, so this screen will not do anything until we leave this mode + select_mode = ! select_mode; + return false; + + default: + return false; + } + + return false; +} + +/** + * @brief Callback when screen is activated + */ +static void activated(void) { +} + + +/** + * @brief Do any required clean up before changing away from this screen + */ +static void deactivated(void) +{ + clear_bars(); + tft_clear(); +} + +/** + * @brief Save persistent parameters + * + * @param past The past + */ +static void past_save(past_t *past) +{ + /** @todo: past bug causes corruption for units smaller than 4 bytes (#27) */ + if (!past_write_unit(past, (SCREEN_ID << 24) | PAST_U, (void*) &saved_v, 4 /* sizeof(dpsmode_voltage.value) */ )) { + /** @todo: handle past write failures */ + } + if (!past_write_unit(past, (SCREEN_ID << 24) | PAST_I, (void*) &saved_i, 4 /* sizeof(dpsmode_current.value) */ )) { + /** @todo: handle past write failures */ + } +} + +/** + * @brief Restore persistent parameters + * + * @param past The past + */ +static void past_restore(past_t *past) +{ + uint32_t length; + uint32_t *p = 0; + if (past_read_unit(past, (SCREEN_ID << 24) | PAST_U, (const void**) &p, &length)) { + saved_v = dpsmode_voltage.value = *p; + (void) length; + } + if (past_read_unit(past, (SCREEN_ID << 24) | PAST_I, (const void**) &p, &length)) { + saved_i = dpsmode_current.value = *p; + (void) length; + } +} + +/** + * @brief Update the UI. We need to be careful about the values shown + * as they will differ depending on the current state of the UI + * and the current power output mode. + * Power off: always show current setting + * Power on : show current output value unless the item has focus + * in which case we shall display the current setting. + */ +static void dpsmode_tick(void) +{ + uint16_t i_out_raw, v_in_raw, v_out_raw; + hw_get_adc_values(&i_out_raw, &v_in_raw, &v_out_raw); + /** Continously update max voltage output value + * Max output voltage = Vin / VIN_VOUT_RATIO + * Add 0.5f to ensure correct rounding when truncated */ + dpsmode_voltage.max = (float) pwrctl_calc_vin(v_in_raw) / VIN_VOUT_RATIO + 0.5f; + + if (pwrctl_vout_enabled()) { + int32_t vout_actual = pwrctl_calc_vout(v_out_raw); + int32_t cout_actual = pwrctl_calc_iout(i_out_raw); + + dpsmode_power.value = vout_actual * cout_actual; + dpsmode_power.color = COLOR_WATTAGE; + dpsmode_power.ui.draw(&dpsmode_power.ui); + + if (dpsmode_voltage.ui.has_focus) { + /** If the voltage setting has focus, make sure we're displaying + * the desired setting and not the current output value. */ + if (dpsmode_voltage.value != saved_v) { + dpsmode_voltage.value = saved_v; + dpsmode_voltage.ui.draw(&dpsmode_voltage.ui); + } + } else { + /** No focus, update display if necessary */ + if (dpsmode_voltage.value != vout_actual) { + dpsmode_voltage.value = vout_actual; + dpsmode_voltage.color = COLOR_VOLTAGE; + dpsmode_voltage.ui.draw(&dpsmode_voltage.ui); + } + } + + if (dpsmode_current.ui.has_focus) { + /** If the current setting has focus, make sure we're displaying + * the desired setting and not the current output value. */ + if (dpsmode_current.value != saved_i) { + dpsmode_current.value = saved_i; + dpsmode_current.ui.draw(&dpsmode_current.ui); + } + } else { + /** No focus, update display if necessary */ + if (dpsmode_current.value != cout_actual) { + dpsmode_current.value = cout_actual; + dpsmode_current.color = COLOR_AMPERAGE; + dpsmode_current.ui.draw(&dpsmode_current.ui); + } + } + + /** Determine if we are in CV or CC mode and display it */ + int32_t vout_diff = abs(saved_v - vout_actual); + int32_t cout_diff = abs(saved_i - cout_actual); + + if (cout_diff < vout_diff) { + // current diff smaller than voltage diff (constant current) + if (dpsmode_graphics & CUR_GFX_CV) { + clear_cvbar(); + } + + if ((dpsmode_graphics & CUR_GFX_CC) == 0) { + dpsmode_graphics |= CUR_GFX_CC; + + // mine, draw cc bar beside current + tft_blit((uint16_t*) gfx_ccbar, + GFX_CCBAR_WIDTH, GFX_CCBAR_HEIGHT, + TFT_WIDTH - GFX_CCBAR_WIDTH, + YPOS_CURRENT + FONT_METER_LARGE_MAX_GLYPH_HEIGHT - GFX_CCBAR_HEIGHT ); + } + + } else { + // current diff larger than voltage diff (constant voltage) + + if (dpsmode_graphics & CUR_GFX_CC) { + clear_ccbar(); + } + + if ((dpsmode_graphics & CUR_GFX_CV) == 0) { + dpsmode_graphics |= CUR_GFX_CV; + + // mine, draw cv bar beside voltage + tft_blit((uint16_t*) gfx_cvbar, + GFX_CVBAR_WIDTH, GFX_CVBAR_HEIGHT, + TFT_WIDTH - GFX_CVBAR_WIDTH, + YPOS_VOLTAGE + FONT_METER_LARGE_MAX_GLYPH_HEIGHT - GFX_CVBAR_HEIGHT ); + } + } + } +} + + +static void clear_bars() { + /** Ensure the CC or CV logo has been cleared from the screen */ + if (dpsmode_graphics & CUR_GFX_CV) { + clear_cvbar(); + } + if (dpsmode_graphics & CUR_GFX_CC) { + clear_ccbar(); + } + dpsmode_graphics = CUR_GFX_NOT_DRAWN; +} + +static void clear_ccbar() { + // clear cc bar + tft_fill(TFT_WIDTH - GFX_CCBAR_WIDTH, YPOS_CURRENT + FONT_METER_LARGE_MAX_GLYPH_HEIGHT - GFX_CCBAR_HEIGHT, + GFX_CCBAR_WIDTH, GFX_CCBAR_HEIGHT, + BLACK); + dpsmode_graphics = dpsmode_graphics & ~CUR_GFX_CC; +} + +static void clear_cvbar() { + // clear cv bar + tft_fill(TFT_WIDTH - GFX_CVBAR_WIDTH, YPOS_VOLTAGE + FONT_METER_LARGE_MAX_GLYPH_HEIGHT - GFX_CVBAR_HEIGHT, + GFX_CVBAR_WIDTH, GFX_CVBAR_HEIGHT, + BLACK); + dpsmode_graphics = dpsmode_graphics & ~CUR_GFX_CV; +} + +/** + * @brief Initialise the DPS Mode module and add its screen to the UI + * + * @param ui The user interface + */ +void func_dpsmode_init(uui_t *ui) +{ + dpsmode_voltage.value = 0; /** read from past */ + dpsmode_current.value = 0; /** read from past */ + uint16_t i_out_raw, v_in_raw, v_out_raw; + hw_get_adc_values(&i_out_raw, &v_in_raw, &v_out_raw); + (void) i_out_raw; + (void) v_out_raw; + + dpsmode_voltage.max = pwrctl_calc_vin(v_in_raw); /** @todo: subtract for LDO */ + + number_init(&dpsmode_voltage); /** @todo: add guards for missing init calls */ + /** Start at the second most significant digit preventing the user from + accidentally cranking up the setting 10V or more */ + dpsmode_voltage.cur_digit = 2; + + number_init(&dpsmode_current); + number_init(&dpsmode_power); + + uui_add_screen(ui, &dpsmode_screen); +} diff --git a/opendps/func_dpsmode.h b/opendps/func_dpsmode.h new file mode 100644 index 00000000..7f0c29b3 --- /dev/null +++ b/opendps/func_dpsmode.h @@ -0,0 +1,38 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Johan Kanflo (github.com/kanflo) + * Modifications made by Leo Leung + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef __FUNC_DPSMODE_H__ +#define __FUNC_DPSMODE_H__ + +#include "uui.h" + +/** + * @brief Add the CV function to the UI + * + * @param ui The user interface + */ +void func_dpsmode_init(uui_t *ui); + +#endif // __FUNC_DPSMODE_H__ diff --git a/opendps/gen_lookup.py b/opendps/gen_lookup.py index 28f1fff6..5bc5159f 100644 --- a/opendps/gen_lookup.py +++ b/opendps/gen_lookup.py @@ -374,7 +374,7 @@ def main(): # If this is a font file ensure that a font_size has been specified if args.font_size: - characters = "0123456789.VA" # The characters to generate a lookup table of + characters = "0123456789.VAW" # The characters to generate a lookup table of if args.ascii: characters = "" for ch in range(0x21,0x7F): # skip , diff --git a/opendps/gfx-ccbar.c b/opendps/gfx-ccbar.c new file mode 100644 index 00000000..72fefbca --- /dev/null +++ b/opendps/gfx-ccbar.c @@ -0,0 +1,38 @@ +/** Gfx generated from gfx/png/ccbar.png */ + +#include "gfx-ccbar.h" + +const uint8_t gfx_ccbar[500] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, + 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, + 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, + 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, + 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, + 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, + 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, + 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, + 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, + 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, + 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, + 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, + 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, + 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, + 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, + 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, + 0x00, 0x1f, 0x00, 0x1f +}; \ No newline at end of file diff --git a/opendps/gfx-ccbar.h b/opendps/gfx-ccbar.h new file mode 100644 index 00000000..1d59cece --- /dev/null +++ b/opendps/gfx-ccbar.h @@ -0,0 +1,13 @@ +/** Gfx generated from gfx/png/ccbar.png */ + +#ifndef __GFX_CCBAR_H__ +#define __GFX_CCBAR_H__ + +#include + +#define GFX_CCBAR_HEIGHT (25) +#define GFX_CCBAR_WIDTH (10) + +extern const uint8_t gfx_ccbar[500]; + +#endif // __GFX_CCBAR_H__ \ No newline at end of file diff --git a/opendps/gfx-cvbar.c b/opendps/gfx-cvbar.c new file mode 100644 index 00000000..45af5721 --- /dev/null +++ b/opendps/gfx-cvbar.c @@ -0,0 +1,38 @@ +/** Gfx generated from gfx/png/cvbar.png */ + +#include "gfx-cvbar.h" + +const uint8_t gfx_cvbar[500] = { + 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, + 0x07, 0xe0, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, + 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, + 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, + 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x07, 0xe0, 0x00, 0x00, + 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x07, 0xe0, + 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, + 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, + 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x07, 0xe0, 0x00, 0x00, + 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, + 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, + 0x00, 0x00, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, + 0x07, 0xe0, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, + 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, + 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, + 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, + 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, 0x07, 0xe0, 0x00, 0x00, + 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, + 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x07, 0xe0, + 0x00, 0x00, 0x07, 0xe0, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0xe0, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, + 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, + 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, + 0x07, 0xe0, 0x07, 0xe0 +}; \ No newline at end of file diff --git a/opendps/gfx-cvbar.h b/opendps/gfx-cvbar.h new file mode 100644 index 00000000..7a348d15 --- /dev/null +++ b/opendps/gfx-cvbar.h @@ -0,0 +1,13 @@ +/** Gfx generated from gfx/png/cvbar.png */ + +#ifndef __GFX_CVBAR_H__ +#define __GFX_CVBAR_H__ + +#include + +#define GFX_CVBAR_HEIGHT (25) +#define GFX_CVBAR_WIDTH (10) + +extern const uint8_t gfx_cvbar[500]; + +#endif // __GFX_CVBAR_H__ \ No newline at end of file diff --git a/opendps/gfx-iconpower.c b/opendps/gfx-iconpower.c new file mode 100644 index 00000000..23fb8150 --- /dev/null +++ b/opendps/gfx-iconpower.c @@ -0,0 +1,38 @@ +/** Gfx generated from gfx/png/iconpower.png */ + +#include "gfx-iconpower.h" + +const uint8_t gfx_iconpower[512] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x45, 0x8c, 0x71, 0xd6, 0xba, 0xf7, 0xbe, + 0xf7, 0xbe, 0xd6, 0x9a, 0x8c, 0x71, 0x29, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x8c, 0x91, 0xe7, 0x3c, 0x73, 0xae, 0x29, 0x65, 0x00, 0x20, + 0x00, 0x20, 0x29, 0x65, 0x73, 0xae, 0xe7, 0x3c, 0x94, 0xb2, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0xb5, 0xd6, 0xad, 0x55, 0x08, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x61, 0xa5, 0x54, 0xb5, 0xd6, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x94, 0x92, 0xad, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xad, 0x55, 0x8c, 0x91, 0x00, 0x00, + 0x29, 0x45, 0xe7, 0x3c, 0x08, 0x61, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x61, 0xe7, 0x3c, 0x29, 0x45, + 0x8c, 0x71, 0x7b, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0xae, 0x8c, 0x71, + 0xd6, 0xba, 0x29, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x29, 0x65, 0xd6, 0xba, + 0xf7, 0xbe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf7, 0xbe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xd6, 0xba, 0x29, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x29, 0x65, 0xce, 0x99, + 0x8c, 0x71, 0x7b, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0xae, 0x8c, 0x71, + 0x29, 0x45, 0xe7, 0x3c, 0x08, 0x61, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x61, 0xe7, 0x3c, 0x29, 0x45, + 0x00, 0x00, 0x94, 0x92, 0xad, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xad, 0x55, 0x94, 0x92, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0xb5, 0xd6, 0xad, 0x55, 0x08, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x61, 0xa5, 0x54, 0xb5, 0xd6, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x8c, 0x91, 0xe7, 0x3c, 0x73, 0xae, 0x29, 0x45, 0x00, 0x20, + 0x00, 0x20, 0x29, 0x45, 0x73, 0xae, 0xe7, 0x3c, 0x94, 0xb2, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x45, 0x8c, 0x71, 0xd6, 0xba, 0xf7, 0xbe, + 0xef, 0x9d, 0xce, 0x99, 0x8c, 0x71, 0x29, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; \ No newline at end of file diff --git a/opendps/gfx-iconpower.h b/opendps/gfx-iconpower.h new file mode 100644 index 00000000..5b062c2f --- /dev/null +++ b/opendps/gfx-iconpower.h @@ -0,0 +1,13 @@ +/** Gfx generated from gfx/png/iconpower.png */ + +#ifndef __GFX_ICONPOWER_H__ +#define __GFX_ICONPOWER_H__ + +#include + +#define GFX_ICONPOWER_HEIGHT (16) +#define GFX_ICONPOWER_WIDTH (16) + +extern const uint8_t gfx_iconpower[512]; + +#endif // __GFX_ICONPOWER_H__ \ No newline at end of file diff --git a/opendps/gfx/png/ccbar.png b/opendps/gfx/png/ccbar.png new file mode 100644 index 0000000000000000000000000000000000000000..37a750e5fb285b6dd373d448ac4671b4fab3de62 GIT binary patch literal 993 zcmaJ=&ui0A91rdyV-pnx-RUhunPBpg^v9OaIJcyA1yg2MSr39{$=e#+P(1iQ4D>R@gL?3=o5R}_ya>Ap1OEW$OV@TDtU0`VzmL!7^ZogrER?Q|4v!5p z3^Q7s*UR*u*yoQQqvxa3liw4EftL$M?Rbv5YI6xr7XE{quXTX%q zi`i6KmM;TI5T~Iq4aF2EW|g#{ND}CNER7b}D@s`}bYoFZWov}^3WQM<@llG$!73DG zS%!iHC5fX5E^K+kj5#ly=qczZv;xN`4)#EzXfER>QCXVlVF|9^m-WJKn`pyeZ2C~- zg`}h&&@lcFb=^KXBxQ7z?>~jZO3O#Ej6&QDEIPQAi6oS-XaO<_4k{QodR<(oVS>XN z_JO7)U6aA&lH=Jp3NLjyhM^R_keHr@in_{D72a`dC9f64*}1%!mr}AQ=4Dw*Ntz&} zQw2SnmFA{;Tpe3Y7kQ+|wU4;cKyI=Qu1_QDC~(%0T?nuXI%O-)z+CjgK)o*49-NCX zkPB%tFd6P&!|q+t4NA=Z>Qbk_{K%slAJEl)!R>9+XK|yb&sO5ypU*y?U`~!`Uq2lj z{Cd3pe0+SPeK+&!<*Az+ZyR6EUKl;I?<#BD?&sFQ($=?ivC%9qj=cV`6Ft2(w)Z2} he&YxC!_A#H%n-AF`<%GtTrDM!u9z?Bn{#&_{sGX+J3#;d literal 0 HcmV?d00001 diff --git a/opendps/gfx/png/cvbar.png b/opendps/gfx/png/cvbar.png new file mode 100644 index 0000000000000000000000000000000000000000..2b6bb31a9f24940c492c0c524301717fb2ea916e GIT binary patch literal 1012 zcmaJ=&ui0A91l*I40q9!it@-rC$9O`A8W$8(Iw4RF|~As_29uYd0WGlyqLVLSq~yY z6$KRrA|j~6gQ8gK}PH8@03T}P~9 z3752!l7VbS4>3$&yM#?qLnDE!8#54tGMu)Y6#e7bOBz^aik^&XoaV}~VvW~4I8n~apAkHKr1|N%q zL6PAT(U>R>0DN@f}%EK5idnoFm@%DtyZf{HOe4w zn&m}NWI2Hqga|=I`~?T=LB#RSZ*CQ#8qRs|4F^%Q}9uO{8IL zpt~&3aA8R;pr-vFYTIqJj|*@+-+v1G#RV6#1?ZzW&me=F>I*};lI%epBd>_iY^#g; z3c|>*AQ#AT*fkOKPg;(Ns{XMCN7JON<73@1U{*=dM1`>|Q&N+oF*TXYWQ3^5^BGYT z66v%oWD@DPEU4UIi>n}G&V~+dam{V6+L0TsgYA;Y3iPabXsRBvL8ENR>YR(*QLo80 zJLjTw!){%X4GPWn>Jq2D{LmpA?~&F1G`8~*c@}0?Nf(3l<;5>OufT5k z_V>+A@8FwzHfA{L-&OS8JbtPi(A?y}wg`Qug20Pdx5BuyX!qa`?*P z>5ZpL^G8Lxc=%zre}7%Q_~PC3f!Ez1?{2Q@*Uo)-Ky^_vzxVjY*QI*+4zrn@vNC$+ F!XNt^M_>Q| literal 0 HcmV?d00001 diff --git a/opendps/gfx/png/iconpower.png b/opendps/gfx/png/iconpower.png new file mode 100644 index 0000000000000000000000000000000000000000..8a4cfc5e9289c844c6cb87067b45c99368f350de GIT binary patch literal 1204 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+nAI{vB1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxOgGuk#8koDQqR!L z*u>ION5ROz&_dt9Lf_C>*U-$$#K6kPNC66zfVLH-q*(>IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8E%gnI^o@*kfhu&1EAvVcD|GXUm0>2hq!uR^WfqiV=I1GZOiWD5 zFD$Tv3bSNU;+l1ennz|zM-B0$V)JVzP|XC=H|jx7ncO3BHWAB;NpiyW)Z+ZoqGVvir744~DzI`cN=+=uFAB-e&w+(vKt_H^esM;Afr7I$DAX(!G{Q6U zQu51-HNkp(eXTt6ic1pnl2bihY?Xkf=w)W6SQ#5T8JfAc7`Ymm7#JG5T3R|=8ai8= z7+YAnxtO~;yTSCjn-&oVcJKGoXyCATG>Fn8j*zOcprd4a{8^Uwd* z)t~ph?6Pw!?}HL6#dXd|ub62f8vqoHI(~3Q-w9Gt(Vy|z1xpr-4)U;HWNh)7nPtRrD!^2nnv#{X6 zzui(LKlP?_FKaHh>~m&ei(#2Ry`O7xdF=Mw+l4au+oL0=6-?hH|4Sf&;nkMIVqYh& Q5eJncp00i_>zopr0A5d>f&c&j literal 0 HcmV?d00001 diff --git a/opendps/opendps.c b/opendps/opendps.c index 784843e7..23ea9a7f 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -63,6 +63,9 @@ #ifdef CONFIG_CL_ENABLE #include "func_cl.h" #endif // CONFIG_CL_ENABLE +#ifdef CONFIG_DPSMODE_ENABLE +#include "func_dpsmode.h" +#endif // CONFIG_DPSMODE_ENABLE #ifdef CONFIG_FUNCGEN_ENABLE #include "func_gen.h" #endif // CONFIG_FUNCGEN_ENABLE @@ -75,9 +78,6 @@ #include "logo.h" #endif // CONFIG_SPLASH_SCREEN -#define TFT_HEIGHT (128) -#define TFT_WIDTH (128) - /** How ofter we update the measurements in the UI (ms) */ #define UI_UPDATE_INTERVAL_MS (250) @@ -437,6 +437,9 @@ static void ui_init(void) #ifdef CONFIG_CL_ENABLE func_cl_init(&func_ui); #endif // CONFIG_CL_ENABLE +#ifdef CONFIG_DPSMODE_ENABLE + func_dpsmode_init(&func_ui); +#endif // CONFIG_DPSMODE_ENABLE #ifdef CONFIG_FUNCGEN_ENABLE func_gen_init(&func_ui); #endif // CONFIG_FUNCGEN_ENABLE diff --git a/opendps/opendps.h b/opendps/opendps.h index 2d35a9c3..32503301 100644 --- a/opendps/opendps.h +++ b/opendps/opendps.h @@ -32,6 +32,10 @@ /** Max number of parameters to a function */ #define OPENDPS_MAX_PARAMETERS (8) +/** UI Width/Height */ +#define TFT_WIDTH (128) +#define TFT_HEIGHT (128) + /** * @brief Enable specified function * diff --git a/opendps/uui_number.c b/opendps/uui_number.c index 59dab21c..5e0ad547 100644 --- a/opendps/uui_number.c +++ b/opendps/uui_number.c @@ -160,6 +160,7 @@ static uint32_t number_draw_width(ui_item_t *_item) break; case unit_volt: case unit_ampere: + case unit_watt: total_width += max_w; break; case unit_hertz: @@ -307,6 +308,9 @@ static void number_draw(ui_item_t *_item) case unit_hertz: tft_puts(FONT_FULL_SMALL, "Hz", xpos, _item->y + h, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 2, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, color, false); break; + case unit_watt: + tft_putch(item->font_size, 'W', xpos, _item->y, max_w, h, color, false); + break; default: assert(0); } From 4cac659b8367db4862b06f36c8e70e430542ee39 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 28 Sep 2019 20:37:56 -0600 Subject: [PATCH 004/175] Updated large meter font size to 40px --- opendps/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opendps/Makefile b/opendps/Makefile index b92fd799..e5449bf5 100644 --- a/opendps/Makefile +++ b/opendps/Makefile @@ -28,7 +28,7 @@ DEBUG ?= 0 METER_FONT_FILE ?= gfx/Ubuntu-C.ttf METER_FONT_SMALL_SIZE ?= 18 METER_FONT_MEDIUM_SIZE ?= 24 -METER_FONT_LARGE_SIZE ?= 38 +METER_FONT_LARGE_SIZE ?= 40 FULL_FONT_FILE ?= gfx/ProggyClean.ttf FULL_FONT_SMALL_SIZE ?= 16 From 9ac1b09dd8514178cdd0d55df6fa333a84d87c30 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 28 Sep 2019 20:57:16 -0600 Subject: [PATCH 005/175] Added DP50v5A model values --- opendps/dps-model.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/opendps/dps-model.h b/opendps/dps-model.h index 1d10d7da..bb4c8547 100644 --- a/opendps/dps-model.h +++ b/opendps/dps-model.h @@ -55,6 +55,19 @@ #define V_ADC_C (float)-125.732f #define V_DAC_K (float)0.072266f #define V_DAC_C (float)4.444777f +#elif defined(DP50V5A) + #ifndef CONFIG_DPS_MAX_CURRENT + #define CONFIG_DPS_MAX_CURRENT (5000) + #endif + #define ADC_CHA_IOUT_GOLDEN_VALUE (0x45) + #define A_DAC_K (float)0.6402f + #define A_DAC_C (float)299.5518f + #define A_ADC_K (float)1.74096f + #define A_ADC_C (float)-121.3943805f + #define V_DAC_K (float)0.07544f + #define V_DAC_C (float)2.1563f + #define V_ADC_K (float)13.253f + #define V_ADC_C (float)-103.105f #elif defined(DPS5005) #ifndef CONFIG_DPS_MAX_CURRENT #define CONFIG_DPS_MAX_CURRENT (5000) From 4f0760bfe41939d22597f85cfef64008f08af528 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 28 Sep 2019 21:31:59 -0600 Subject: [PATCH 006/175] Reordering DPS model values for DP50V5A --- opendps/dps-model.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/opendps/dps-model.h b/opendps/dps-model.h index bb4c8547..e4e33ffc 100644 --- a/opendps/dps-model.h +++ b/opendps/dps-model.h @@ -55,19 +55,6 @@ #define V_ADC_C (float)-125.732f #define V_DAC_K (float)0.072266f #define V_DAC_C (float)4.444777f -#elif defined(DP50V5A) - #ifndef CONFIG_DPS_MAX_CURRENT - #define CONFIG_DPS_MAX_CURRENT (5000) - #endif - #define ADC_CHA_IOUT_GOLDEN_VALUE (0x45) - #define A_DAC_K (float)0.6402f - #define A_DAC_C (float)299.5518f - #define A_ADC_K (float)1.74096f - #define A_ADC_C (float)-121.3943805f - #define V_DAC_K (float)0.07544f - #define V_DAC_C (float)2.1563f - #define V_ADC_K (float)13.253f - #define V_ADC_C (float)-103.105f #elif defined(DPS5005) #ifndef CONFIG_DPS_MAX_CURRENT #define CONFIG_DPS_MAX_CURRENT (5000) @@ -81,6 +68,19 @@ #define V_DAC_C (float)1.85f #define V_ADC_K (float)13.164f #define V_ADC_C (float)-100.751f +#elif defined(DP50V5A) + #ifndef CONFIG_DPS_MAX_CURRENT + #define CONFIG_DPS_MAX_CURRENT (5000) + #endif + #define ADC_CHA_IOUT_GOLDEN_VALUE (0x45) + #define A_DAC_K (float)0.6402f + #define A_DAC_C (float)299.5518f + #define A_ADC_K (float)1.74096f + #define A_ADC_C (float)-121.3943805f + #define V_DAC_K (float)0.07544f + #define V_DAC_C (float)2.1563f + #define V_ADC_K (float)13.253f + #define V_ADC_C (float)-103.105f #elif defined(DPS3005) #ifndef CONFIG_DPS_MAX_CURRENT #define CONFIG_DPS_MAX_CURRENT (5000) From 4a873603693b6d20827cf017df5340011d2cd9a1 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 28 Sep 2019 21:33:46 -0600 Subject: [PATCH 007/175] Added colored power buttons --- opendps/gfx-poweroff.c | 38 +++++++++++++++++++++++++++++++++++ opendps/gfx-poweroff.h | 13 ++++++++++++ opendps/gfx-poweron.c | 38 +++++++++++++++++++++++++++++++++++ opendps/gfx-poweron.h | 13 ++++++++++++ opendps/gfx/png/poweroff.png | Bin 0 -> 1177 bytes opendps/gfx/png/poweron.png | Bin 0 -> 1187 bytes opendps/opendps.c | 22 +++++++++++--------- 7 files changed, 115 insertions(+), 9 deletions(-) create mode 100644 opendps/gfx-poweroff.c create mode 100644 opendps/gfx-poweroff.h create mode 100644 opendps/gfx-poweron.c create mode 100644 opendps/gfx-poweron.h create mode 100644 opendps/gfx/png/poweroff.png create mode 100644 opendps/gfx/png/poweron.png diff --git a/opendps/gfx-poweroff.c b/opendps/gfx-poweroff.c new file mode 100644 index 00000000..c9bfb756 --- /dev/null +++ b/opendps/gfx-poweroff.c @@ -0,0 +1,38 @@ +/** Gfx generated from gfx/png/poweroff.png */ + +#include "gfx-poweroff.h" + +const uint8_t gfx_poweroff[512] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, + 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x1d, + 0x00, 0x1d, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x1d, + 0x00, 0x1d, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x1a, 0x00, 0x11, 0x00, 0x00, 0x00, 0x03, 0x00, 0x1d, + 0x00, 0x1d, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x1f, 0x00, 0x13, 0x00, 0x00, 0x00, 0x03, 0x00, 0x1d, + 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1d, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x16, 0x00, 0x1f, 0x00, 0x16, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x1d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x16, 0x00, 0x1f, 0x00, 0x16, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x1e, 0x00, 0x1d, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x1e, 0x00, 0x06, + 0x00, 0x0c, 0x00, 0x1f, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x1f, 0x00, 0x0c, + 0x00, 0x10, 0x00, 0x1f, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, + 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x1f, 0x00, 0x10, + 0x00, 0x0c, 0x00, 0x1f, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x1f, 0x00, 0x0c, + 0x00, 0x06, 0x00, 0x1e, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x1e, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x1f, 0x00, 0x16, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16, 0x00, 0x1f, 0x00, 0x1d, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1d, 0x00, 0x15, 0x00, 0x10, + 0x00, 0x10, 0x00, 0x15, 0x00, 0x1d, 0x00, 0x1f, 0x00, 0x1c, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x05, 0x00, 0x14, 0x00, 0x1d, 0x00, 0x1f, 0x00, 0x1f, + 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1d, 0x00, 0x14, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x12, + 0x00, 0x12, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; \ No newline at end of file diff --git a/opendps/gfx-poweroff.h b/opendps/gfx-poweroff.h new file mode 100644 index 00000000..1cf09c91 --- /dev/null +++ b/opendps/gfx-poweroff.h @@ -0,0 +1,13 @@ +/** Gfx generated from gfx/png/poweroff.png */ + +#ifndef __GFX_POWEROFF_H__ +#define __GFX_POWEROFF_H__ + +#include + +#define GFX_POWEROFF_HEIGHT (16) +#define GFX_POWEROFF_WIDTH (16) + +extern const uint8_t gfx_poweroff[512]; + +#endif // __GFX_POWEROFF_H__ \ No newline at end of file diff --git a/opendps/gfx-poweron.c b/opendps/gfx-poweron.c new file mode 100644 index 00000000..978c1cda --- /dev/null +++ b/opendps/gfx-poweron.c @@ -0,0 +1,38 @@ +/** Gfx generated from gfx/png/poweron.png */ + +#include "gfx-poweron.h" + +const uint8_t gfx_poweron[512] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x20, + 0x03, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x80, + 0x07, 0x80, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x80, + 0x07, 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x60, 0x06, 0xc0, 0x04, 0x80, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x80, + 0x07, 0x80, 0x00, 0xe0, 0x00, 0x00, 0x04, 0x80, 0x06, 0xc0, 0x02, 0x60, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x80, 0x07, 0x60, 0x07, 0xe0, 0x04, 0xc0, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x80, + 0x07, 0x80, 0x00, 0xe0, 0x00, 0x00, 0x04, 0xc0, 0x07, 0xe0, 0x07, 0x60, 0x01, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x05, 0xc0, 0x07, 0xe0, 0x05, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x80, + 0x07, 0x80, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x40, 0x05, 0x80, 0x07, 0xe0, 0x05, 0xc0, 0x00, 0x00, + 0x01, 0x80, 0x07, 0xc0, 0x07, 0x80, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0xa0, + 0x07, 0xa0, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x07, 0x80, 0x07, 0xc0, 0x01, 0x80, + 0x03, 0x40, 0x07, 0xe0, 0x05, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xa0, + 0x02, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xe0, 0x07, 0xe0, 0x03, 0x40, + 0x04, 0x20, 0x07, 0xe0, 0x05, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x07, 0xe0, 0x04, 0x20, + 0x03, 0x40, 0x07, 0xe0, 0x05, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xe0, 0x07, 0xe0, 0x03, 0x40, + 0x01, 0x80, 0x07, 0xc0, 0x07, 0x80, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x07, 0x80, 0x07, 0xc0, 0x01, 0x80, + 0x00, 0x00, 0x05, 0xc0, 0x07, 0xe0, 0x05, 0xa0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x05, 0xa0, 0x07, 0xe0, 0x05, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x80, 0x07, 0x60, 0x07, 0xe0, 0x05, 0x80, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x05, 0x80, 0x07, 0xe0, 0x07, 0x60, 0x01, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x07, 0x40, 0x07, 0xe0, 0x07, 0x80, 0x05, 0x80, 0x04, 0x20, + 0x04, 0x20, 0x05, 0x80, 0x07, 0x80, 0x07, 0xe0, 0x07, 0x40, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x05, 0x20, 0x07, 0x80, 0x07, 0xe0, 0x07, 0xe0, + 0x07, 0xe0, 0x07, 0xe0, 0x07, 0x80, 0x05, 0x20, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x02, 0xc0, 0x04, 0xa0, + 0x04, 0xa0, 0x02, 0xc0, 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; \ No newline at end of file diff --git a/opendps/gfx-poweron.h b/opendps/gfx-poweron.h new file mode 100644 index 00000000..8ea2e5cd --- /dev/null +++ b/opendps/gfx-poweron.h @@ -0,0 +1,13 @@ +/** Gfx generated from gfx/png/poweron.png */ + +#ifndef __GFX_POWERON_H__ +#define __GFX_POWERON_H__ + +#include + +#define GFX_POWERON_HEIGHT (16) +#define GFX_POWERON_WIDTH (16) + +extern const uint8_t gfx_poweron[512]; + +#endif // __GFX_POWERON_H__ \ No newline at end of file diff --git a/opendps/gfx/png/poweroff.png b/opendps/gfx/png/poweroff.png new file mode 100644 index 0000000000000000000000000000000000000000..8a7d34c5f147bdc878f814875d5297f8ca7a22a2 GIT binary patch literal 1177 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+nAI{vB1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxOgGuk#8koDQqR!L z*u>ION5ROz&_dt9Lf_C>*U-$$#K6kPNC66zfVLH-q*(>IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8E%gnI^o@*kfhu&1EAvVcD|GXUm0>2hq!uR^WfqiV=I1GZOiWD5 zFD$Tv3bSNU;+l1ennz|zM-B0$V)JVzP|XC=H|jx7ncO3BHWAB;NpiyW)Z+ZoqGVvir744~DzI`cN=+=uFAB-e&w+(vKt_H^esM;Afr7I$DAX(!G{Q6U zQu51-HNkp(eXTt6ic1pnl2bihY?Xkf=w)W6SXr347#g@3ySf?~I~p3gT3VO^xhAf_ zSTJ)lG&gmG>2=9ZF3nBND}m`vLFjeEsTY(SatnYqyQCInmZhe+73JqDfW2*%iQ6sC zIL(9VO~LIJ7o2+afsWA!MJ`fg!-Rk-2*iXZT_6XZ_*3(MDZU7pw2#eO)y=@b$m!|g z7*cVoX41kuCP#s`{d?7xZ1E4^5#?R9;1&x@oA?7+fjxn_vR&*N5-z-LElU+w`)As_`8P|S=rpaH<8RTnaz=Jo)82VOeSKHo<@7&zBBHm` zY29{j?pq(2<(CELuq-K2no<7ZAh(D!FSm1k%iK47Ze4s294DsVXx+tL)z32j72k%| zaN{jY1GBWx91e6Y4W1FZWB;6YGa33TEwr?^?Aex|uEhD^p~lQNFV*HUaa%jPZ8x<( zTc-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxOgGuk#8koDQqR!L z*u>ION5ROz&_dt9Lf_C>*U-$$#K6kPNC66zfVLH-q*(>IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8E%gnI^o@*kfhu&1EAvVcD|GXUm0>2hq!uR^WfqiV=I1GZOiWD5 zFD$Tv3bSNU;+l1ennz|zM-B0$V)JVzP|XC=H|jx7ncO3BHWAB;NpiyW)Z+ZoqGVvir744~DzI`cN=+=uFAB-e&w+(vKt_H^esM;Afr7I$DAX(!G{Q6U zQu51-HNkp(eXTt6ic1pnl2bihY?Xkf=w)W6SXsK5Ia!z)8M+!7I~p3gT3R|8x>*{! z8aO&TnYx;rIm7h2N@Uj$6rt3!SyF)%O+ zd%8G=RNU&Bw9${rQJ`(VuoJ_42Pusn){+?+iI2Dim%a)${Wo?3o-BX_4CZ_wJb z86LUfa}J8E`*Qh&fo13hJ&P8_H_nUSwD7K6xJgv2Ab+!=$=Q;Gg{3^RgH~?xx>m<2 zf1!8Uze{z~-)TjxI}+Nrwz?_OZ~vjncPTS8EmS*JZ}Hvh(#}_2AACbac+25S#e4Ve zms1x$<6W+ybW3s9QqC)}N2;oU2;U(BxBPF~qm=fm^BSE)zt;8HUqpQUU^ zFD|^f_PuC*Z|lj7oK3N14DJPs{xkG{*mLkdhXKRVB%k1hL;D**#fGP=pUXO@geCwJ CQ=LZu literal 0 HcmV?d00001 diff --git a/opendps/opendps.c b/opendps/opendps.c index 784843e7..21a735e6 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -42,7 +42,8 @@ #include "ili9163c.h" #include "gfx-padlock.h" #include "gfx-thermometer.h" -#include "gfx-power.h" +#include "gfx-poweron.h" +#include "gfx-poweroff.h" #include "gfx-wifi.h" #include "font-full_small.h" #include "font-meter_small.h" @@ -718,14 +719,17 @@ void opendps_update_wifi_status(wifi_status_t status) */ void opendps_update_power_status(bool enabled) { - if (is_enabled != enabled) { - is_enabled = enabled; - if (is_enabled) { - tft_blit((uint16_t*) gfx_power, GFX_POWER_WIDTH, GFX_POWER_HEIGHT, ui_width-GFX_POWER_WIDTH, ui_height-GFX_POWER_HEIGHT); - } else { - tft_fill(ui_width-GFX_POWER_WIDTH, ui_height-GFX_POWER_HEIGHT, GFX_POWER_WIDTH, GFX_POWER_HEIGHT, bg_color); - } - } + is_enabled = enabled; + + if (is_enabled) { + tft_blit((uint16_t*) gfx_poweron, + GFX_POWERON_WIDTH, GFX_POWERON_HEIGHT, + TFT_WIDTH-GFX_POWERON_WIDTH, TFT_HEIGHT-GFX_POWERON_HEIGHT); + } else { + tft_blit((uint16_t*) gfx_poweroff, + GFX_POWERON_WIDTH, GFX_POWERON_HEIGHT, + TFT_WIDTH-GFX_POWERON_WIDTH, TFT_HEIGHT-GFX_POWERON_HEIGHT); + } } /** From 8a82aa6082bdbc978523737bb863ea25d0af9361 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 28 Sep 2019 21:35:55 -0600 Subject: [PATCH 008/175] Added power graphics to makefile Removed white power button --- opendps/Makefile | 3 ++- opendps/gfx-power.c | 38 -------------------------------------- opendps/gfx-power.h | 13 ------------- opendps/gfx/png/power.png | Bin 493 -> 0 bytes 4 files changed, 2 insertions(+), 52 deletions(-) delete mode 100644 opendps/gfx-power.c delete mode 100644 opendps/gfx-power.h delete mode 100644 opendps/gfx/png/power.png diff --git a/opendps/Makefile b/opendps/Makefile index 44fd065e..a579b710 100644 --- a/opendps/Makefile +++ b/opendps/Makefile @@ -98,7 +98,8 @@ OBJS = \ gfx-cv.o \ gfx-cl.o \ gfx-padlock.o \ - gfx-power.o \ + gfx-poweron.o \ + gfx-poweroff.o \ gfx-thermometer.o \ gfx-wifi.o \ opendps.o diff --git a/opendps/gfx-power.c b/opendps/gfx-power.c deleted file mode 100644 index 8c664e34..00000000 --- a/opendps/gfx-power.c +++ /dev/null @@ -1,38 +0,0 @@ -/** Gfx generated from gfx\png\power.png */ - -#include "gfx-power.h" - -const uint8_t gfx_power[512] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x4c, - 0x63, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xe3, 0xf7, 0xbe, - 0xef, 0x9d, 0x18, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x21, 0x04, 0xf7, 0xbe, - 0xef, 0x9d, 0x18, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x4a, 0x89, 0xd6, 0xda, 0x8c, 0x71, 0x00, 0x00, 0x21, 0x04, 0xf7, 0xbe, - 0xef, 0x9d, 0x18, 0xe3, 0x00, 0x00, 0x8c, 0x91, 0xd6, 0xda, 0x4a, 0x69, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x31, 0xa6, 0xef, 0x9d, 0xff, 0xff, 0x94, 0xb2, 0x00, 0x00, 0x21, 0x04, 0xf7, 0xbe, - 0xef, 0x9d, 0x18, 0xe3, 0x00, 0x00, 0x9c, 0xd3, 0xff, 0xff, 0xef, 0x7d, 0x31, 0x86, 0x00, 0x00, - 0x00, 0x20, 0xbd, 0xf7, 0xff, 0xff, 0xad, 0x75, 0x08, 0x41, 0x00, 0x00, 0x21, 0x04, 0xf7, 0xbe, - 0xef, 0x9d, 0x18, 0xe3, 0x00, 0x00, 0x08, 0x41, 0xb5, 0x96, 0xff, 0xff, 0xb5, 0xd6, 0x00, 0x00, - 0x31, 0xa6, 0xf7, 0xde, 0xef, 0x7d, 0x21, 0x24, 0x00, 0x00, 0x00, 0x00, 0x18, 0xe3, 0xf7, 0xde, - 0xf7, 0xbe, 0x18, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x29, 0x45, 0xef, 0x9d, 0xf7, 0xde, 0x31, 0x86, - 0x7b, 0xcf, 0xff, 0xff, 0xb5, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0xcb, - 0x52, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0xf7, 0xff, 0xff, 0x63, 0x4c, - 0xdf, 0x1b, 0xff, 0xff, 0x9c, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x34, 0xff, 0xff, 0x84, 0x30, - 0x7b, 0xcf, 0xff, 0xff, 0xb5, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0xf7, 0xff, 0xff, 0x63, 0x4c, - 0x31, 0xa6, 0xf7, 0xde, 0xef, 0x7d, 0x21, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x45, 0xef, 0x9d, 0xf7, 0xde, 0x31, 0x86, - 0x00, 0x20, 0xbd, 0xf7, 0xff, 0xff, 0xad, 0x75, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xb5, 0xb6, 0xff, 0xff, 0xb5, 0xd6, 0x00, 0x00, - 0x00, 0x00, 0x31, 0xa6, 0xef, 0x7d, 0xff, 0xff, 0xad, 0x75, 0x21, 0x44, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x29, 0x45, 0xb5, 0x96, 0xff, 0xff, 0xef, 0x7d, 0x31, 0x86, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x4a, 0x69, 0xe7, 0x5c, 0xff, 0xff, 0xef, 0x9d, 0xad, 0x75, 0x84, 0x30, - 0x84, 0x30, 0xad, 0x95, 0xef, 0x9d, 0xff, 0xff, 0xe7, 0x5c, 0x4a, 0x49, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x65, 0xa5, 0x54, 0xef, 0x9d, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xef, 0x9d, 0xa5, 0x34, 0x29, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x24, 0x5a, 0xcb, 0x94, 0xb2, - 0x94, 0xb2, 0x5a, 0xcb, 0x21, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; \ No newline at end of file diff --git a/opendps/gfx-power.h b/opendps/gfx-power.h deleted file mode 100644 index 242f6ed2..00000000 --- a/opendps/gfx-power.h +++ /dev/null @@ -1,13 +0,0 @@ -/** Gfx generated from gfx\png\power.png */ - -#ifndef __GFX_POWER_H__ -#define __GFX_POWER_H__ - -#include - -#define GFX_POWER_HEIGHT (16) -#define GFX_POWER_WIDTH (16) - -extern const uint8_t gfx_power[512]; - -#endif // __GFX_POWER_H__ \ No newline at end of file diff --git a/opendps/gfx/png/power.png b/opendps/gfx/png/power.png deleted file mode 100644 index 78710edaecddd6b44a8c94944dc584b19a0aa4c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 493 zcmVSLCfJ8-TBB6%=Uyv($zrjTN~KsVHlNQC@!MdQ*XzCC@2aYLJf1&}(^oE+ ziy#O9AW0Gt5s@TG03Zm$>2#U{`Fvg!#d5g}0B8^ZR4Nrw6tmgvC&2T3tyT*J0u)7k z_drn;P1E&yon=`70GrJ=8jTRK-EO}FG)>=bH$_qWem?*>9FBg!kBGzJ&}y{;&-0q5 zNs<%{26gDi<8i%Sb?8VWBFpmg`D9u4C!J0c1TmRRR;$&!yxD9Dg~IFg+VA)8oyB4? zo6SQvv{v<0MIXXTssI(akVSuh&Dw)9DnC$3KN!E_Xa05%F@l zbUGbD5ClQ!cDu4HBjVw3$Ye6+tE16qtJP9f)%Z0OMQJvh48!O)!W0XILWx8onM`V$ jHXe_s)9G@#G#Y*ZXqD`R8>F0Z00000NkvXXu0mjf_b}T4 From 87352f5b626ae489aa2a6a1298afc68095839bae Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 28 Sep 2019 21:38:19 -0600 Subject: [PATCH 009/175] Ensure power button state is updated --- opendps/opendps.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/opendps/opendps.c b/opendps/opendps.c index 21a735e6..9959b28c 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -415,8 +415,13 @@ static void main_ui_tick(void) hw_get_adc_values(&i_out_raw, &v_in_raw, &v_out_raw); (void) i_out_raw; (void) v_out_raw; + + // update input voltage value input_voltage.value = pwrctl_calc_vin(v_in_raw); input_voltage.ui.draw(&input_voltage.ui); + + // Update power button + opendps_update_power_status(is_enabled); } /** From afc1bbdda818ff3b6a790314db695a0f72711b5f Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 28 Sep 2019 21:42:42 -0600 Subject: [PATCH 010/175] Updated font-meter-large to 42px --- opendps/Makefile | 2 +- opendps/font-meter_large.c | 276 ++++++++++++++++++------------------- opendps/font-meter_large.h | 14 +- 3 files changed, 142 insertions(+), 150 deletions(-) diff --git a/opendps/Makefile b/opendps/Makefile index e5449bf5..44503224 100644 --- a/opendps/Makefile +++ b/opendps/Makefile @@ -28,7 +28,7 @@ DEBUG ?= 0 METER_FONT_FILE ?= gfx/Ubuntu-C.ttf METER_FONT_SMALL_SIZE ?= 18 METER_FONT_MEDIUM_SIZE ?= 24 -METER_FONT_LARGE_SIZE ?= 40 +METER_FONT_LARGE_SIZE ?= 42 FULL_FONT_FILE ?= gfx/ProggyClean.ttf FULL_FONT_SMALL_SIZE ?= 16 diff --git a/opendps/font-meter_large.c b/opendps/font-meter_large.c index 61f6ae8b..d8d100b8 100644 --- a/opendps/font-meter_large.c +++ b/opendps/font-meter_large.c @@ -1,147 +1,139 @@ -/** Font generated from gfx/Ubuntu-C.ttf 48pt */ +/** Font generated from gfx/Ubuntu-C.ttf 42pt */ #include "font-meter_large.h" -const uint32_t font_meter_large_height = 35; -const uint8_t font_meter_large_pixdata[1745] = { +const uint32_t font_meter_large_height = 31; +const uint8_t font_meter_large_pixdata[1587] = { /* '0', offset=0 */ - 0x00, 0xf4, 0x6f, 0x00, 0x00, 0xff, 0xff, 0x02, 0xc0, 0xff, 0xff, 0x0b, 0xe0, 0xff, 0xff, 0x0f, - 0xf0, 0x3f, 0xf4, 0x2f, 0xf4, 0x0f, 0xe0, 0x3f, 0xf8, 0x0b, 0xc0, 0x3f, 0xfc, 0x07, 0xc0, 0x7f, - 0xfc, 0x07, 0x80, 0xbf, 0xfc, 0x03, 0x80, 0xbf, 0xfc, 0x03, 0x40, 0xff, 0xfd, 0x03, 0x40, 0xff, - 0xfd, 0x03, 0x40, 0xff, 0xfd, 0x03, 0x00, 0xff, 0xfd, 0x03, 0x00, 0xff, 0xfd, 0x03, 0x00, 0xff, - 0xfd, 0x03, 0x00, 0xff, 0xfd, 0x03, 0x00, 0xff, 0xfd, 0x03, 0x00, 0xff, 0xfd, 0x03, 0x00, 0xff, - 0xfd, 0x03, 0x00, 0xff, 0xfd, 0x03, 0x00, 0xff, 0xfd, 0x03, 0x40, 0xff, 0xfd, 0x03, 0x40, 0xff, - 0xfc, 0x03, 0x40, 0xff, 0xfc, 0x03, 0x80, 0xbf, 0xfc, 0x07, 0x80, 0xbf, 0xfc, 0x07, 0xc0, 0x7f, - 0xf8, 0x0b, 0xc0, 0x3f, 0xf4, 0x0f, 0xe0, 0x3f, 0xf0, 0x3f, 0xf4, 0x2f, 0xe0, 0xff, 0xff, 0x0f, - 0xc0, 0xff, 0xff, 0x0b, 0x00, 0xff, 0xff, 0x02, 0x00, 0xf4, 0x6f, 0x00, - /* '1', offset=140 */ - 0x00, 0x00, 0x00, 0xc0, 0x0f, 0x80, 0x3f, 0x40, 0xff, 0x40, 0xff, 0x03, 0xff, 0x4f, 0xff, 0x7f, - 0xff, 0xff, 0xff, 0xfd, 0xff, 0xf0, 0x9f, 0xc0, 0x3f, 0x00, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0x0f, - 0xc0, 0x3f, 0x00, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0x0f, 0xc0, 0x3f, 0x00, 0xff, 0x00, 0xfc, 0x03, - 0xf0, 0x0f, 0xc0, 0x3f, 0x00, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0x0f, 0xc0, 0x3f, 0x00, 0xff, 0x00, - 0xfc, 0x03, 0xf0, 0x0f, 0xc0, 0x3f, 0x00, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0x0f, 0x00, 0x00, - /* '2', offset=219 */ - 0x40, 0xfe, 0x1b, 0x00, 0xf4, 0xff, 0xff, 0x01, 0xfd, 0xff, 0xff, 0x07, 0xfd, 0xff, 0xff, 0x0f, - 0xfc, 0x01, 0xfd, 0x1f, 0x20, 0x00, 0xf0, 0x2f, 0x00, 0x00, 0xe0, 0x3f, 0x00, 0x00, 0xd0, 0x3f, - 0x00, 0x00, 0xd0, 0x3f, 0x00, 0x00, 0xd0, 0x3f, 0x00, 0x00, 0xd0, 0x3f, 0x00, 0x00, 0xe0, 0x2f, - 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xf4, 0x0f, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, 0xfe, 0x02, - 0x00, 0x40, 0xff, 0x00, 0x00, 0xc0, 0x7f, 0x00, 0x00, 0xe0, 0x3f, 0x00, 0x00, 0xf4, 0x0f, 0x00, - 0x00, 0xfc, 0x07, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x40, 0xff, 0x00, 0x00, 0xc0, 0xbf, 0x00, 0x00, - 0xd0, 0x3f, 0x00, 0x00, 0xe0, 0x1f, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xf4, 0x0b, 0x00, 0x00, - 0xf8, 0x07, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xbf, 0xfc, 0xff, 0xff, 0xbf, - 0xfc, 0xff, 0xff, 0xbf, 0xfc, 0xff, 0xff, 0xbf, 0x00, 0x00, 0x00, 0x00, - /* '3', offset=359 */ - 0x40, 0xfe, 0x0b, 0x00, 0xfe, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0xff, 0x0f, 0xb8, - 0x01, 0xfe, 0x0b, 0x04, 0x00, 0xfe, 0x03, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc0, 0x7f, 0x00, 0x00, - 0xe0, 0x1f, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0xff, 0x01, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0xf4, - 0x0f, 0x00, 0x00, 0xff, 0x01, 0x00, 0xf8, 0x3f, 0x00, 0xfd, 0xff, 0x03, 0x40, 0xff, 0x2f, 0x00, - 0xd0, 0xff, 0x2f, 0x00, 0xf4, 0xff, 0x3f, 0x00, 0x00, 0xf9, 0x3f, 0x00, 0x00, 0xf4, 0x1f, 0x00, - 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, - 0xf0, 0x0f, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xff, 0x00, 0x00, 0xd0, 0x3f, 0x01, 0x00, 0xfc, - 0xcb, 0x07, 0xe0, 0xff, 0xf9, 0xff, 0xff, 0x2f, 0xff, 0xff, 0xff, 0x43, 0xff, 0xff, 0x2f, 0x00, - 0xf9, 0xbf, 0x00, 0x00, - /* '4', offset=491 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x3f, 0x00, 0x00, 0xc0, 0xff, 0x00, 0x00, 0x80, 0xff, - 0x03, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xfe, 0x3f, 0x00, 0x00, 0xfc, 0xff, 0x00, 0x00, 0xf8, - 0xfb, 0x03, 0x00, 0xf0, 0xe7, 0x0f, 0x00, 0xe0, 0x8f, 0x3f, 0x00, 0xc0, 0x1f, 0xfe, 0x00, 0x80, - 0x3f, 0xf8, 0x03, 0x00, 0x7f, 0xe0, 0x0f, 0x00, 0xfe, 0x80, 0x3f, 0x00, 0xfc, 0x01, 0xfe, 0x00, - 0xf4, 0x03, 0xf8, 0x03, 0xf0, 0x0b, 0xe0, 0x0f, 0xd0, 0x0f, 0x80, 0x3f, 0x80, 0x3f, 0x00, 0xfe, - 0x00, 0x7f, 0x00, 0xf8, 0x03, 0xfd, 0x00, 0xe0, 0x0f, 0xf8, 0x02, 0x80, 0x3f, 0xf0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, - 0x00, 0xfe, 0x00, 0x00, 0x00, 0xf8, 0x03, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0x80, 0x3f, 0x00, - 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0xf8, 0x03, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0x80, 0x3f, + 0x00, 0xfd, 0x07, 0x00, 0xfc, 0xff, 0x03, 0xe0, 0xff, 0xff, 0x40, 0xbf, 0xe0, 0x1f, 0xf8, 0x03, + 0xfc, 0xc2, 0x2f, 0x80, 0x3f, 0xfc, 0x02, 0xf4, 0xd3, 0x1f, 0x40, 0x7f, 0xfd, 0x00, 0xf0, 0xeb, + 0x0f, 0x00, 0xbf, 0xfe, 0x00, 0xf0, 0xeb, 0x0f, 0x00, 0xff, 0xff, 0x00, 0xf0, 0xff, 0x0f, 0x00, + 0xff, 0xff, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0xff, 0xff, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0xff, 0xff, + 0x00, 0xf0, 0xef, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0xf0, 0xeb, 0x0f, 0x00, 0xbf, 0xfd, 0x00, 0xf0, + 0xdb, 0x1f, 0x40, 0x7f, 0xfc, 0x01, 0xf4, 0xc3, 0x2f, 0x80, 0x3f, 0xf8, 0x03, 0xfc, 0x42, 0xbf, + 0xe0, 0x1f, 0xe0, 0xff, 0xbf, 0x00, 0xfc, 0xff, 0x03, 0x00, 0xfd, 0x07, 0x00, + /* '1', offset=109 */ + 0x00, 0x00, 0x00, 0xd0, 0x0b, 0xd0, 0x2f, 0xc0, 0xbf, 0xd0, 0xff, 0xe2, 0xff, 0xfb, 0xff, 0x6f, + 0x3f, 0xbf, 0x1c, 0xfc, 0x02, 0xf0, 0x0b, 0xc0, 0x2f, 0x00, 0xbf, 0x00, 0xfc, 0x02, 0xf0, 0x0b, + 0xc0, 0x2f, 0x00, 0xbf, 0x00, 0xfc, 0x02, 0xf0, 0x0b, 0xc0, 0x2f, 0x00, 0xbf, 0x00, 0xfc, 0x02, + 0xf0, 0x0b, 0xc0, 0x2f, 0x00, 0xbf, 0x00, 0xfc, 0x02, 0xf0, 0x0b, 0xc0, 0x2f, 0x00, 0xbf, 0x00, + 0xfc, 0x02, 0xf0, 0x0b, 0x00, 0x00, + /* '2', offset=179 */ + 0x90, 0xff, 0x06, 0xc0, 0xff, 0xff, 0x02, 0xff, 0xff, 0xbf, 0xd0, 0x07, 0xf4, 0x0f, 0x04, 0x00, + 0xfd, 0x02, 0x00, 0xc0, 0x2f, 0x00, 0x00, 0xfc, 0x03, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0xfc, 0x03, + 0x00, 0xc0, 0x2f, 0x00, 0x00, 0xfd, 0x01, 0x00, 0xf0, 0x0f, 0x00, 0x40, 0xbf, 0x00, 0x00, 0xfc, + 0x03, 0x00, 0xe0, 0x2f, 0x00, 0x40, 0xff, 0x00, 0x00, 0xfc, 0x07, 0x00, 0xe0, 0x2f, 0x00, 0x40, + 0xff, 0x00, 0x00, 0xfc, 0x07, 0x00, 0xd0, 0x2f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xf4, 0x0b, 0x00, + 0x80, 0x3f, 0x00, 0x00, 0xfc, 0x03, 0x00, 0xc0, 0x2f, 0x00, 0x00, 0xfd, 0x01, 0x00, 0xd0, 0xff, + 0xff, 0xbf, 0xfd, 0xff, 0xff, 0xeb, 0xff, 0xff, 0xbf, 0x00, 0x00, 0x00, 0x00, + /* '3', offset=288 */ + 0x90, 0xff, 0x01, 0xf4, 0xff, 0x3f, 0xe0, 0xff, 0xff, 0x03, 0x1f, 0xf0, 0x2f, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xf8, 0x03, 0x00, 0xd0, 0x1f, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xfd, 0x01, 0x00, 0xf4, + 0x03, 0x00, 0xf0, 0x0f, 0x00, 0xd0, 0x2f, 0x00, 0xe0, 0x3f, 0x00, 0xff, 0x3f, 0x00, 0xfc, 0x7f, + 0x00, 0xf0, 0xff, 0x0b, 0x00, 0xd0, 0xbf, 0x00, 0x00, 0xfc, 0x07, 0x00, 0xc0, 0x2f, 0x00, 0x00, + 0xff, 0x00, 0x00, 0xf8, 0x03, 0x00, 0xd0, 0x0f, 0x00, 0x40, 0x3f, 0x00, 0x00, 0xfe, 0x00, 0x00, + 0xf8, 0x03, 0x00, 0xf0, 0x0f, 0x00, 0xe0, 0x9f, 0x0b, 0xe0, 0x3f, 0xff, 0xff, 0x7f, 0xf8, 0xff, + 0x7f, 0x00, 0xfe, 0x1f, 0x00, + /* '4', offset=389 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0xf4, 0x0f, 0x00, 0x00, 0xff, 0x03, 0x00, + 0xe0, 0xff, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x80, 0xef, 0x0f, 0x00, 0xf0, 0xf7, 0x03, 0x00, 0x7e, + 0xfc, 0x00, 0xc0, 0x0f, 0x3f, 0x00, 0xf4, 0xc2, 0x0f, 0x00, 0x3f, 0xf0, 0x03, 0xd0, 0x0b, 0xfc, + 0x00, 0xf8, 0x00, 0x3f, 0x00, 0x3f, 0xc0, 0x0f, 0xe0, 0x07, 0xf0, 0x03, 0xfc, 0x00, 0xfc, 0x40, + 0x2f, 0x00, 0x3f, 0xe0, 0x07, 0xc0, 0x0f, 0xfc, 0x00, 0xf0, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0xf0, 0x03, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, + 0x3f, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, - /* '5', offset=640 */ - 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xe0, 0xff, 0xff, 0x0f, 0xfe, 0xff, 0xff, 0xe0, 0xff, - 0xff, 0x0f, 0xfe, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, - 0xff, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xf0, 0x0b, 0x00, 0x00, 0xbf, 0x00, - 0x00, 0xf0, 0xbf, 0x01, 0x00, 0xff, 0xff, 0x01, 0xf4, 0xff, 0x7f, 0x40, 0xff, 0xff, 0x1f, 0x00, - 0xf9, 0xff, 0x03, 0x00, 0xf4, 0xbf, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x40, 0xff, 0x00, 0x00, 0xf0, - 0x0f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xf0, 0x0f, 0x00, - 0x00, 0xff, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0xd0, 0x7f, 0x1a, 0x90, 0xff, 0xf3, 0xff, 0xff, 0x1f, - 0xff, 0xff, 0x7f, 0xf0, 0xff, 0xff, 0x01, 0xe4, 0xbf, 0x01, 0x00, - /* '6', offset=763 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x07, 0x00, 0x40, 0xff, 0x07, 0x00, 0xe0, 0xff, 0x0b, - 0x00, 0xfc, 0xff, 0x0b, 0x00, 0xff, 0x6f, 0x00, 0x80, 0xff, 0x02, 0x00, 0xc0, 0xbf, 0x00, 0x00, - 0xe0, 0x2f, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xf8, 0x0b, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, - 0xfc, 0x03, 0x00, 0x00, 0xfd, 0x02, 0x00, 0x00, 0xfd, 0xf6, 0x2f, 0x00, 0xfe, 0xff, 0xff, 0x01, - 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x0f, 0xff, 0x07, 0xf8, 0x1f, 0xff, 0x00, 0xf0, 0x3f, - 0xff, 0x00, 0xd0, 0x3f, 0xff, 0x00, 0xc0, 0x3f, 0xff, 0x00, 0xc0, 0x7f, 0xff, 0x00, 0xc0, 0x7f, - 0xff, 0x01, 0xc0, 0x7f, 0xfe, 0x01, 0xc0, 0x7f, 0xfe, 0x01, 0xc0, 0x7f, 0xfd, 0x02, 0xc0, 0x3f, - 0xfc, 0x03, 0xd0, 0x3f, 0xfc, 0x07, 0xe0, 0x2f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf0, 0xff, 0xff, 0x0f, - 0xd0, 0xff, 0xff, 0x07, 0x80, 0xff, 0xff, 0x01, 0x00, 0xf8, 0x2f, 0x00, - /* '7', offset=903 */ - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xc0, 0xbf, 0x00, 0x00, 0xd0, 0x3f, 0x00, 0x00, 0xe0, 0x2f, - 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xf8, 0x0b, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xfd, 0x03, - 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0xff, 0x00, 0x00, 0x40, 0xbf, 0x00, 0x00, 0x80, 0x7f, 0x00, - 0x00, 0xc0, 0x3f, 0x00, 0x00, 0xd0, 0x3f, 0x00, 0x00, 0xe0, 0x1f, 0x00, 0x00, 0xf0, 0x0f, 0x00, - 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xf4, 0x0b, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0xfc, 0x03, 0x00, - 0x00, 0xfc, 0x03, 0x00, 0x00, 0xfd, 0x03, 0x00, 0x00, 0xfd, 0x02, 0x00, 0x00, 0xfe, 0x01, 0x00, - 0x00, 0xff, 0x01, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x40, 0xff, 0x00, 0x00, - 0x40, 0xff, 0x00, 0x00, 0x40, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* '8', offset=1043 */ - 0x00, 0xe4, 0x6f, 0x00, 0x00, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x3f, - 0xf4, 0x2f, 0xf0, 0x7f, 0xf8, 0x0b, 0xc0, 0xbf, 0xfc, 0x07, 0x80, 0xff, 0xfc, 0x03, 0x40, 0xff, - 0xfc, 0x03, 0x00, 0xff, 0xfc, 0x03, 0x40, 0xff, 0xfc, 0x03, 0x40, 0xbf, 0xf8, 0x07, 0x80, 0x7f, - 0xf4, 0x0f, 0xc0, 0x3f, 0xf0, 0x1f, 0xe0, 0x1f, 0xc0, 0x7f, 0xf4, 0x0b, 0x40, 0xff, 0xfe, 0x03, - 0x00, 0xfd, 0xff, 0x00, 0x00, 0xfe, 0xbf, 0x00, 0x80, 0xff, 0xff, 0x02, 0xd0, 0x2f, 0xfd, 0x0b, - 0xf0, 0x0f, 0xf0, 0x2f, 0xf8, 0x07, 0xd0, 0x3f, 0xfc, 0x03, 0x80, 0xbf, 0xfd, 0x02, 0x00, 0xff, - 0xfe, 0x01, 0x00, 0xff, 0xfe, 0x01, 0x00, 0xfe, 0xfe, 0x01, 0x00, 0xff, 0xfe, 0x02, 0x00, 0xff, - 0xfe, 0x03, 0x00, 0xff, 0xfd, 0x07, 0xc0, 0xbf, 0xfc, 0x2f, 0xf0, 0x7f, 0xf4, 0xff, 0xff, 0x2f, - 0xe0, 0xff, 0xff, 0x0f, 0x40, 0xff, 0xff, 0x02, 0x00, 0xf8, 0x6f, 0x00, - /* '9', offset=1183 */ - 0x00, 0xfd, 0x1b, 0x00, 0xf4, 0xff, 0x2f, 0x00, 0xff, 0xff, 0x2f, 0xf0, 0xff, 0xff, 0x0f, 0xfc, - 0x0b, 0xfd, 0x8b, 0xff, 0x00, 0xfd, 0xf3, 0x1f, 0x00, 0xff, 0xfd, 0x03, 0x40, 0xbf, 0xff, 0x00, - 0xd0, 0xef, 0x3f, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0xfc, 0xff, 0x03, 0x00, 0xff, 0xff, 0x00, 0xc0, - 0xff, 0x3f, 0x00, 0xf0, 0xff, 0x1f, 0x00, 0xfc, 0xfb, 0x0f, 0x00, 0xff, 0xfd, 0x1f, 0xe4, 0x3f, - 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x43, 0xff, 0xff, 0xff, 0x00, 0xfe, 0xeb, 0x2f, 0x00, - 0x00, 0xf8, 0x07, 0x00, 0x00, 0xff, 0x01, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0xf8, 0x0b, 0x00, 0x00, - 0xff, 0x01, 0x00, 0xe0, 0x3f, 0x00, 0x00, 0xfe, 0x07, 0x00, 0xe0, 0xbf, 0x00, 0x90, 0xff, 0x0f, - 0xc0, 0xff, 0xff, 0x00, 0xe0, 0xff, 0x0f, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0xbd, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - /* '.', offset=1315 */ + /* '5', offset=506 */ + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0b, 0xfc, 0xff, 0x2f, 0xf0, 0xff, 0xbf, 0xd0, 0x0f, 0x00, + 0x40, 0x3f, 0x00, 0x00, 0xfd, 0x00, 0x00, 0xf4, 0x03, 0x00, 0xd0, 0x0f, 0x00, 0x40, 0x2f, 0x00, + 0x00, 0xbe, 0x00, 0x00, 0xf8, 0x02, 0x00, 0xe0, 0x0b, 0x00, 0xc0, 0xff, 0x02, 0x00, 0xff, 0xbf, + 0x00, 0xfc, 0xff, 0x0f, 0x00, 0xf9, 0xff, 0x00, 0x00, 0xfd, 0x07, 0x00, 0xd0, 0x2f, 0x00, 0x00, + 0xff, 0x00, 0x00, 0xf8, 0x03, 0x00, 0xd0, 0x0f, 0x00, 0x40, 0x3f, 0x00, 0x00, 0xfe, 0x00, 0x00, + 0xf8, 0x03, 0x00, 0xf0, 0x0b, 0x00, 0xe0, 0x0f, 0x07, 0xf4, 0x2f, 0xfd, 0xff, 0x3f, 0xf8, 0xff, + 0x2f, 0x40, 0xfe, 0x0b, 0x00, + /* '6', offset=607 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0xff, 0x07, 0x40, 0xff, 0x2f, 0x40, 0xff, 0x07, + 0x00, 0xff, 0x01, 0x00, 0xff, 0x00, 0x00, 0xfd, 0x00, 0x00, 0xfc, 0x02, 0x00, 0xf0, 0x07, 0x00, + 0xd0, 0x0f, 0x00, 0x80, 0x3f, 0x00, 0x00, 0xff, 0xfe, 0x06, 0xfc, 0xff, 0xbf, 0xf0, 0xff, 0xff, + 0xc7, 0x7f, 0xd0, 0x3f, 0x7f, 0x00, 0xfd, 0xfd, 0x01, 0xf0, 0xfb, 0x07, 0xc0, 0xff, 0x1f, 0x00, + 0xfe, 0x7f, 0x00, 0xf8, 0xff, 0x01, 0xe0, 0xff, 0x07, 0x80, 0xff, 0x2f, 0x00, 0xfe, 0xbf, 0x00, + 0xfc, 0xfb, 0x03, 0xf0, 0xdb, 0x1f, 0xd0, 0x1f, 0xff, 0xc1, 0x3f, 0xf4, 0xff, 0x7f, 0x80, 0xff, + 0xbf, 0x00, 0xe4, 0x6f, 0x00, + /* '7', offset=708 */ + 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0xf4, 0x07, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0xfd, 0x01, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0x7f, 0x00, + 0x00, 0xf8, 0x03, 0x00, 0xc0, 0x2f, 0x00, 0x00, 0xfc, 0x01, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xbf, + 0x00, 0x00, 0xf0, 0x07, 0x00, 0x40, 0x3f, 0x00, 0x00, 0xf8, 0x03, 0x00, 0xc0, 0x2f, 0x00, 0x00, + 0xfc, 0x01, 0x00, 0xd0, 0x0f, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xf0, 0x0b, 0x00, 0x00, 0x7f, 0x00, + 0x00, 0xf4, 0x07, 0x00, 0x80, 0x3f, 0x00, 0x00, 0xf8, 0x03, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0xfc, + 0x02, 0x00, 0xc0, 0x2f, 0x00, 0x00, 0xfc, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + /* '8', offset=817 */ + 0x00, 0xfd, 0x0b, 0x00, 0xfc, 0xff, 0x07, 0xf0, 0xff, 0xff, 0x81, 0xbf, 0xd0, 0x3f, 0xfc, 0x02, + 0xf8, 0xc7, 0x1f, 0x00, 0xbf, 0xfd, 0x00, 0xf0, 0xdb, 0x0f, 0x00, 0xbf, 0xfd, 0x00, 0xf0, 0xcb, + 0x1f, 0x00, 0x7f, 0xfc, 0x02, 0xf4, 0x43, 0x3f, 0xc0, 0x2f, 0xf0, 0x0f, 0xfe, 0x00, 0xfc, 0xfb, + 0x07, 0x40, 0xff, 0x1f, 0x00, 0xf4, 0xff, 0x00, 0xd0, 0xef, 0x3f, 0x00, 0x7f, 0xf4, 0x0f, 0xfc, + 0x02, 0xfd, 0xd2, 0x0f, 0x80, 0x7f, 0xfe, 0x00, 0xf0, 0xfb, 0x0b, 0x00, 0xfe, 0xbf, 0x00, 0xe0, + 0xff, 0x0b, 0x00, 0xfe, 0xbf, 0x00, 0xe0, 0xff, 0x0f, 0x00, 0xbf, 0xfd, 0x01, 0xf4, 0xc7, 0x7f, + 0xd0, 0x3f, 0xf4, 0xff, 0xff, 0x00, 0xfd, 0xff, 0x07, 0x00, 0xfe, 0x07, 0x00, + /* '9', offset=926 */ + 0x00, 0xfe, 0x07, 0x00, 0xfc, 0xff, 0x03, 0xf0, 0xff, 0xff, 0x40, 0xbf, 0xe0, 0x1f, 0xfc, 0x03, + 0xfc, 0xc3, 0x1f, 0x40, 0x3f, 0xfd, 0x01, 0xf0, 0xd7, 0x0f, 0x00, 0xbf, 0xfe, 0x00, 0xf0, 0xeb, + 0x0f, 0x00, 0xbf, 0xfe, 0x00, 0xf0, 0xef, 0x0f, 0x00, 0xff, 0xfd, 0x01, 0xf0, 0xcf, 0x2f, 0x00, + 0xff, 0xfc, 0x03, 0xf0, 0x4f, 0xff, 0x40, 0xff, 0xf0, 0xff, 0xff, 0x0b, 0xfc, 0xff, 0xbf, 0x00, + 0xfe, 0xfb, 0x07, 0x00, 0x40, 0x3f, 0x00, 0x00, 0xf8, 0x03, 0x00, 0xc0, 0x2f, 0x00, 0x00, 0xfd, + 0x01, 0x00, 0xf0, 0x0f, 0x00, 0x80, 0x7f, 0x00, 0x00, 0xfe, 0x02, 0x40, 0xfe, 0x0f, 0x40, 0xff, + 0x2f, 0x00, 0xf0, 0x7f, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* '.', offset=1035 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf3, 0xff, 0xff, 0xff, 0xff, 0x8f, 0x0f, - /* 'V', offset=1359 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x2f, 0x00, 0x00, 0x80, 0xff, 0xfe, 0x03, 0x00, 0x00, 0xfc, - 0xeb, 0x3f, 0x00, 0x00, 0xc0, 0x7f, 0xfd, 0x03, 0x00, 0x00, 0xfc, 0xc3, 0x7f, 0x00, 0x00, 0xd0, - 0x3f, 0xfc, 0x0b, 0x00, 0x00, 0xfe, 0x82, 0xbf, 0x00, 0x00, 0xe0, 0x1f, 0xf4, 0x0f, 0x00, 0x00, - 0xff, 0x01, 0xff, 0x00, 0x00, 0xf0, 0x0f, 0xf0, 0x1f, 0x00, 0x40, 0xff, 0x00, 0xfe, 0x02, 0x00, - 0xf8, 0x0b, 0xd0, 0x3f, 0x00, 0xc0, 0x7f, 0x00, 0xfc, 0x03, 0x00, 0xfc, 0x03, 0xc0, 0x3f, 0x00, - 0xd0, 0x3f, 0x00, 0xf8, 0x07, 0x00, 0xfd, 0x02, 0x40, 0xbf, 0x00, 0xe0, 0x1f, 0x00, 0xf0, 0x0f, - 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0xf0, 0x0f, 0x00, 0xe0, 0x1f, 0x40, 0xbf, 0x00, 0x00, 0xfd, - 0x02, 0xf8, 0x07, 0x00, 0xc0, 0x3f, 0xc0, 0x3f, 0x00, 0x00, 0xfc, 0x03, 0xfc, 0x02, 0x00, 0x80, - 0xbf, 0xe0, 0x1f, 0x00, 0x00, 0xf4, 0x0f, 0xff, 0x00, 0x00, 0x00, 0xff, 0xf0, 0x0f, 0x00, 0x00, - 0xe0, 0x5f, 0xbf, 0x00, 0x00, 0x00, 0xfd, 0xfa, 0x03, 0x00, 0x00, 0xc0, 0xff, 0x3f, 0x00, 0x00, - 0x00, 0xfc, 0xff, 0x02, 0x00, 0x00, 0x40, 0xff, 0x1f, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, - 0x00, 0x00, 0xff, 0x0b, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, - /* 'A', offset=1552 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xbf, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x0f, 0x00, - 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x40, 0xff, 0x2f, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, - 0x00, 0x00, 0xc0, 0xff, 0x3f, 0x00, 0x00, 0x00, 0xfd, 0xfa, 0x07, 0x00, 0x00, 0xe0, 0x0f, 0xff, - 0x00, 0x00, 0x00, 0xff, 0xf0, 0x0f, 0x00, 0x00, 0xf0, 0x0b, 0xfe, 0x01, 0x00, 0x80, 0x7f, 0xd0, - 0x2f, 0x00, 0x00, 0xfc, 0x03, 0xfc, 0x03, 0x00, 0xc0, 0x2f, 0xc0, 0x3f, 0x00, 0x00, 0xfd, 0x01, - 0xf8, 0x07, 0x00, 0xe0, 0x0f, 0x40, 0xff, 0x00, 0x00, 0xff, 0x00, 0xf0, 0x0f, 0x00, 0xf0, 0x0b, - 0x00, 0xff, 0x01, 0x40, 0x7f, 0x00, 0xe0, 0x2f, 0x00, 0xf8, 0x03, 0x00, 0xfd, 0x03, 0xc0, 0x3f, - 0x00, 0xc0, 0x3f, 0x00, 0xfc, 0x02, 0x00, 0xfc, 0x07, 0xd0, 0xff, 0xff, 0xff, 0xbf, 0x00, 0xfe, - 0xff, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xbf, 0x00, 0x00, 0xe0, 0x1f, 0xf4, - 0x07, 0x00, 0x00, 0xfd, 0x82, 0x7f, 0x00, 0x00, 0xd0, 0x2f, 0xfc, 0x03, 0x00, 0x00, 0xfc, 0xc3, - 0x3f, 0x00, 0x00, 0xc0, 0x3f, 0xfd, 0x02, 0x00, 0x00, 0xfc, 0xe7, 0x2f, 0x00, 0x00, 0x80, 0xbf, - 0xfe, 0x01, 0x00, 0x00, 0xf4, 0xff, 0x0f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, + 0x80, 0x5f, 0xff, 0xfe, 0xf7, 0x8f, 0x1f, + /* 'V', offset=1074 */ + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0x00, 0xfc, 0xfa, 0x07, + 0x00, 0x40, 0xbf, 0xfd, 0x01, 0x00, 0xd0, 0x1f, 0xbf, 0x00, 0x00, 0xf8, 0xc3, 0x3f, 0x00, 0x00, + 0xff, 0xf0, 0x0f, 0x00, 0xc0, 0x2f, 0xf8, 0x03, 0x00, 0xf0, 0x07, 0xfd, 0x01, 0x00, 0xfd, 0x00, + 0xbf, 0x00, 0x80, 0x3f, 0xc0, 0x3f, 0x00, 0xf0, 0x0b, 0xe0, 0x0f, 0x00, 0xfc, 0x01, 0xf4, 0x07, + 0x40, 0x3f, 0x00, 0xfc, 0x02, 0xe0, 0x0f, 0x00, 0xff, 0x00, 0xfc, 0x02, 0x80, 0x3f, 0x00, 0x7f, + 0x00, 0xd0, 0x1f, 0xd0, 0x0f, 0x00, 0xf0, 0x0b, 0xf8, 0x03, 0x00, 0xf8, 0x03, 0xbf, 0x00, 0x00, + 0xfd, 0xc0, 0x1f, 0x00, 0x00, 0x7f, 0xf4, 0x03, 0x00, 0xc0, 0x2f, 0xbe, 0x00, 0x00, 0xe0, 0xcf, + 0x1f, 0x00, 0x00, 0xf4, 0xf7, 0x03, 0x00, 0x00, 0xfc, 0xff, 0x00, 0x00, 0x00, 0xfe, 0x2f, 0x00, + 0x00, 0x40, 0xff, 0x03, 0x00, 0x00, 0xc0, 0xff, 0x00, 0x00, 0x00, 0xe0, 0x2f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + /* 'A', offset=1222 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x2f, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0x00, + 0xff, 0x07, 0x00, 0x00, 0xe0, 0xff, 0x02, 0x00, 0x00, 0xfc, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x7f, + 0x00, 0x00, 0xd0, 0xcf, 0x2f, 0x00, 0x00, 0xfc, 0xe2, 0x0f, 0x00, 0x00, 0x3f, 0xf0, 0x03, 0x00, + 0xd0, 0x0f, 0xfc, 0x02, 0x00, 0xf8, 0x02, 0xfe, 0x00, 0x00, 0x7f, 0x40, 0x3f, 0x00, 0xc0, 0x0f, + 0xc0, 0x1f, 0x00, 0xf4, 0x03, 0xf0, 0x0b, 0x00, 0xbf, 0x00, 0xf8, 0x03, 0xc0, 0x1f, 0x00, 0xfd, + 0x00, 0xf4, 0x03, 0x00, 0x7f, 0x00, 0xfe, 0x00, 0xc0, 0x2f, 0xc0, 0xff, 0xff, 0xff, 0x0f, 0xf0, + 0xff, 0xff, 0xff, 0x03, 0xfd, 0xff, 0xff, 0xff, 0x81, 0x3f, 0x00, 0x00, 0xbf, 0xe0, 0x0b, 0x00, + 0x80, 0x3f, 0xfc, 0x01, 0x00, 0xd0, 0x0f, 0x7f, 0x00, 0x00, 0xf4, 0xd7, 0x0f, 0x00, 0x00, 0xfc, + 0xfa, 0x03, 0x00, 0x00, 0xbf, 0xbf, 0x00, 0x00, 0xc0, 0xff, 0x2f, 0x00, 0x00, 0xe0, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, + /* 'W', offset=1370 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xbf, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xbf, 0xff, 0x00, 0x40, 0xff, 0x00, 0x00, 0xbf, 0xfe, 0x00, 0x40, 0xff, 0x01, 0x00, + 0x7f, 0xfe, 0x00, 0x80, 0xff, 0x02, 0x00, 0x7f, 0xfd, 0x00, 0xc0, 0xff, 0x03, 0x40, 0x3f, 0xfc, + 0x01, 0xc0, 0xff, 0x03, 0x40, 0x3f, 0xfc, 0x01, 0xd0, 0xfb, 0x03, 0x80, 0x3f, 0xfc, 0x02, 0xe0, + 0xe7, 0x07, 0x80, 0x2f, 0xfc, 0x02, 0xf0, 0xd3, 0x0b, 0xc0, 0x2f, 0xf8, 0x03, 0xf0, 0xc3, 0x0f, + 0xc0, 0x1f, 0xf4, 0x03, 0xf4, 0xc2, 0x0f, 0xc0, 0x0f, 0xf4, 0x03, 0xf8, 0x81, 0x1f, 0xd0, 0x0f, + 0xf0, 0x07, 0xfc, 0x40, 0x2f, 0xd0, 0x0f, 0xf0, 0x07, 0xfc, 0x00, 0x3f, 0xe0, 0x0b, 0xf0, 0x0b, + 0xbd, 0x00, 0x3f, 0xe0, 0x0b, 0xe0, 0x0b, 0x7e, 0x00, 0x7e, 0xf0, 0x07, 0xd0, 0x0f, 0x3f, 0x00, + 0xbd, 0xf0, 0x03, 0xc0, 0x0f, 0x3f, 0x00, 0xfc, 0xf0, 0x03, 0xc0, 0x4f, 0x2f, 0x00, 0xfc, 0xf5, + 0x03, 0xc0, 0x9f, 0x1f, 0x00, 0xf8, 0xfa, 0x02, 0x80, 0xef, 0x0f, 0x00, 0xf4, 0xff, 0x01, 0x40, + 0xff, 0x0f, 0x00, 0xf0, 0xff, 0x00, 0x00, 0xff, 0x07, 0x00, 0xe0, 0xff, 0x00, 0x00, 0xff, 0x03, + 0x00, 0xd0, 0xbf, 0x00, 0x00, 0xfe, 0x03, 0x00, 0xc0, 0x7f, 0x00, 0x00, 0xfd, 0x02, 0x00, 0xc0, + 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; const uint8_t font_meter_large_widths[96] = { - 9u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 8u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 5u, 0u, - 16u, 9u, 16u, 15u, 17u, 14u, 16u, 16u, - 16u, 15u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 22u, 0u, 0u, 0u, 0u, 0u, 0u, + 14u, 9u, 14u, 13u, 15u, 13u, 13u, 14u, + 14u, 14u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 19u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 22u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 19u, 28u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, @@ -151,12 +143,12 @@ const uint8_t font_meter_large_widths[96] = { const uint8_t font_meter_large_sizes[96] = { 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 44u, 0u, - 140u, 79u, 140u, 132u, 149u, 123u, 140u, 140u, - 140u, 132u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 193u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 39u, 0u, + 109u, 70u, 109u, 101u, 117u, 101u, 101u, 109u, + 109u, 109u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 148u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 193u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 148u, 217u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, @@ -166,12 +158,12 @@ const uint8_t font_meter_large_sizes[96] = { const uint16_t font_meter_large_offsets[96] = { 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 1315u, 0u, - 0u, 140u, 219u, 359u, 491u, 640u, 763u, 903u, - 1043u, 1183u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 1552u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 1035u, 0u, + 0u, 109u, 179u, 288u, 389u, 506u, 607u, 708u, + 817u, 926u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 1222u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 1359u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 1074u, 1370u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, diff --git a/opendps/font-meter_large.h b/opendps/font-meter_large.h index 5e748fcc..9cf51f13 100644 --- a/opendps/font-meter_large.h +++ b/opendps/font-meter_large.h @@ -1,21 +1,21 @@ -/** Font generated from gfx/Ubuntu-C.ttf 48pt */ +/** Font generated from gfx/Ubuntu-C.ttf 42pt */ #ifndef __FONT_METER_LARGE_H__ #define __FONT_METER_LARGE_H__ #include -#define FONT_METER_LARGE_MAX_GLYPH_HEIGHT (35) -#define FONT_METER_LARGE_MAX_GLYPH_WIDTH (22) -#define FONT_METER_LARGE_MAX_DIGIT_WIDTH (17) +#define FONT_METER_LARGE_MAX_GLYPH_HEIGHT (31) +#define FONT_METER_LARGE_MAX_GLYPH_WIDTH (28) +#define FONT_METER_LARGE_MAX_DIGIT_WIDTH (15) #define FONT_METER_LARGE_DOT_WIDTH (5) -#define FONT_METER_LARGE_SPACING (4) -#define FONT_METER_LARGE_SPACE_WIDTH (9) +#define FONT_METER_LARGE_SPACING (5) +#define FONT_METER_LARGE_SPACE_WIDTH (8) extern const uint32_t font_meter_large_height; extern const uint8_t font_meter_large_widths[96]; extern const uint8_t font_meter_large_sizes[96]; extern const uint16_t font_meter_large_offsets[96]; -extern const uint8_t font_meter_large_pixdata[1745]; +extern const uint8_t font_meter_large_pixdata[1587]; #endif // __FONT_METER_LARGE_H__ \ No newline at end of file From 223f30b233cc82c25c07cf89c8f472401fe4031f Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 28 Sep 2019 21:44:34 -0600 Subject: [PATCH 011/175] Clearing screen on deactivation for func_cc/cl/cv --- opendps/func_cc.c | 11 ++++++++++- opendps/func_cl.c | 2 ++ opendps/func_cv.c | 10 +++++++++- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/opendps/func_cc.c b/opendps/func_cc.c index e3f19e7e..f328679f 100644 --- a/opendps/func_cc.c +++ b/opendps/func_cc.c @@ -119,7 +119,7 @@ ui_screen_t cc_screen = { .icon_width = GFX_CC_WIDTH, .icon_height = GFX_CC_HEIGHT, .activated = NULL, - .deactivated = NULL, + .deactivated = &deactivated, .enable = &cc_enable, .past_save = &past_save, .past_restore = &past_restore, @@ -248,6 +248,15 @@ static void current_changed(ui_number_t *item) (void) pwrctl_set_iout(item->value); } +/** + * @brief Do any required clean up before changing away from this screen + */ +static void deactivated(void) +{ + tft_clear(); +} + + /** * @brief Save persistent parameters * diff --git a/opendps/func_cl.c b/opendps/func_cl.c index 76e17040..61a163e2 100644 --- a/opendps/func_cl.c +++ b/opendps/func_cl.c @@ -277,6 +277,8 @@ static void deactivated(void) tft_fill(XPOS_CCCV, 128 - GFX_CC_HEIGHT, GFX_CC_WIDTH, GFX_CC_HEIGHT, BLACK); } current_mode_gfx = CUR_GFX_NOT_DRAWN; + + tft_clear(); } /** diff --git a/opendps/func_cv.c b/opendps/func_cv.c index 440091b4..c1446780 100644 --- a/opendps/func_cv.c +++ b/opendps/func_cv.c @@ -117,7 +117,7 @@ ui_screen_t cv_screen = { .icon_width = GFX_CV_WIDTH, .icon_height = GFX_CV_HEIGHT, .activated = NULL, - .deactivated = NULL, + .deactivated = &deactivated, .enable = &cv_enable, .past_save = &past_save, .past_restore = &past_restore, @@ -247,6 +247,14 @@ static void current_changed(ui_number_t *item) (void) pwrctl_set_ilimit(item->value); } +/** + * @brief Do any required clean up before changing away from this screen + */ +static void deactivated(void) +{ + tft_clear(); +} + /** * @brief Save persistent parameters * From e1591a319f51bb7abdd54733db9da715cf1a2bec Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 28 Sep 2019 21:45:44 -0600 Subject: [PATCH 012/175] Fixed missing deactivated spec --- opendps/func_cc.c | 1 + opendps/func_cv.c | 1 + 2 files changed, 2 insertions(+) diff --git a/opendps/func_cc.c b/opendps/func_cc.c index f328679f..a27edb90 100644 --- a/opendps/func_cc.c +++ b/opendps/func_cc.c @@ -50,6 +50,7 @@ static void cc_enable(bool _enable); static void voltage_changed(ui_number_t *item); static void current_changed(ui_number_t *item); static void cc_tick(void); +static void deactivated(void); static void past_save(past_t *past); static void past_restore(past_t *past); static set_param_status_t set_parameter(char *name, char *value); diff --git a/opendps/func_cv.c b/opendps/func_cv.c index c1446780..61f7e126 100644 --- a/opendps/func_cv.c +++ b/opendps/func_cv.c @@ -48,6 +48,7 @@ static void cv_enable(bool _enable); static void voltage_changed(ui_number_t *item); static void current_changed(ui_number_t *item); static void cv_tick(void); +static void deactivated(void); static void past_save(past_t *past); static void past_restore(past_t *past); static set_param_status_t set_parameter(char *name, char *value); From 9a03080f4856e5e7b0e6a73de91dca4602e40477 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 28 Sep 2019 22:26:44 -0600 Subject: [PATCH 013/175] Fixed --- opendps/Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/opendps/Makefile b/opendps/Makefile index f3ef7808..7d504030 100644 --- a/opendps/Makefile +++ b/opendps/Makefile @@ -53,7 +53,7 @@ CL_ENABLE ?= 1 FUNCGEN_ENABLE ?= 1 # Enable invert color feature -CONFIG_INVERT_ENABLE ?= 0 +INVERT_ENABLE ?= 0 GIT_VERSION := $(shell git describe --abbrev=4 --dirty --always --tags) CFLAGS = -I. -DGIT_VERSION=\"$(GIT_VERSION)\" -Wno-missing-braces @@ -116,6 +116,10 @@ ifeq ($(DEBUG),1) OBJS += dbg_printf.o endif +ifeq ($(INVERT_ENABLE),1) + CFLAGS +=-DCONFIG_INVERT_ENABLE +endif + ifeq ($(CC_ENABLE),1) CFLAGS +=-DCONFIG_CC_ENABLE OBJS += func_cc.o From e46803c78a9cba0d6570b5d4dc3b1966bb36a811 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 28 Sep 2019 22:28:03 -0600 Subject: [PATCH 014/175] Fixed --- opendps/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/opendps/Makefile b/opendps/Makefile index 7d504030..afa7d6b0 100644 --- a/opendps/Makefile +++ b/opendps/Makefile @@ -68,7 +68,6 @@ CFLAGS += \ -DCOLOR_VOLTAGE=$(COLOR_VOLTAGE) \ -DCOLOR_AMPERAGE=$(COLOR_AMPERAGE) \ -DCOLOR_INPUT=$(COLOR_INPUT) \ - -DCONFIG_INVERT_ENABLE=$(CONFIG_INVERT_ENABLE) \ -D$(MODEL) # Application linker script From dcc4c668bb20414ce63322af46a409b9f1096fc0 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 28 Sep 2019 22:33:11 -0600 Subject: [PATCH 015/175] Added invert color feature as an option (disabled by default). Enable with INVERT_ENABLE=1 when making --- opendps/Makefile | 7 +++++++ opendps/opendps.c | 2 ++ 2 files changed, 9 insertions(+) diff --git a/opendps/Makefile b/opendps/Makefile index 44fd065e..afa7d6b0 100644 --- a/opendps/Makefile +++ b/opendps/Makefile @@ -52,6 +52,9 @@ CL_ENABLE ?= 1 # Enable function generator mode FUNCGEN_ENABLE ?= 1 +# Enable invert color feature +INVERT_ENABLE ?= 0 + GIT_VERSION := $(shell git describe --abbrev=4 --dirty --always --tags) CFLAGS = -I. -DGIT_VERSION=\"$(GIT_VERSION)\" -Wno-missing-braces @@ -112,6 +115,10 @@ ifeq ($(DEBUG),1) OBJS += dbg_printf.o endif +ifeq ($(INVERT_ENABLE),1) + CFLAGS +=-DCONFIG_INVERT_ENABLE +endif + ifeq ($(CC_ENABLE),1) CFLAGS +=-DCONFIG_CC_ENABLE OBJS += func_cc.o diff --git a/opendps/opendps.c b/opendps/opendps.c index 784843e7..756cd4db 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -470,10 +470,12 @@ static void ui_handle_event(event_t event, uint8_t data) if (event == event_rot_press && data == press_long) { opendps_lock(!is_locked); return; +#ifdef CONFIG_INVERT_ENABLE } else if (event == event_button_sel && data == press_long) { tft_invert(!tft_is_inverted()); write_past_settings(); return; +#endif // CONFIG_INVERT_ENABLE } if (is_locked) { From 65baee4f18bee37227aa31ec5ed20c6a56fe7337 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 28 Sep 2019 22:48:52 -0600 Subject: [PATCH 016/175] Fixed spelling mistakes --- opendps/func_cc.c | 2 +- opendps/func_cl.c | 2 +- opendps/func_cv.c | 2 +- opendps/pwrctl.c | 2 +- opendps/pwrctl.h | 2 +- opendps/settings_calibration.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/opendps/func_cc.c b/opendps/func_cc.c index e3f19e7e..6febd983 100644 --- a/opendps/func_cc.c +++ b/opendps/func_cc.c @@ -43,7 +43,7 @@ * constant voltage and current limit. When power is enabled it will continously * display the current output voltage and current draw. If the user edits one * of the values when power is eabled, the other will continue to be updated. - * Thid allows for ramping the voltage and obsering the current increase. + * This allows for ramping the voltage and obsering the current increase. */ static void cc_enable(bool _enable); diff --git a/opendps/func_cl.c b/opendps/func_cl.c index 76e17040..c27c2431 100644 --- a/opendps/func_cl.c +++ b/opendps/func_cl.c @@ -43,7 +43,7 @@ * constant voltage and current limit. When power is enabled it will continously * display the current output voltage and current draw. If the user edits one * of the values when power is eabled, the other will continue to be updated. - * Thid allows for ramping the voltage and obsering the current increase. + * This allows for ramping the voltage and obsering the current increase. */ static void cl_enable(bool _enable); diff --git a/opendps/func_cv.c b/opendps/func_cv.c index 440091b4..4459528e 100644 --- a/opendps/func_cv.c +++ b/opendps/func_cv.c @@ -41,7 +41,7 @@ * constant voltage and current limit. When power is enabled it will continously * display the current output voltage and current draw. If the user edits one * of the values when power is eabled, the other will continue to be updated. - * Thid allows for ramping the voltage and obsering the current increase. + * This allows for ramping the voltage and obsering the current increase. */ static void cv_enable(bool _enable); diff --git a/opendps/pwrctl.c b/opendps/pwrctl.c index 6840ab3c..cf51ca1a 100644 --- a/opendps/pwrctl.c +++ b/opendps/pwrctl.c @@ -226,7 +226,7 @@ void pwrctl_enable_vout(bool enable) /** * @brief Return power output status - * @retval true if power output is wnabled + * @retval true if power output is enabled */ bool pwrctl_vout_enabled(void) { diff --git a/opendps/pwrctl.h b/opendps/pwrctl.h index 02c0cd8c..31fde92f 100644 --- a/opendps/pwrctl.h +++ b/opendps/pwrctl.h @@ -109,7 +109,7 @@ void pwrctl_enable_vout(bool enable); /** * @brief Return power output status - * @retval true if power output is wnabled + * @retval true if power output is enabled */ bool pwrctl_vout_enabled(void); diff --git a/opendps/settings_calibration.c b/opendps/settings_calibration.c index e24fc772..72d222ce 100644 --- a/opendps/settings_calibration.c +++ b/opendps/settings_calibration.c @@ -42,7 +42,7 @@ * constant voltage and current limit. When power is enabled it will continously * display the current output voltage and current draw. If the user edits one * of the values when power is eabled, the other will continue to be updated. - * Thid allows for ramping the voltage and obsering the current increase. + * This allows for ramping the voltage and obsering the current increase. */ static void calibration_enable(bool _enable); From e373c72e675ab118ae165be1a418e309f24b2636 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 28 Sep 2019 23:00:48 -0600 Subject: [PATCH 017/175] Made func_cv optional and made func_cv and func_cc disabled by default This is because func_cc and func_cv are replaced by the combined func_cl --- opendps/Makefile | 10 +++++++++- opendps/opendps.c | 6 +++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/opendps/Makefile b/opendps/Makefile index 44fd065e..2c868689 100644 --- a/opendps/Makefile +++ b/opendps/Makefile @@ -44,7 +44,10 @@ COLOR_INPUT ?= WHITE TINT ?= ffffff # Enable CC mode -CC_ENABLE ?= 1 +CC_ENABLE ?= 0 + +# Enable CV mode +CV_ENABLE ?= 0 # Enable cl mode CL_ENABLE ?= 1 @@ -117,6 +120,11 @@ ifeq ($(CC_ENABLE),1) OBJS += func_cc.o endif +ifeq ($(CV_ENABLE),1) + CFLAGS +=-DCONFIG_CV_ENABLE + OBJS += func_cv.o +endif + ifeq ($(CL_ENABLE),1) CFLAGS +=-DCONFIG_CL_ENABLE OBJS += func_cl.o diff --git a/opendps/opendps.c b/opendps/opendps.c index 784843e7..5102c6b0 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -54,9 +54,11 @@ #include "uui.h" #include "uui_number.h" #include "opendps.h" -#include "func_cv.h" #include "settings_calibration.h" #include "my_assert.h" +#ifdef CONFIG_CV_ENABLE +#include "func_cv.h" +#endif // CONFIG_CV_ENABLE #ifdef CONFIG_CC_ENABLE #include "func_cc.h" #endif // CONFIG_CC_ENABLE @@ -430,7 +432,9 @@ static void ui_init(void) /** Initialise the function screens */ uui_init(&func_ui, &g_past); +#ifdef CONFIG_CV_ENABLE func_cv_init(&func_ui); +#endif // CONFIG_CV_ENABLE #ifdef CONFIG_CC_ENABLE func_cc_init(&func_ui); #endif // CONFIG_CC_ENABLE From 2a7ea760dba77aa7b5a0ad00c420888160f5b3ed Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 28 Sep 2019 23:07:12 -0600 Subject: [PATCH 018/175] Removed clear code on activation because all other screens should clear on deactivation --- opendps/func_gen.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/opendps/func_gen.c b/opendps/func_gen.c index fbd71cd0..87b14979 100644 --- a/opendps/func_gen.c +++ b/opendps/func_gen.c @@ -464,10 +464,12 @@ static void func_changed(ui_icon_t *item) static void activated(void) { /** The screen is different here, let's clear it */ +/* tft_clear(); for (uint32_t i = 0; i < gen_screen.num_items; i++) { gen_screen.items[i]->draw(gen_screen.items[i]); } + */ tft_puts(FONT_FULL_SMALL, "Vout:", 6, 15+FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, 64, 20, WHITE, false); tft_puts(FONT_FULL_SMALL, "Freq:", 6, 42+FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, 64, 20, WHITE, false); tft_puts(FONT_FULL_SMALL, "Func:", 6, 69+FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, 64, 20, WHITE, false); From 18733c916a204e5364a288d8c60b91f181d88fac Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 28 Sep 2019 23:15:06 -0600 Subject: [PATCH 019/175] Function generator should not clear on activation to prevent glitchiness --- opendps/func_gen.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/opendps/func_gen.c b/opendps/func_gen.c index fbd71cd0..1cd65541 100644 --- a/opendps/func_gen.c +++ b/opendps/func_gen.c @@ -463,11 +463,6 @@ static void func_changed(ui_icon_t *item) */ static void activated(void) { - /** The screen is different here, let's clear it */ - tft_clear(); - for (uint32_t i = 0; i < gen_screen.num_items; i++) { - gen_screen.items[i]->draw(gen_screen.items[i]); - } tft_puts(FONT_FULL_SMALL, "Vout:", 6, 15+FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, 64, 20, WHITE, false); tft_puts(FONT_FULL_SMALL, "Freq:", 6, 42+FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, 64, 20, WHITE, false); tft_puts(FONT_FULL_SMALL, "Func:", 6, 69+FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, 64, 20, WHITE, false); From f8b05a864ab2282ad735ba13284ac4a92409be1a Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 29 Sep 2019 00:11:34 -0600 Subject: [PATCH 020/175] Fixed wrong reference to on/off image size --- opendps/opendps.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/opendps/opendps.c b/opendps/opendps.c index 9959b28c..04405ed5 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -724,17 +724,17 @@ void opendps_update_wifi_status(wifi_status_t status) */ void opendps_update_power_status(bool enabled) { - is_enabled = enabled; - - if (is_enabled) { - tft_blit((uint16_t*) gfx_poweron, - GFX_POWERON_WIDTH, GFX_POWERON_HEIGHT, - TFT_WIDTH-GFX_POWERON_WIDTH, TFT_HEIGHT-GFX_POWERON_HEIGHT); - } else { - tft_blit((uint16_t*) gfx_poweroff, - GFX_POWERON_WIDTH, GFX_POWERON_HEIGHT, - TFT_WIDTH-GFX_POWERON_WIDTH, TFT_HEIGHT-GFX_POWERON_HEIGHT); - } + is_enabled = enabled; + + if (is_enabled) { + tft_blit((uint16_t*) gfx_poweron, + GFX_POWERON_WIDTH, GFX_POWERON_HEIGHT, + TFT_WIDTH-GFX_POWERON_WIDTH, TFT_HEIGHT-GFX_POWERON_HEIGHT); + } else { + tft_blit((uint16_t*) gfx_poweroff, + GFX_POWEROFF_WIDTH, GFX_POWEROFF_HEIGHT, + TFT_WIDTH-GFX_POWEROFF_WIDTH, TFT_HEIGHT-GFX_POWEROFF_HEIGHT); + } } /** From adda5767c8c7e1c8bc40da12a1d82f6278bf558e Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 29 Sep 2019 00:35:29 -0600 Subject: [PATCH 021/175] Added POWER_OFF_VISIBLE and POWER_COLORED options --- opendps/Makefile | 19 +++++++++++++++++-- opendps/opendps.c | 24 ++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/opendps/Makefile b/opendps/Makefile index a579b710..58e440ca 100644 --- a/opendps/Makefile +++ b/opendps/Makefile @@ -52,6 +52,12 @@ CL_ENABLE ?= 1 # Enable function generator mode FUNCGEN_ENABLE ?= 1 +# Power buttons in color +POWER_COLORED ?= 1 + +# Power off button visible +POWER_OFF_VISIBLE ?= 0 + GIT_VERSION := $(shell git describe --abbrev=4 --dirty --always --tags) CFLAGS = -I. -DGIT_VERSION=\"$(GIT_VERSION)\" -Wno-missing-braces @@ -98,8 +104,6 @@ OBJS = \ gfx-cv.o \ gfx-cl.o \ gfx-padlock.o \ - gfx-poweron.o \ - gfx-poweroff.o \ gfx-thermometer.o \ gfx-wifi.o \ opendps.o @@ -113,6 +117,17 @@ ifeq ($(DEBUG),1) OBJS += dbg_printf.o endif +ifeq ($(POWER_COLORED),1) + CFLAGS +=-DCONFIG_POWER_COLORED + OBJS += gfx-poweron.o gfx-poweroff.o +else + OBJS += gfx-power.o +endif + +ifeq ($(POWER_OFF_VISIBLE),1) + CFLAGS +=-DCONFIG_POWER_OFF_VISIBLE +endif + ifeq ($(CC_ENABLE),1) CFLAGS +=-DCONFIG_CC_ENABLE OBJS += func_cc.o diff --git a/opendps/opendps.c b/opendps/opendps.c index 04405ed5..df82bb69 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -42,8 +42,14 @@ #include "ili9163c.h" #include "gfx-padlock.h" #include "gfx-thermometer.h" +#ifdef CONFIG_POWER_COLORED #include "gfx-poweron.h" +#ifdef CONFIG_POWER_OFF_VISIBLE #include "gfx-poweroff.h" +#endif //CONFIG_POWER_OFF_VISIBLE +#else +#include "gfx-power.h" +#endif //CONFIG_POWER_COLORED #include "gfx-wifi.h" #include "font-full_small.h" #include "font-meter_small.h" @@ -727,13 +733,31 @@ void opendps_update_power_status(bool enabled) is_enabled = enabled; if (is_enabled) { +#ifdef CONFIG_POWER_COLORED tft_blit((uint16_t*) gfx_poweron, GFX_POWERON_WIDTH, GFX_POWERON_HEIGHT, TFT_WIDTH-GFX_POWERON_WIDTH, TFT_HEIGHT-GFX_POWERON_HEIGHT); +#else + tft_blit((uint16_t*) gfx_power, + GFX_POWER_WIDTH, GFX_POWER_HEIGHT, + TFT_WIDTH-GFX_POWER_WIDTH, TFT_HEIGHT-GFX_POWER_HEIGHT); +#endif //CONFIG_POWER_COLORED + } else { +// red poweroff button visible only if colored and off_visible are set +#ifdef CONFIG_POWER_COLORED +#ifdef CONFIG_POWER_OFF_VISIBLE tft_blit((uint16_t*) gfx_poweroff, GFX_POWEROFF_WIDTH, GFX_POWEROFF_HEIGHT, TFT_WIDTH-GFX_POWEROFF_WIDTH, TFT_HEIGHT-GFX_POWEROFF_HEIGHT); +#else //not CONFIG_POWER_OFF_VISIBLE + tft_fill(ui_width-GFX_POWERON_WIDTH, ui_height-GFX_POWERON_HEIGHT, GFX_POWERON_WIDTH, GFX_POWERON_HEIGHT, bg_color); +#endif //CONFIG_POWER_OFF_VISIBLE + +#else //not CONFIG_POWER_COLORED + tft_fill(ui_width-GFX_POWER_WIDTH, ui_height-GFX_POWER_HEIGHT, GFX_POWER_WIDTH, GFX_POWER_HEIGHT, bg_color); +#endif //CONFIG_POWER_COLORED + } } From d732ec88dcc23c227bb277b0b9065134c83db466 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 29 Sep 2019 00:58:56 -0600 Subject: [PATCH 022/175] Added uncolored graphics --- opendps/gfx-power.c | 38 ++++++++++++++++++++++++++++++++++++++ opendps/gfx-power.h | 13 +++++++++++++ opendps/gfx/png/power.png | Bin 0 -> 493 bytes 3 files changed, 51 insertions(+) create mode 100644 opendps/gfx-power.c create mode 100644 opendps/gfx-power.h create mode 100644 opendps/gfx/png/power.png diff --git a/opendps/gfx-power.c b/opendps/gfx-power.c new file mode 100644 index 00000000..8c664e34 --- /dev/null +++ b/opendps/gfx-power.c @@ -0,0 +1,38 @@ +/** Gfx generated from gfx\png\power.png */ + +#include "gfx-power.h" + +const uint8_t gfx_power[512] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x4c, + 0x63, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xe3, 0xf7, 0xbe, + 0xef, 0x9d, 0x18, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x21, 0x04, 0xf7, 0xbe, + 0xef, 0x9d, 0x18, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x4a, 0x89, 0xd6, 0xda, 0x8c, 0x71, 0x00, 0x00, 0x21, 0x04, 0xf7, 0xbe, + 0xef, 0x9d, 0x18, 0xe3, 0x00, 0x00, 0x8c, 0x91, 0xd6, 0xda, 0x4a, 0x69, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x31, 0xa6, 0xef, 0x9d, 0xff, 0xff, 0x94, 0xb2, 0x00, 0x00, 0x21, 0x04, 0xf7, 0xbe, + 0xef, 0x9d, 0x18, 0xe3, 0x00, 0x00, 0x9c, 0xd3, 0xff, 0xff, 0xef, 0x7d, 0x31, 0x86, 0x00, 0x00, + 0x00, 0x20, 0xbd, 0xf7, 0xff, 0xff, 0xad, 0x75, 0x08, 0x41, 0x00, 0x00, 0x21, 0x04, 0xf7, 0xbe, + 0xef, 0x9d, 0x18, 0xe3, 0x00, 0x00, 0x08, 0x41, 0xb5, 0x96, 0xff, 0xff, 0xb5, 0xd6, 0x00, 0x00, + 0x31, 0xa6, 0xf7, 0xde, 0xef, 0x7d, 0x21, 0x24, 0x00, 0x00, 0x00, 0x00, 0x18, 0xe3, 0xf7, 0xde, + 0xf7, 0xbe, 0x18, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x29, 0x45, 0xef, 0x9d, 0xf7, 0xde, 0x31, 0x86, + 0x7b, 0xcf, 0xff, 0xff, 0xb5, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0xcb, + 0x52, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0xf7, 0xff, 0xff, 0x63, 0x4c, + 0xdf, 0x1b, 0xff, 0xff, 0x9c, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x34, 0xff, 0xff, 0x84, 0x30, + 0x7b, 0xcf, 0xff, 0xff, 0xb5, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0xf7, 0xff, 0xff, 0x63, 0x4c, + 0x31, 0xa6, 0xf7, 0xde, 0xef, 0x7d, 0x21, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x45, 0xef, 0x9d, 0xf7, 0xde, 0x31, 0x86, + 0x00, 0x20, 0xbd, 0xf7, 0xff, 0xff, 0xad, 0x75, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xb5, 0xb6, 0xff, 0xff, 0xb5, 0xd6, 0x00, 0x00, + 0x00, 0x00, 0x31, 0xa6, 0xef, 0x7d, 0xff, 0xff, 0xad, 0x75, 0x21, 0x44, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x29, 0x45, 0xb5, 0x96, 0xff, 0xff, 0xef, 0x7d, 0x31, 0x86, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x4a, 0x69, 0xe7, 0x5c, 0xff, 0xff, 0xef, 0x9d, 0xad, 0x75, 0x84, 0x30, + 0x84, 0x30, 0xad, 0x95, 0xef, 0x9d, 0xff, 0xff, 0xe7, 0x5c, 0x4a, 0x49, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x65, 0xa5, 0x54, 0xef, 0x9d, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xef, 0x9d, 0xa5, 0x34, 0x29, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x24, 0x5a, 0xcb, 0x94, 0xb2, + 0x94, 0xb2, 0x5a, 0xcb, 0x21, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; \ No newline at end of file diff --git a/opendps/gfx-power.h b/opendps/gfx-power.h new file mode 100644 index 00000000..242f6ed2 --- /dev/null +++ b/opendps/gfx-power.h @@ -0,0 +1,13 @@ +/** Gfx generated from gfx\png\power.png */ + +#ifndef __GFX_POWER_H__ +#define __GFX_POWER_H__ + +#include + +#define GFX_POWER_HEIGHT (16) +#define GFX_POWER_WIDTH (16) + +extern const uint8_t gfx_power[512]; + +#endif // __GFX_POWER_H__ \ No newline at end of file diff --git a/opendps/gfx/png/power.png b/opendps/gfx/png/power.png new file mode 100644 index 0000000000000000000000000000000000000000..78710edaecddd6b44a8c94944dc584b19a0aa4c3 GIT binary patch literal 493 zcmVSLCfJ8-TBB6%=Uyv($zrjTN~KsVHlNQC@!MdQ*XzCC@2aYLJf1&}(^oE+ ziy#O9AW0Gt5s@TG03Zm$>2#U{`Fvg!#d5g}0B8^ZR4Nrw6tmgvC&2T3tyT*J0u)7k z_drn;P1E&yon=`70GrJ=8jTRK-EO}FG)>=bH$_qWem?*>9FBg!kBGzJ&}y{;&-0q5 zNs<%{26gDi<8i%Sb?8VWBFpmg`D9u4C!J0c1TmRRR;$&!yxD9Dg~IFg+VA)8oyB4? zo6SQvv{v<0MIXXTssI(akVSuh&Dw)9DnC$3KN!E_Xa05%F@l zbUGbD5ClQ!cDu4HBjVw3$Ye6+tE16qtJP9f)%Z0OMQJvh48!O)!W0XILWx8onM`V$ jHXe_s)9G@#G#Y*ZXqD`R8>F0Z00000NkvXXu0mjf_b}T4 literal 0 HcmV?d00001 From 66cc497cdf0eb99f88095c60b6458d606f3342d7 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 29 Sep 2019 01:02:05 -0600 Subject: [PATCH 023/175] Added nerd font --- opendps/Makefile | 6 +- opendps/font-meter_large.c | 261 ++++++++++++++++-------------------- opendps/font-meter_large.h | 14 +- opendps/font-meter_medium.c | 149 ++++++++++---------- opendps/font-meter_medium.h | 14 +- opendps/font-meter_small.c | 101 +++++++------- opendps/font-meter_small.h | 10 +- opendps/gfx/nf.ttf | Bin 0 -> 1281428 bytes 8 files changed, 271 insertions(+), 284 deletions(-) create mode 100644 opendps/gfx/nf.ttf diff --git a/opendps/Makefile b/opendps/Makefile index 44fd065e..b7129cc8 100644 --- a/opendps/Makefile +++ b/opendps/Makefile @@ -25,10 +25,10 @@ WIFI := 1 DEBUG ?= 0 # Font file -METER_FONT_FILE ?= gfx/Ubuntu-C.ttf -METER_FONT_SMALL_SIZE ?= 18 +METER_FONT_FILE ?= gfx/nf.ttf +METER_FONT_SMALL_SIZE ?= 16 METER_FONT_MEDIUM_SIZE ?= 24 -METER_FONT_LARGE_SIZE ?= 48 +METER_FONT_LARGE_SIZE ?= 34 FULL_FONT_FILE ?= gfx/ProggyClean.ttf FULL_FONT_SMALL_SIZE ?= 16 diff --git a/opendps/font-meter_large.c b/opendps/font-meter_large.c index 61f6ae8b..e56c0f11 100644 --- a/opendps/font-meter_large.c +++ b/opendps/font-meter_large.c @@ -1,147 +1,120 @@ -/** Font generated from gfx/Ubuntu-C.ttf 48pt */ +/** Font generated from gfx/nf.ttf 34pt */ #include "font-meter_large.h" -const uint32_t font_meter_large_height = 35; -const uint8_t font_meter_large_pixdata[1745] = { +const uint32_t font_meter_large_height = 25; +const uint8_t font_meter_large_pixdata[1271] = { /* '0', offset=0 */ - 0x00, 0xf4, 0x6f, 0x00, 0x00, 0xff, 0xff, 0x02, 0xc0, 0xff, 0xff, 0x0b, 0xe0, 0xff, 0xff, 0x0f, - 0xf0, 0x3f, 0xf4, 0x2f, 0xf4, 0x0f, 0xe0, 0x3f, 0xf8, 0x0b, 0xc0, 0x3f, 0xfc, 0x07, 0xc0, 0x7f, - 0xfc, 0x07, 0x80, 0xbf, 0xfc, 0x03, 0x80, 0xbf, 0xfc, 0x03, 0x40, 0xff, 0xfd, 0x03, 0x40, 0xff, - 0xfd, 0x03, 0x40, 0xff, 0xfd, 0x03, 0x00, 0xff, 0xfd, 0x03, 0x00, 0xff, 0xfd, 0x03, 0x00, 0xff, - 0xfd, 0x03, 0x00, 0xff, 0xfd, 0x03, 0x00, 0xff, 0xfd, 0x03, 0x00, 0xff, 0xfd, 0x03, 0x00, 0xff, - 0xfd, 0x03, 0x00, 0xff, 0xfd, 0x03, 0x00, 0xff, 0xfd, 0x03, 0x40, 0xff, 0xfd, 0x03, 0x40, 0xff, - 0xfc, 0x03, 0x40, 0xff, 0xfc, 0x03, 0x80, 0xbf, 0xfc, 0x07, 0x80, 0xbf, 0xfc, 0x07, 0xc0, 0x7f, - 0xf8, 0x0b, 0xc0, 0x3f, 0xf4, 0x0f, 0xe0, 0x3f, 0xf0, 0x3f, 0xf4, 0x2f, 0xe0, 0xff, 0xff, 0x0f, - 0xc0, 0xff, 0xff, 0x0b, 0x00, 0xff, 0xff, 0x02, 0x00, 0xf4, 0x6f, 0x00, - /* '1', offset=140 */ - 0x00, 0x00, 0x00, 0xc0, 0x0f, 0x80, 0x3f, 0x40, 0xff, 0x40, 0xff, 0x03, 0xff, 0x4f, 0xff, 0x7f, - 0xff, 0xff, 0xff, 0xfd, 0xff, 0xf0, 0x9f, 0xc0, 0x3f, 0x00, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0x0f, - 0xc0, 0x3f, 0x00, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0x0f, 0xc0, 0x3f, 0x00, 0xff, 0x00, 0xfc, 0x03, - 0xf0, 0x0f, 0xc0, 0x3f, 0x00, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0x0f, 0xc0, 0x3f, 0x00, 0xff, 0x00, - 0xfc, 0x03, 0xf0, 0x0f, 0xc0, 0x3f, 0x00, 0xff, 0x00, 0xfc, 0x03, 0xf0, 0x0f, 0x00, 0x00, - /* '2', offset=219 */ - 0x40, 0xfe, 0x1b, 0x00, 0xf4, 0xff, 0xff, 0x01, 0xfd, 0xff, 0xff, 0x07, 0xfd, 0xff, 0xff, 0x0f, - 0xfc, 0x01, 0xfd, 0x1f, 0x20, 0x00, 0xf0, 0x2f, 0x00, 0x00, 0xe0, 0x3f, 0x00, 0x00, 0xd0, 0x3f, - 0x00, 0x00, 0xd0, 0x3f, 0x00, 0x00, 0xd0, 0x3f, 0x00, 0x00, 0xd0, 0x3f, 0x00, 0x00, 0xe0, 0x2f, - 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xf4, 0x0f, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, 0xfe, 0x02, - 0x00, 0x40, 0xff, 0x00, 0x00, 0xc0, 0x7f, 0x00, 0x00, 0xe0, 0x3f, 0x00, 0x00, 0xf4, 0x0f, 0x00, - 0x00, 0xfc, 0x07, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x40, 0xff, 0x00, 0x00, 0xc0, 0xbf, 0x00, 0x00, - 0xd0, 0x3f, 0x00, 0x00, 0xe0, 0x1f, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xf4, 0x0b, 0x00, 0x00, - 0xf8, 0x07, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xbf, 0xfc, 0xff, 0xff, 0xbf, - 0xfc, 0xff, 0xff, 0xbf, 0xfc, 0xff, 0xff, 0xbf, 0x00, 0x00, 0x00, 0x00, - /* '3', offset=359 */ - 0x40, 0xfe, 0x0b, 0x00, 0xfe, 0xff, 0x1f, 0xd0, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0xff, 0x0f, 0xb8, - 0x01, 0xfe, 0x0b, 0x04, 0x00, 0xfe, 0x03, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc0, 0x7f, 0x00, 0x00, - 0xe0, 0x1f, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0xff, 0x01, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0xf4, - 0x0f, 0x00, 0x00, 0xff, 0x01, 0x00, 0xf8, 0x3f, 0x00, 0xfd, 0xff, 0x03, 0x40, 0xff, 0x2f, 0x00, - 0xd0, 0xff, 0x2f, 0x00, 0xf4, 0xff, 0x3f, 0x00, 0x00, 0xf9, 0x3f, 0x00, 0x00, 0xf4, 0x1f, 0x00, - 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xff, 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, - 0xf0, 0x0f, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xff, 0x00, 0x00, 0xd0, 0x3f, 0x01, 0x00, 0xfc, - 0xcb, 0x07, 0xe0, 0xff, 0xf9, 0xff, 0xff, 0x2f, 0xff, 0xff, 0xff, 0x43, 0xff, 0xff, 0x2f, 0x00, - 0xf9, 0xbf, 0x00, 0x00, - /* '4', offset=491 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x3f, 0x00, 0x00, 0xc0, 0xff, 0x00, 0x00, 0x80, 0xff, - 0x03, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xfe, 0x3f, 0x00, 0x00, 0xfc, 0xff, 0x00, 0x00, 0xf8, - 0xfb, 0x03, 0x00, 0xf0, 0xe7, 0x0f, 0x00, 0xe0, 0x8f, 0x3f, 0x00, 0xc0, 0x1f, 0xfe, 0x00, 0x80, - 0x3f, 0xf8, 0x03, 0x00, 0x7f, 0xe0, 0x0f, 0x00, 0xfe, 0x80, 0x3f, 0x00, 0xfc, 0x01, 0xfe, 0x00, - 0xf4, 0x03, 0xf8, 0x03, 0xf0, 0x0b, 0xe0, 0x0f, 0xd0, 0x0f, 0x80, 0x3f, 0x80, 0x3f, 0x00, 0xfe, - 0x00, 0x7f, 0x00, 0xf8, 0x03, 0xfd, 0x00, 0xe0, 0x0f, 0xf8, 0x02, 0x80, 0x3f, 0xf0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, - 0x00, 0xfe, 0x00, 0x00, 0x00, 0xf8, 0x03, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0x80, 0x3f, 0x00, - 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0xf8, 0x03, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0x80, 0x3f, - 0x00, 0x00, 0x00, 0x00, 0x00, - /* '5', offset=640 */ - 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xe0, 0xff, 0xff, 0x0f, 0xfe, 0xff, 0xff, 0xe0, 0xff, - 0xff, 0x0f, 0xfe, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, - 0xff, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xf0, 0x0b, 0x00, 0x00, 0xbf, 0x00, - 0x00, 0xf0, 0xbf, 0x01, 0x00, 0xff, 0xff, 0x01, 0xf4, 0xff, 0x7f, 0x40, 0xff, 0xff, 0x1f, 0x00, - 0xf9, 0xff, 0x03, 0x00, 0xf4, 0xbf, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x40, 0xff, 0x00, 0x00, 0xf0, - 0x0f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xf0, 0x0f, 0x00, - 0x00, 0xff, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0xd0, 0x7f, 0x1a, 0x90, 0xff, 0xf3, 0xff, 0xff, 0x1f, - 0xff, 0xff, 0x7f, 0xf0, 0xff, 0xff, 0x01, 0xe4, 0xbf, 0x01, 0x00, - /* '6', offset=763 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x07, 0x00, 0x40, 0xff, 0x07, 0x00, 0xe0, 0xff, 0x0b, - 0x00, 0xfc, 0xff, 0x0b, 0x00, 0xff, 0x6f, 0x00, 0x80, 0xff, 0x02, 0x00, 0xc0, 0xbf, 0x00, 0x00, - 0xe0, 0x2f, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xf8, 0x0b, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, - 0xfc, 0x03, 0x00, 0x00, 0xfd, 0x02, 0x00, 0x00, 0xfd, 0xf6, 0x2f, 0x00, 0xfe, 0xff, 0xff, 0x01, - 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x0f, 0xff, 0x07, 0xf8, 0x1f, 0xff, 0x00, 0xf0, 0x3f, - 0xff, 0x00, 0xd0, 0x3f, 0xff, 0x00, 0xc0, 0x3f, 0xff, 0x00, 0xc0, 0x7f, 0xff, 0x00, 0xc0, 0x7f, - 0xff, 0x01, 0xc0, 0x7f, 0xfe, 0x01, 0xc0, 0x7f, 0xfe, 0x01, 0xc0, 0x7f, 0xfd, 0x02, 0xc0, 0x3f, - 0xfc, 0x03, 0xd0, 0x3f, 0xfc, 0x07, 0xe0, 0x2f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf0, 0xff, 0xff, 0x0f, - 0xd0, 0xff, 0xff, 0x07, 0x80, 0xff, 0xff, 0x01, 0x00, 0xf8, 0x2f, 0x00, - /* '7', offset=903 */ - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xc0, 0xbf, 0x00, 0x00, 0xd0, 0x3f, 0x00, 0x00, 0xe0, 0x2f, - 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xf8, 0x0b, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xfd, 0x03, - 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0xff, 0x00, 0x00, 0x40, 0xbf, 0x00, 0x00, 0x80, 0x7f, 0x00, - 0x00, 0xc0, 0x3f, 0x00, 0x00, 0xd0, 0x3f, 0x00, 0x00, 0xe0, 0x1f, 0x00, 0x00, 0xf0, 0x0f, 0x00, - 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xf4, 0x0b, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0xfc, 0x03, 0x00, - 0x00, 0xfc, 0x03, 0x00, 0x00, 0xfd, 0x03, 0x00, 0x00, 0xfd, 0x02, 0x00, 0x00, 0xfe, 0x01, 0x00, - 0x00, 0xff, 0x01, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x40, 0xff, 0x00, 0x00, - 0x40, 0xff, 0x00, 0x00, 0x40, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* '8', offset=1043 */ - 0x00, 0xe4, 0x6f, 0x00, 0x00, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x3f, - 0xf4, 0x2f, 0xf0, 0x7f, 0xf8, 0x0b, 0xc0, 0xbf, 0xfc, 0x07, 0x80, 0xff, 0xfc, 0x03, 0x40, 0xff, - 0xfc, 0x03, 0x00, 0xff, 0xfc, 0x03, 0x40, 0xff, 0xfc, 0x03, 0x40, 0xbf, 0xf8, 0x07, 0x80, 0x7f, - 0xf4, 0x0f, 0xc0, 0x3f, 0xf0, 0x1f, 0xe0, 0x1f, 0xc0, 0x7f, 0xf4, 0x0b, 0x40, 0xff, 0xfe, 0x03, - 0x00, 0xfd, 0xff, 0x00, 0x00, 0xfe, 0xbf, 0x00, 0x80, 0xff, 0xff, 0x02, 0xd0, 0x2f, 0xfd, 0x0b, - 0xf0, 0x0f, 0xf0, 0x2f, 0xf8, 0x07, 0xd0, 0x3f, 0xfc, 0x03, 0x80, 0xbf, 0xfd, 0x02, 0x00, 0xff, - 0xfe, 0x01, 0x00, 0xff, 0xfe, 0x01, 0x00, 0xfe, 0xfe, 0x01, 0x00, 0xff, 0xfe, 0x02, 0x00, 0xff, - 0xfe, 0x03, 0x00, 0xff, 0xfd, 0x07, 0xc0, 0xbf, 0xfc, 0x2f, 0xf0, 0x7f, 0xf4, 0xff, 0xff, 0x2f, - 0xe0, 0xff, 0xff, 0x0f, 0x40, 0xff, 0xff, 0x02, 0x00, 0xf8, 0x6f, 0x00, - /* '9', offset=1183 */ - 0x00, 0xfd, 0x1b, 0x00, 0xf4, 0xff, 0x2f, 0x00, 0xff, 0xff, 0x2f, 0xf0, 0xff, 0xff, 0x0f, 0xfc, - 0x0b, 0xfd, 0x8b, 0xff, 0x00, 0xfd, 0xf3, 0x1f, 0x00, 0xff, 0xfd, 0x03, 0x40, 0xbf, 0xff, 0x00, - 0xd0, 0xef, 0x3f, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0xfc, 0xff, 0x03, 0x00, 0xff, 0xff, 0x00, 0xc0, - 0xff, 0x3f, 0x00, 0xf0, 0xff, 0x1f, 0x00, 0xfc, 0xfb, 0x0f, 0x00, 0xff, 0xfd, 0x1f, 0xe4, 0x3f, - 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x43, 0xff, 0xff, 0xff, 0x00, 0xfe, 0xeb, 0x2f, 0x00, - 0x00, 0xf8, 0x07, 0x00, 0x00, 0xff, 0x01, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0xf8, 0x0b, 0x00, 0x00, - 0xff, 0x01, 0x00, 0xe0, 0x3f, 0x00, 0x00, 0xfe, 0x07, 0x00, 0xe0, 0xbf, 0x00, 0x90, 0xff, 0x0f, - 0xc0, 0xff, 0xff, 0x00, 0xe0, 0xff, 0x0f, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0xbd, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - /* '.', offset=1315 */ + 0x00, 0xf4, 0x6f, 0x00, 0x40, 0xff, 0xff, 0x02, 0xc0, 0xff, 0xff, 0x0b, 0xf0, 0x1f, 0xf4, 0x1f, + 0xf4, 0x07, 0xc0, 0x3f, 0xfc, 0x02, 0x80, 0x7f, 0xfc, 0x01, 0xc0, 0xbf, 0xfd, 0x00, 0xf0, 0xff, + 0xfe, 0x00, 0xf8, 0xfe, 0xbe, 0x00, 0xbc, 0xfd, 0xbe, 0x00, 0x3f, 0xfc, 0xbf, 0x80, 0x0f, 0xfc, + 0xbf, 0xd0, 0x07, 0xfc, 0xbf, 0xf0, 0x03, 0xfc, 0xbe, 0xf8, 0x00, 0xfc, 0xfe, 0x7d, 0x00, 0xfd, + 0xfe, 0x2f, 0x00, 0xfd, 0xfd, 0x0f, 0x00, 0xfe, 0xfc, 0x07, 0x00, 0xbf, 0xfc, 0x03, 0x00, 0x7f, + 0xf4, 0x07, 0xc0, 0x3f, 0xf0, 0x1f, 0xf0, 0x1f, 0xc0, 0xff, 0xff, 0x0b, 0x40, 0xff, 0xff, 0x02, + 0x00, 0xf4, 0x6f, 0x00, + /* '1', offset=100 */ + 0x00, 0xf4, 0x0f, 0x00, 0xd0, 0xff, 0x03, 0x40, 0xff, 0xff, 0x00, 0xf8, 0xbf, 0x3f, 0x00, 0xfe, + 0xd1, 0x0f, 0x80, 0x07, 0xf4, 0x03, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x40, 0x3f, 0x00, 0x00, 0xd0, + 0x0f, 0x00, 0x00, 0xf4, 0x03, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x40, 0x3f, 0x00, 0x00, 0xd0, 0x0f, + 0x00, 0x00, 0xf4, 0x03, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x40, 0x3f, 0x00, 0x00, 0xd0, 0x0f, 0x00, + 0x00, 0xf4, 0x03, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x40, 0x3f, 0x00, 0x00, 0xd0, 0x0f, 0x00, 0x00, + 0xf4, 0x03, 0x80, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0x3f, + /* '2', offset=194 */ + 0x40, 0xfe, 0x2f, 0x00, 0xf8, 0xff, 0xff, 0x02, 0xfd, 0xff, 0xff, 0x0b, 0xfd, 0x01, 0xf4, 0x2f, + 0x1d, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0x40, 0x7f, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x00, 0xe0, 0x0f, + 0x00, 0x00, 0xf4, 0x03, 0x00, 0x00, 0xfd, 0x01, 0x00, 0x40, 0x7f, 0x00, 0x00, 0xc0, 0x1f, 0x00, + 0x00, 0xf0, 0x07, 0x00, 0x00, 0xfc, 0x02, 0x00, 0x00, 0xbf, 0x00, 0x00, 0xc0, 0x2f, 0x00, 0x00, + 0xf0, 0x0b, 0x00, 0x00, 0xfc, 0x02, 0x00, 0x00, 0xfd, 0xff, 0xff, 0xbf, 0xfd, 0xff, 0xff, 0xbf, + 0xfd, 0xff, 0xff, 0xbf, + /* '3', offset=294 */ + 0x40, 0xfe, 0x2f, 0x00, 0xfc, 0xff, 0xff, 0x02, 0xfc, 0xff, 0xff, 0x0f, 0xbc, 0x01, 0xe4, 0x2f, + 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x3f, + 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0xf4, 0x1f, 0x00, 0xfd, 0xff, 0x07, 0x00, 0xfd, 0xbf, 0x00, + 0x00, 0xfd, 0xff, 0x07, 0x00, 0x00, 0xf4, 0x1f, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0xbf, + 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0xbf, + 0x01, 0x00, 0x80, 0x7f, 0x6e, 0x00, 0xf4, 0x3f, 0xfe, 0xff, 0xff, 0x0f, 0xfe, 0xff, 0xff, 0x03, + 0x90, 0xff, 0x6f, 0x00, + /* '4', offset=394 */ + 0x00, 0x00, 0xf8, 0x0b, 0x00, 0x00, 0xf4, 0x2f, 0x00, 0x00, 0xf0, 0xbf, 0x00, 0x00, 0xe0, 0xff, + 0x02, 0x00, 0xc0, 0xf7, 0x0b, 0x00, 0xc0, 0xcf, 0x2f, 0x00, 0x80, 0x0f, 0xbf, 0x00, 0x00, 0x2f, + 0xfc, 0x02, 0x00, 0x3f, 0xf0, 0x0b, 0x00, 0x7d, 0xc0, 0x2f, 0x00, 0xbc, 0x00, 0xbf, 0x00, 0xf8, + 0x00, 0xfc, 0x02, 0xf4, 0x02, 0xf0, 0x0b, 0xf0, 0x03, 0xc0, 0x2f, 0xe0, 0x07, 0x00, 0xbf, 0xc0, + 0x0b, 0x00, 0xfc, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x3f, 0x00, 0x00, 0xfc, 0x02, 0x00, 0x00, 0xf0, 0x0b, 0x00, 0x00, 0xc0, 0x2f, 0x00, 0x00, 0x00, + 0xbf, 0x00, 0x00, 0x00, 0xfc, 0x02, 0x00, 0x00, 0xf0, 0x0b, 0x00, + /* '5', offset=501 */ + 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0x01, 0x00, 0x00, + 0xf8, 0x01, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, + 0xf8, 0xfa, 0x2f, 0x00, 0xf8, 0xff, 0xff, 0x01, 0xf8, 0xff, 0xff, 0x0b, 0x78, 0x00, 0xf9, 0x1f, + 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0x40, 0x7f, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0xbe, + 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x40, 0x7f, + 0x01, 0x00, 0xc0, 0x3f, 0x6e, 0x00, 0xf8, 0x1f, 0xfe, 0xff, 0xff, 0x0b, 0xfe, 0xff, 0xff, 0x01, + 0xa4, 0xff, 0x1b, 0x00, + /* '6', offset=601 */ + 0x00, 0xd0, 0xff, 0x02, 0x00, 0xfe, 0xff, 0x1f, 0x80, 0xff, 0xff, 0x1f, 0xe0, 0x7f, 0x00, 0x19, + 0xf0, 0x0b, 0x00, 0x00, 0xf8, 0x03, 0x00, 0x00, 0xfc, 0x01, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, + 0xbd, 0xe0, 0xbf, 0x00, 0x7e, 0xfc, 0xff, 0x07, 0x7e, 0xff, 0xff, 0x1f, 0xfe, 0x1f, 0xd0, 0x3f, + 0xff, 0x03, 0x00, 0xbf, 0xff, 0x01, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfd, 0xfe, 0x00, 0x00, 0xfc, + 0xfe, 0x00, 0x00, 0xfc, 0xfd, 0x00, 0x00, 0xfc, 0xfc, 0x00, 0x00, 0xfd, 0xfc, 0x01, 0x00, 0xfe, + 0xf8, 0x03, 0x00, 0xbf, 0xf0, 0x1f, 0xd0, 0x3f, 0xd0, 0xff, 0xff, 0x1f, 0x40, 0xff, 0xff, 0x07, + 0x00, 0xf4, 0xbf, 0x00, + /* '7', offset=701 */ + 0xfe, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xbf, 0x00, 0x00, 0x00, 0x3f, + 0x00, 0x00, 0x40, 0x3f, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0xe0, 0x0b, + 0x00, 0x00, 0xf0, 0x07, 0x00, 0x00, 0xf4, 0x03, 0x00, 0x00, 0xfc, 0x02, 0x00, 0x00, 0xfc, 0x00, + 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x40, 0x3f, 0x00, 0x00, 0x80, 0x2f, 0x00, + 0x00, 0xc0, 0x1f, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xf0, 0x07, 0x00, 0x00, 0xf4, 0x03, 0x00, + 0x00, 0xf8, 0x02, 0x00, 0x00, 0xfc, 0x01, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, + 0x40, 0x3f, 0x00, 0x00, + /* '8', offset=801 */ + 0x00, 0xf9, 0xbf, 0x00, 0xc0, 0xff, 0xff, 0x07, 0xf0, 0xff, 0xff, 0x2f, 0xf8, 0x1b, 0xd0, 0x3f, + 0xfc, 0x02, 0x00, 0xbf, 0xfc, 0x00, 0x00, 0xbf, 0xfc, 0x00, 0x00, 0xbe, 0xfc, 0x00, 0x00, 0xbf, + 0xf8, 0x02, 0x00, 0x3f, 0xf0, 0x1b, 0xd0, 0x1f, 0x80, 0xff, 0xff, 0x07, 0x00, 0xfd, 0xff, 0x00, + 0xd0, 0xff, 0xff, 0x0b, 0xf4, 0x0b, 0xd0, 0x3f, 0xfc, 0x02, 0x00, 0xbf, 0xfd, 0x00, 0x00, 0xfd, + 0xbe, 0x00, 0x00, 0xfc, 0xbf, 0x00, 0x00, 0xfc, 0xbf, 0x00, 0x00, 0xfc, 0xfe, 0x00, 0x00, 0xfd, + 0xfd, 0x02, 0x00, 0xff, 0xfc, 0x0b, 0xd0, 0x7f, 0xf4, 0xff, 0xff, 0x2f, 0xd0, 0xff, 0xff, 0x0b, + 0x00, 0xf9, 0xbf, 0x00, + /* '9', offset=901 */ + 0x00, 0xf9, 0x2f, 0x00, 0xc0, 0xff, 0xff, 0x02, 0xf0, 0xff, 0xff, 0x0b, 0xfc, 0x0b, 0xe4, 0x1f, + 0xfd, 0x01, 0x80, 0x3f, 0xfe, 0x00, 0x00, 0x3f, 0xbf, 0x00, 0x00, 0xbe, 0x7f, 0x00, 0x00, 0xbe, + 0x7f, 0x00, 0x00, 0xfe, 0xbf, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xff, 0xfd, 0x01, 0x80, 0xff, + 0xfc, 0x0b, 0xe4, 0xff, 0xf0, 0xff, 0xff, 0xfd, 0xd0, 0xff, 0x7f, 0xfc, 0x00, 0xfd, 0x0b, 0xfc, + 0x00, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, 0xbe, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x80, 0x3f, + 0x00, 0x00, 0xd0, 0x2f, 0xb0, 0x00, 0xf9, 0x0f, 0xf0, 0xff, 0xff, 0x03, 0xf0, 0xff, 0xff, 0x00, + 0x40, 0xff, 0x1b, 0x00, + /* '.', offset=1001 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf3, 0xff, 0xff, 0xff, 0xff, 0x8f, 0x0f, - /* 'V', offset=1359 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x2f, 0x00, 0x00, 0x80, 0xff, 0xfe, 0x03, 0x00, 0x00, 0xfc, - 0xeb, 0x3f, 0x00, 0x00, 0xc0, 0x7f, 0xfd, 0x03, 0x00, 0x00, 0xfc, 0xc3, 0x7f, 0x00, 0x00, 0xd0, - 0x3f, 0xfc, 0x0b, 0x00, 0x00, 0xfe, 0x82, 0xbf, 0x00, 0x00, 0xe0, 0x1f, 0xf4, 0x0f, 0x00, 0x00, - 0xff, 0x01, 0xff, 0x00, 0x00, 0xf0, 0x0f, 0xf0, 0x1f, 0x00, 0x40, 0xff, 0x00, 0xfe, 0x02, 0x00, - 0xf8, 0x0b, 0xd0, 0x3f, 0x00, 0xc0, 0x7f, 0x00, 0xfc, 0x03, 0x00, 0xfc, 0x03, 0xc0, 0x3f, 0x00, - 0xd0, 0x3f, 0x00, 0xf8, 0x07, 0x00, 0xfd, 0x02, 0x40, 0xbf, 0x00, 0xe0, 0x1f, 0x00, 0xf0, 0x0f, - 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0xf0, 0x0f, 0x00, 0xe0, 0x1f, 0x40, 0xbf, 0x00, 0x00, 0xfd, - 0x02, 0xf8, 0x07, 0x00, 0xc0, 0x3f, 0xc0, 0x3f, 0x00, 0x00, 0xfc, 0x03, 0xfc, 0x02, 0x00, 0x80, - 0xbf, 0xe0, 0x1f, 0x00, 0x00, 0xf4, 0x0f, 0xff, 0x00, 0x00, 0x00, 0xff, 0xf0, 0x0f, 0x00, 0x00, - 0xe0, 0x5f, 0xbf, 0x00, 0x00, 0x00, 0xfd, 0xfa, 0x03, 0x00, 0x00, 0xc0, 0xff, 0x3f, 0x00, 0x00, - 0x00, 0xfc, 0xff, 0x02, 0x00, 0x00, 0x40, 0xff, 0x1f, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, - 0x00, 0x00, 0xff, 0x0b, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, - /* 'A', offset=1552 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xbf, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x0f, 0x00, - 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x40, 0xff, 0x2f, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, - 0x00, 0x00, 0xc0, 0xff, 0x3f, 0x00, 0x00, 0x00, 0xfd, 0xfa, 0x07, 0x00, 0x00, 0xe0, 0x0f, 0xff, - 0x00, 0x00, 0x00, 0xff, 0xf0, 0x0f, 0x00, 0x00, 0xf0, 0x0b, 0xfe, 0x01, 0x00, 0x80, 0x7f, 0xd0, - 0x2f, 0x00, 0x00, 0xfc, 0x03, 0xfc, 0x03, 0x00, 0xc0, 0x2f, 0xc0, 0x3f, 0x00, 0x00, 0xfd, 0x01, - 0xf8, 0x07, 0x00, 0xe0, 0x0f, 0x40, 0xff, 0x00, 0x00, 0xff, 0x00, 0xf0, 0x0f, 0x00, 0xf0, 0x0b, - 0x00, 0xff, 0x01, 0x40, 0x7f, 0x00, 0xe0, 0x2f, 0x00, 0xf8, 0x03, 0x00, 0xfd, 0x03, 0xc0, 0x3f, - 0x00, 0xc0, 0x3f, 0x00, 0xfc, 0x02, 0x00, 0xfc, 0x07, 0xd0, 0xff, 0xff, 0xff, 0xbf, 0x00, 0xfe, - 0xff, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x00, 0xbf, 0x00, 0x00, 0xe0, 0x1f, 0xf4, - 0x07, 0x00, 0x00, 0xfd, 0x82, 0x7f, 0x00, 0x00, 0xd0, 0x2f, 0xfc, 0x03, 0x00, 0x00, 0xfc, 0xc3, - 0x3f, 0x00, 0x00, 0xc0, 0x3f, 0xfd, 0x02, 0x00, 0x00, 0xfc, 0xe7, 0x2f, 0x00, 0x00, 0x80, 0xbf, - 0xfe, 0x01, 0x00, 0x00, 0xf4, 0xff, 0x0f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xef, 0xff, 0xfe, 0xef, + 0xff, 0xfe, 0xef, 0xff, 0xfe, 0x0f, + /* 'V', offset=1039 */ + 0xbf, 0x00, 0x00, 0xc0, 0xef, 0x0f, 0x00, 0x00, 0xfd, 0xfd, 0x00, 0x00, 0xe0, 0xcf, 0x1f, 0x00, + 0x00, 0xbf, 0xf8, 0x02, 0x00, 0xf0, 0x43, 0x3f, 0x00, 0x40, 0x3f, 0xf0, 0x03, 0x00, 0xf8, 0x02, + 0x7f, 0x00, 0xc0, 0x1f, 0xe0, 0x0b, 0x00, 0xfc, 0x00, 0xfd, 0x00, 0xd0, 0x0f, 0xc0, 0x0f, 0x00, + 0x7e, 0x00, 0xf8, 0x01, 0xf0, 0x03, 0x40, 0x2f, 0x00, 0x3f, 0x00, 0xf0, 0x03, 0xf4, 0x02, 0x00, + 0x3f, 0xc0, 0x1f, 0x00, 0xe0, 0x07, 0xfc, 0x00, 0x00, 0xbd, 0xd0, 0x0b, 0x00, 0xc0, 0x0f, 0x7e, + 0x00, 0x00, 0xf8, 0xf1, 0x03, 0x00, 0x40, 0x2f, 0x3f, 0x00, 0x00, 0xf0, 0xf7, 0x02, 0x00, 0x00, + 0xbf, 0x1f, 0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0xfc, 0x0b, 0x00, 0x00, 0xc0, 0x7f, 0x00, 0x00, + /* 'A', offset=1152 */ + 0x00, 0xc0, 0x7f, 0x00, 0x00, 0x00, 0xf4, 0x2f, 0x00, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0xc0, + 0xff, 0x07, 0x00, 0x00, 0xf0, 0xf7, 0x02, 0x00, 0x00, 0xbd, 0xfc, 0x00, 0x00, 0xc0, 0x1f, 0x3f, + 0x00, 0x00, 0xf0, 0x83, 0x2f, 0x00, 0x00, 0xfd, 0xd0, 0x0f, 0x00, 0x80, 0x1f, 0xf0, 0x03, 0x00, + 0xf0, 0x03, 0xf8, 0x01, 0x00, 0xfd, 0x00, 0xfd, 0x00, 0x80, 0x2f, 0x00, 0x3f, 0x00, 0xf0, 0x07, + 0xc0, 0x1f, 0x00, 0xfc, 0x00, 0xe0, 0x0b, 0x80, 0x3f, 0x00, 0xf4, 0x03, 0xf0, 0xff, 0xff, 0xff, + 0x01, 0xfc, 0xff, 0xff, 0xbf, 0x40, 0xff, 0xff, 0xff, 0x3f, 0xe0, 0x0b, 0x00, 0xd0, 0x0f, 0xfc, + 0x01, 0x00, 0xf0, 0x47, 0x3f, 0x00, 0x00, 0xf8, 0xe3, 0x0f, 0x00, 0x00, 0xfd, 0xfc, 0x02, 0x00, + 0x00, 0x7f, 0x3f, 0x00, 0x00, 0xc0, 0x2f, }; const uint8_t font_meter_large_widths[96] = { - 9u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 5u, 0u, - 16u, 9u, 16u, 15u, 17u, 14u, 16u, 16u, - 16u, 15u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 22u, 0u, 0u, 0u, 0u, 0u, 0u, + 20u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 6u, 0u, + 16u, 15u, 16u, 16u, 17u, 16u, 16u, 16u, + 16u, 16u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 19u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 22u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 18u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, @@ -151,12 +124,12 @@ const uint8_t font_meter_large_widths[96] = { const uint8_t font_meter_large_sizes[96] = { 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 44u, 0u, - 140u, 79u, 140u, 132u, 149u, 123u, 140u, 140u, - 140u, 132u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 193u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 38u, 0u, + 100u, 94u, 100u, 100u, 107u, 100u, 100u, 100u, + 100u, 100u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 119u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 193u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 113u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, @@ -166,12 +139,12 @@ const uint8_t font_meter_large_sizes[96] = { const uint16_t font_meter_large_offsets[96] = { 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 1315u, 0u, - 0u, 140u, 219u, 359u, 491u, 640u, 763u, 903u, - 1043u, 1183u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 1552u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 1001u, 0u, + 0u, 100u, 194u, 294u, 394u, 501u, 601u, 701u, + 801u, 901u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 1152u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 1359u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 1039u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, diff --git a/opendps/font-meter_large.h b/opendps/font-meter_large.h index 5e748fcc..3f6fbdcb 100644 --- a/opendps/font-meter_large.h +++ b/opendps/font-meter_large.h @@ -1,21 +1,21 @@ -/** Font generated from gfx/Ubuntu-C.ttf 48pt */ +/** Font generated from gfx/nf.ttf 34pt */ #ifndef __FONT_METER_LARGE_H__ #define __FONT_METER_LARGE_H__ #include -#define FONT_METER_LARGE_MAX_GLYPH_HEIGHT (35) -#define FONT_METER_LARGE_MAX_GLYPH_WIDTH (22) +#define FONT_METER_LARGE_MAX_GLYPH_HEIGHT (25) +#define FONT_METER_LARGE_MAX_GLYPH_WIDTH (19) #define FONT_METER_LARGE_MAX_DIGIT_WIDTH (17) -#define FONT_METER_LARGE_DOT_WIDTH (5) -#define FONT_METER_LARGE_SPACING (4) -#define FONT_METER_LARGE_SPACE_WIDTH (9) +#define FONT_METER_LARGE_DOT_WIDTH (6) +#define FONT_METER_LARGE_SPACING (3) +#define FONT_METER_LARGE_SPACE_WIDTH (20) extern const uint32_t font_meter_large_height; extern const uint8_t font_meter_large_widths[96]; extern const uint8_t font_meter_large_sizes[96]; extern const uint16_t font_meter_large_offsets[96]; -extern const uint8_t font_meter_large_pixdata[1745]; +extern const uint8_t font_meter_large_pixdata[1271]; #endif // __FONT_METER_LARGE_H__ \ No newline at end of file diff --git a/opendps/font-meter_medium.c b/opendps/font-meter_medium.c index 73cea4c9..b6b72f62 100644 --- a/opendps/font-meter_medium.c +++ b/opendps/font-meter_medium.c @@ -1,69 +1,82 @@ -/** Font generated from gfx/Ubuntu-C.ttf 24pt */ +/** Font generated from gfx/nf.ttf 24pt */ #include "font-meter_medium.h" -const uint32_t font_meter_medium_height = 17; -const uint8_t font_meter_medium_pixdata[444] = { +const uint32_t font_meter_medium_height = 18; +const uint8_t font_meter_medium_pixdata[665] = { /* '0', offset=0 */ - 0xe0, 0x0b, 0xf8, 0x3f, 0x7c, 0x7c, 0x3d, 0xb4, 0x2e, 0xf4, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, - 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x1e, 0xf0, 0x2e, 0xf4, 0x3d, 0xb4, 0x7c, 0x7c, 0xf8, 0x3f, - 0xe0, 0x0b, - /* '1', offset=34 */ - 0xd0, 0xc2, 0xcb, 0xef, 0xbb, 0xd6, 0x42, 0x0b, 0x2d, 0xb4, 0xd0, 0x42, 0x0b, 0x2d, 0xb4, 0xd0, - 0x42, 0x0b, 0x2d, 0xb4, 0xd0, 0x02, - /* '2', offset=56 */ - 0xf8, 0x0b, 0xfe, 0x3f, 0x09, 0x7d, 0x00, 0x7c, 0x00, 0x78, 0x00, 0x7c, 0x00, 0x3c, 0x00, 0x1e, - 0x40, 0x0f, 0xc0, 0x03, 0xe0, 0x02, 0xf4, 0x00, 0x78, 0x00, 0x3c, 0x00, 0x2d, 0x00, 0xfe, 0xff, - 0xfe, 0xff, - /* '3', offset=90 */ - 0xf8, 0x07, 0xfe, 0x1f, 0x08, 0x3e, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x2f, 0xf0, 0x0b, - 0xf0, 0x1f, 0x00, 0x3e, 0x00, 0x78, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb8, 0x05, 0x7d, 0xff, 0x2f, - 0xf9, 0x07, - /* '4', offset=124 */ - 0x00, 0x3d, 0x00, 0xfc, 0x00, 0xf4, 0x03, 0xf0, 0x0f, 0xd0, 0x3d, 0xc0, 0xf3, 0x00, 0xc7, 0x03, - 0x0e, 0x0f, 0x2c, 0x3c, 0x74, 0xf0, 0xe0, 0xc0, 0xc3, 0xff, 0xbf, 0xff, 0xff, 0x02, 0xf0, 0x00, - 0xc0, 0x03, 0x00, 0x0f, 0x00, 0x3c, 0x00, - /* '5', offset=163 */ - 0xf4, 0x7f, 0xf4, 0x7f, 0xb4, 0x00, 0x74, 0x00, 0x74, 0x00, 0x74, 0x00, 0xf8, 0x06, 0xf8, 0x1f, - 0x40, 0x3f, 0x00, 0x7c, 0x00, 0xb8, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0x7c, 0x04, 0x3e, 0xfe, 0x1f, - 0xfd, 0x06, - /* '6', offset=197 */ - 0x00, 0x39, 0x80, 0x7f, 0xe0, 0x07, 0xf0, 0x00, 0x78, 0x00, 0x3c, 0x00, 0xfc, 0x1f, 0xfd, 0x7f, - 0x2d, 0xf8, 0x2d, 0xf0, 0x2d, 0xf0, 0x2d, 0xf0, 0x3d, 0xf0, 0x3c, 0xf0, 0x7c, 0xb8, 0xf4, 0x7f, - 0xd0, 0x1f, - /* '7', offset=231 */ - 0xff, 0xff, 0xff, 0xff, 0x00, 0xb4, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x1e, 0x00, 0x0f, 0x40, 0x0b, - 0x80, 0x07, 0xc0, 0x03, 0xc0, 0x03, 0xd0, 0x02, 0xe0, 0x01, 0xf0, 0x01, 0xf0, 0x00, 0xf0, 0x00, - 0xf0, 0x00, - /* '8', offset=265 */ - 0xe0, 0x1f, 0xf8, 0x7f, 0x3d, 0xb8, 0x2d, 0xf0, 0x2d, 0xf0, 0x2d, 0xb4, 0x3c, 0x38, 0xf0, 0x1e, - 0xf0, 0x0f, 0x78, 0x3e, 0x2d, 0xb8, 0x1e, 0xf0, 0x0f, 0xf0, 0x1f, 0xf0, 0x3e, 0xf8, 0xfc, 0x3f, - 0xe0, 0x0b, - /* '9', offset=299 */ - 0xe0, 0x0b, 0xf8, 0x3f, 0x7c, 0x7c, 0x2d, 0xb4, 0x2e, 0xf0, 0x1e, 0xf0, 0x2e, 0xf0, 0x2d, 0xf0, - 0x7c, 0xf0, 0xf8, 0xff, 0xe0, 0xff, 0x00, 0xb4, 0x00, 0x3c, 0x00, 0x3d, 0x90, 0x0f, 0xfc, 0x07, - 0xb8, 0x00, - /* '.', offset=333 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xfa, 0x2c, - /* 'V', offset=346 */ - 0x3d, 0x00, 0x3c, 0x0f, 0x00, 0xcf, 0x03, 0xc0, 0xf3, 0x01, 0xb4, 0xb8, 0x00, 0x2e, 0x3d, 0xc0, - 0x07, 0x0f, 0xf0, 0xc0, 0x03, 0x3c, 0xe0, 0x41, 0x0b, 0xb4, 0xe0, 0x01, 0x3c, 0x3c, 0x00, 0x0f, - 0x0b, 0x80, 0xd7, 0x01, 0xc0, 0x3e, 0x00, 0xf0, 0x0f, 0x00, 0xf8, 0x02, 0x00, 0x7d, 0x00, - /* 'A', offset=393 */ - 0x00, 0x7d, 0x00, 0x00, 0xbe, 0x00, 0x00, 0xff, 0x00, 0x00, 0xeb, 0x00, 0x40, 0xd7, 0x01, 0x80, - 0xc3, 0x02, 0xc0, 0xc3, 0x03, 0xd0, 0x82, 0x07, 0xe0, 0x41, 0x0b, 0xf0, 0x00, 0x0f, 0xf0, 0x00, - 0x0f, 0xf4, 0xff, 0x1f, 0xf8, 0xff, 0x2f, 0x7c, 0x00, 0x3d, 0x3c, 0x00, 0x3c, 0x3c, 0x00, 0x7c, - 0x2d, 0x00, 0x78, + 0x00, 0xfe, 0x01, 0xd0, 0xff, 0x0f, 0xf0, 0x42, 0x2f, 0xf8, 0x00, 0x3e, 0x7c, 0x00, 0x7f, 0x3c, + 0x80, 0xbf, 0x3d, 0xc0, 0xbb, 0x3d, 0xf0, 0xf8, 0x3d, 0x78, 0xf8, 0x3d, 0x3c, 0xf4, 0x3d, 0x0f, + 0xf8, 0xbd, 0x07, 0xb8, 0xfc, 0x03, 0xbc, 0xfc, 0x00, 0x7c, 0xf8, 0x00, 0x3d, 0xf0, 0x42, 0x2f, + 0xd0, 0xff, 0x0f, 0x00, 0xfe, 0x01, + /* '1', offset=54 */ + 0x40, 0x3f, 0x00, 0xfd, 0x0f, 0xd0, 0xef, 0x03, 0xb8, 0xf0, 0x00, 0x01, 0x3c, 0x00, 0x00, 0x0f, + 0x00, 0xc0, 0x03, 0x00, 0xf0, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x0f, 0x00, 0xc0, 0x03, 0x00, 0xf0, + 0x00, 0x00, 0x3c, 0x00, 0x00, 0x0f, 0x00, 0xc0, 0x03, 0x00, 0xf0, 0x00, 0xfc, 0xff, 0x3f, 0xff, + 0xff, 0x0f, + /* '2', offset=104 */ + 0xe4, 0x6f, 0xc0, 0xff, 0xff, 0xf0, 0x01, 0xbe, 0x04, 0x00, 0x3e, 0x00, 0x00, 0x1f, 0x00, 0xc0, + 0x03, 0x00, 0xf4, 0x00, 0x00, 0x2f, 0x00, 0xd0, 0x03, 0x00, 0x7d, 0x00, 0xc0, 0x07, 0x00, 0xbc, + 0x00, 0xc0, 0x0b, 0x00, 0xbc, 0x00, 0xc0, 0x0b, 0x00, 0xf8, 0x00, 0x00, 0xff, 0xff, 0xdf, 0xff, + 0xff, 0x07, + /* '3', offset=154 */ + 0xf9, 0x7f, 0xc0, 0xff, 0xff, 0xa0, 0x01, 0xfd, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x0f, 0x00, 0xd0, + 0x03, 0x00, 0xbd, 0x40, 0xff, 0x07, 0xd0, 0xff, 0x01, 0x00, 0xf8, 0x02, 0x00, 0xf4, 0x00, 0x00, + 0x7c, 0x00, 0x00, 0x2e, 0x00, 0xc0, 0x0b, 0x00, 0xf4, 0x1d, 0x80, 0x3f, 0xff, 0xff, 0x43, 0xfe, + 0x1f, 0x00, + /* '4', offset=204 */ + 0x00, 0xc0, 0x0f, 0x00, 0xe0, 0x0f, 0x00, 0xf4, 0x0f, 0x00, 0x7c, 0x0f, 0x00, 0x5d, 0x0f, 0x00, + 0x4f, 0x0f, 0x80, 0x43, 0x0f, 0xd0, 0x42, 0x0f, 0xf0, 0x40, 0x0f, 0xb4, 0x40, 0x0f, 0x3c, 0x40, + 0x0f, 0x1e, 0x40, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x40, 0x0f, 0x00, 0x40, 0x0f, + 0x00, 0x40, 0x0f, 0x00, 0x40, 0x0f, + /* '5', offset=258 */ + 0xfe, 0xff, 0x87, 0xff, 0xff, 0xe1, 0x02, 0x00, 0xb8, 0x00, 0x00, 0x2e, 0x00, 0x80, 0x0b, 0x00, + 0xe0, 0xff, 0x06, 0xf8, 0xff, 0x0b, 0x05, 0xe0, 0x0b, 0x00, 0xe0, 0x03, 0x00, 0xf0, 0x01, 0x00, + 0x7c, 0x00, 0x00, 0x1f, 0x00, 0xc0, 0x07, 0x00, 0xf8, 0x1c, 0x80, 0x2f, 0xff, 0xff, 0x42, 0xfe, + 0x1b, 0x00, + /* '6', offset=308 */ + 0x00, 0xfd, 0x0b, 0xc0, 0xff, 0x2f, 0xf0, 0x07, 0x14, 0xf4, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x3c, + 0x00, 0x00, 0x3d, 0xfd, 0x02, 0x7d, 0xff, 0x1f, 0xfd, 0x02, 0x3e, 0xfd, 0x00, 0xbc, 0x7d, 0x00, + 0xf8, 0x3d, 0x00, 0xf4, 0x3c, 0x00, 0xf4, 0x7c, 0x00, 0xf8, 0xf8, 0x00, 0xbc, 0xf0, 0x02, 0x3f, + 0xd0, 0xff, 0x1f, 0x40, 0xfe, 0x02, + /* '7', offset=362 */ + 0xff, 0xff, 0xef, 0xff, 0xff, 0x07, 0x00, 0xf0, 0x00, 0x00, 0x2e, 0x00, 0xc0, 0x07, 0x00, 0xf4, + 0x00, 0x00, 0x2e, 0x00, 0xc0, 0x07, 0x00, 0xf4, 0x00, 0x00, 0x2f, 0x00, 0xc0, 0x03, 0x00, 0xf8, + 0x00, 0x00, 0x1f, 0x00, 0xd0, 0x03, 0x00, 0xb8, 0x00, 0x00, 0x1f, 0x00, 0xe0, 0x03, 0x00, 0xbc, + 0x00, 0x00, + /* '8', offset=412 */ + 0x40, 0xff, 0x02, 0xf0, 0xff, 0x1f, 0xf8, 0x01, 0x3f, 0xbc, 0x00, 0x7c, 0x7c, 0x00, 0x7c, 0xbc, + 0x00, 0x3c, 0xf0, 0x01, 0x2f, 0x80, 0xff, 0x07, 0xd0, 0xff, 0x0b, 0xf4, 0x01, 0x3f, 0x7c, 0x00, + 0x7c, 0x3d, 0x00, 0xf8, 0x3d, 0x00, 0xf8, 0x3d, 0x00, 0xf8, 0x7c, 0x00, 0xbc, 0xfc, 0x01, 0x3f, + 0xf0, 0xff, 0x1f, 0x80, 0xff, 0x02, + /* '9', offset=466 */ + 0x80, 0xff, 0x01, 0xf0, 0xff, 0x0f, 0xf8, 0x41, 0x2f, 0x7c, 0x00, 0x3d, 0x3d, 0x00, 0x7c, 0x3d, + 0x00, 0xbc, 0x3d, 0x00, 0xbc, 0x3d, 0x00, 0xfc, 0x7c, 0x00, 0xfd, 0xf8, 0x41, 0xff, 0xf0, 0xff, + 0xb7, 0x80, 0xbf, 0xb8, 0x00, 0x00, 0x78, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3e, 0x20, 0x80, 0x0f, + 0xf0, 0xff, 0x07, 0xe0, 0xbf, 0x00, + /* '.', offset=520 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf4, 0xdb, 0x6f, 0xbf, 0xfd, 0xf6, 0x0b, + /* 'V', offset=543 */ + 0x1f, 0x00, 0xf0, 0xbe, 0x00, 0xc0, 0xe7, 0x03, 0x40, 0x4f, 0x0f, 0x00, 0x3e, 0x7c, 0x00, 0x7c, + 0xf0, 0x02, 0xf0, 0x40, 0x0f, 0xd0, 0x03, 0x3c, 0x80, 0x0b, 0xf0, 0x01, 0x1f, 0x80, 0x0b, 0x3c, + 0x00, 0x3d, 0xf4, 0x00, 0xf0, 0xe0, 0x02, 0xc0, 0xc7, 0x03, 0x00, 0x2d, 0x0f, 0x00, 0xf0, 0x2d, + 0x00, 0xc0, 0x7f, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xf4, 0x03, 0x00, + /* 'A', offset=602 */ + 0x00, 0xf4, 0x03, 0x00, 0x80, 0x3f, 0x00, 0x00, 0xfc, 0x07, 0x00, 0xc0, 0xb7, 0x00, 0x00, 0x2e, + 0x0f, 0x00, 0xf0, 0xf1, 0x01, 0x00, 0x0f, 0x2e, 0x00, 0xb4, 0xd0, 0x03, 0x80, 0x07, 0x3c, 0x00, + 0x3c, 0x80, 0x07, 0xd0, 0x03, 0xf4, 0x00, 0xfe, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x01, 0x0f, 0x00, + 0x2e, 0xf8, 0x00, 0xd0, 0xc3, 0x0b, 0x00, 0x7c, 0x7c, 0x00, 0xc0, 0xdb, 0x03, 0x00, 0xf8, }; const uint8_t font_meter_medium_widths[96] = { - 5u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 3u, 0u, - 8u, 5u, 8u, 8u, 9u, 8u, 8u, 8u, - 8u, 8u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 12u, 0u, 0u, 0u, 0u, 0u, 0u, + 14u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 5u, 0u, + 12u, 11u, 11u, 11u, 12u, 11u, 12u, 11u, + 12u, 12u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 14u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 11u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 13u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, @@ -73,12 +86,12 @@ const uint8_t font_meter_medium_widths[96] = { const uint8_t font_meter_medium_sizes[96] = { 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 13u, 0u, - 34u, 22u, 34u, 34u, 39u, 34u, 34u, 34u, - 34u, 34u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 51u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 23u, 0u, + 54u, 50u, 50u, 50u, 54u, 50u, 54u, 50u, + 54u, 54u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 63u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 47u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 59u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, @@ -88,12 +101,12 @@ const uint8_t font_meter_medium_sizes[96] = { const uint16_t font_meter_medium_offsets[96] = { 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 333u, 0u, - 0u, 34u, 56u, 90u, 124u, 163u, 197u, 231u, - 265u, 299u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 393u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 520u, 0u, + 0u, 54u, 104u, 154u, 204u, 258u, 308u, 362u, + 412u, 466u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 602u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 346u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 543u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, diff --git a/opendps/font-meter_medium.h b/opendps/font-meter_medium.h index 6597f3a4..5955c86b 100644 --- a/opendps/font-meter_medium.h +++ b/opendps/font-meter_medium.h @@ -1,21 +1,21 @@ -/** Font generated from gfx/Ubuntu-C.ttf 24pt */ +/** Font generated from gfx/nf.ttf 24pt */ #ifndef __FONT_METER_MEDIUM_H__ #define __FONT_METER_MEDIUM_H__ #include -#define FONT_METER_MEDIUM_MAX_GLYPH_HEIGHT (17) -#define FONT_METER_MEDIUM_MAX_GLYPH_WIDTH (12) -#define FONT_METER_MEDIUM_MAX_DIGIT_WIDTH (9) -#define FONT_METER_MEDIUM_DOT_WIDTH (3) +#define FONT_METER_MEDIUM_MAX_GLYPH_HEIGHT (18) +#define FONT_METER_MEDIUM_MAX_GLYPH_WIDTH (14) +#define FONT_METER_MEDIUM_MAX_DIGIT_WIDTH (12) +#define FONT_METER_MEDIUM_DOT_WIDTH (5) #define FONT_METER_MEDIUM_SPACING (2) -#define FONT_METER_MEDIUM_SPACE_WIDTH (5) +#define FONT_METER_MEDIUM_SPACE_WIDTH (14) extern const uint32_t font_meter_medium_height; extern const uint8_t font_meter_medium_widths[96]; extern const uint8_t font_meter_medium_sizes[96]; extern const uint16_t font_meter_medium_offsets[96]; -extern const uint8_t font_meter_medium_pixdata[444]; +extern const uint8_t font_meter_medium_pixdata[665]; #endif // __FONT_METER_MEDIUM_H__ \ No newline at end of file diff --git a/opendps/font-meter_small.c b/opendps/font-meter_small.c index 8d62f2bb..f4fb1dc9 100644 --- a/opendps/font-meter_small.c +++ b/opendps/font-meter_small.c @@ -1,53 +1,54 @@ -/** Font generated from gfx/Ubuntu-C.ttf 18pt */ +/** Font generated from gfx/nf.ttf 16pt */ #include "font-meter_small.h" const uint32_t font_meter_small_height = 12; -const uint8_t font_meter_small_pixdata[234] = { +const uint8_t font_meter_small_pixdata[291] = { /* '0', offset=0 */ - 0xf8, 0xd1, 0x34, 0x0f, 0xb7, 0xb0, 0x0b, 0xbb, 0xf0, 0x0b, 0xbf, 0xb0, 0x0b, 0xfb, 0x70, 0x4d, - 0x83, 0x1f, - /* '1', offset=18 */ - 0xd0, 0xf0, 0xfc, 0xe5, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, - /* '2', offset=30 */ - 0xfd, 0x21, 0x38, 0x40, 0x07, 0x74, 0x80, 0x03, 0x2d, 0xf0, 0x80, 0x07, 0x2c, 0xe0, 0x00, 0x0f, - 0xf0, 0xbf, - /* '3', offset=48 */ - 0xbd, 0x10, 0x3c, 0x40, 0x03, 0x34, 0xc0, 0xc2, 0x0f, 0xc0, 0x03, 0x70, 0x00, 0x07, 0x70, 0x81, - 0xe3, 0x0f, - /* '4', offset=66 */ - 0xc0, 0x03, 0x3d, 0xf0, 0x43, 0x37, 0x5c, 0xd3, 0x34, 0x4a, 0x33, 0x34, 0xff, 0x0f, 0x34, 0x40, - 0x03, 0x34, - /* '5', offset=84 */ - 0xfc, 0xc7, 0x01, 0x1c, 0xc0, 0x01, 0x1c, 0xc0, 0x0b, 0xd0, 0x03, 0x74, 0x00, 0x07, 0x70, 0xc0, - 0xe3, 0x0b, - /* '6', offset=102 */ - 0x80, 0x03, 0x0b, 0x2c, 0xd0, 0x00, 0x0e, 0xe0, 0x2f, 0x0f, 0xb7, 0xf0, 0x0b, 0xee, 0xf0, 0x1d, - 0x47, 0x2f, - /* '7', offset=120 */ - 0xff, 0x0f, 0x70, 0x80, 0x03, 0x2c, 0xd0, 0x00, 0x0e, 0xb0, 0x00, 0x07, 0x34, 0x80, 0x03, 0x3c, - 0xc0, 0x02, - /* '8', offset=138 */ - 0xf8, 0xe2, 0x70, 0x0b, 0xbb, 0xb0, 0x4d, 0x83, 0x1f, 0xec, 0xb2, 0x74, 0x07, 0x7f, 0xe0, 0x0e, - 0x87, 0x1f, - /* '9', offset=156 */ - 0xf8, 0xe1, 0x34, 0x0b, 0xbb, 0xb0, 0x0b, 0xef, 0xf0, 0xf8, 0x0b, 0xb0, 0x40, 0x07, 0x3c, 0xf0, - 0xd0, 0x02, - /* '.', offset=174 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0xee, - /* 'V', offset=180 */ - 0x0e, 0xc0, 0x75, 0x40, 0xc7, 0x02, 0x0e, 0x0f, 0x3c, 0x38, 0xb0, 0xd0, 0xc0, 0x01, 0x8b, 0x03, - 0x3c, 0x0b, 0xd0, 0x1c, 0x00, 0x3b, 0x00, 0xfc, 0x00, 0xe0, 0x02, - /* 'A', offset=207 */ - 0x80, 0x0b, 0x00, 0x3f, 0x00, 0xec, 0x01, 0x38, 0x0b, 0xb0, 0x38, 0xc0, 0xd1, 0x40, 0x03, 0x07, - 0x0e, 0x2c, 0xfc, 0xff, 0x70, 0x40, 0xd3, 0x00, 0x9c, 0x03, 0xb0, + 0xe0, 0x0b, 0x2c, 0x2c, 0x0d, 0x3c, 0x0e, 0x7d, 0x0b, 0xb7, 0x8b, 0xb2, 0xcb, 0xb0, 0x7b, 0xb0, + 0x3e, 0x70, 0x1d, 0x34, 0x2c, 0x2c, 0xe0, 0x0b, + /* '1', offset=24 */ + 0xf4, 0xc0, 0x3f, 0x20, 0x0d, 0x40, 0x03, 0xd0, 0x00, 0x34, 0x00, 0x0d, 0x40, 0x03, 0xd0, 0x00, + 0x34, 0x00, 0x0d, 0xfc, 0xbf, + /* '2', offset=45 */ + 0xf9, 0x87, 0x41, 0x0b, 0x80, 0x03, 0xd0, 0x00, 0x38, 0x00, 0x0b, 0xf0, 0x00, 0x0f, 0xe0, 0x00, + 0x1e, 0xd0, 0x01, 0xfc, 0xff, + /* '3', offset=66 */ + 0xfd, 0x07, 0x05, 0x2c, 0x00, 0x38, 0x00, 0x34, 0x00, 0x2d, 0xf0, 0x0b, 0x00, 0x2d, 0x00, 0x34, + 0x00, 0x70, 0x00, 0x74, 0x06, 0x3d, 0xfe, 0x0b, + /* '4', offset=90 */ + 0x00, 0x1f, 0x40, 0x1f, 0xc0, 0x1d, 0xa0, 0x1d, 0x30, 0x1d, 0x1c, 0x1d, 0x0d, 0x1d, 0x07, 0x1d, + 0xff, 0xff, 0x00, 0x1d, 0x00, 0x1d, 0x00, 0x1d, + /* '5', offset=114 */ + 0xfd, 0x6f, 0x03, 0xd0, 0x00, 0x34, 0x00, 0xfd, 0x07, 0x41, 0x0b, 0x80, 0x03, 0xd0, 0x00, 0x34, + 0x00, 0x6e, 0xd0, 0xfa, 0x1f, + /* '6', offset=135 */ + 0xe0, 0x2f, 0x38, 0x10, 0x0d, 0x00, 0x0a, 0x00, 0xeb, 0x0b, 0x2f, 0x3c, 0x0f, 0x70, 0x0f, 0xb0, + 0x0e, 0xb0, 0x0d, 0x70, 0x2c, 0x38, 0xe0, 0x0b, + /* '7', offset=159 */ + 0xff, 0x3f, 0x00, 0x0e, 0xc0, 0x02, 0x74, 0x00, 0x0e, 0xc0, 0x02, 0x74, 0x00, 0x0e, 0xc0, 0x02, + 0x34, 0x00, 0x0f, 0xc0, 0x01, + /* '8', offset=180 */ + 0xf4, 0x0b, 0x2d, 0x3c, 0x0e, 0x74, 0x0e, 0x34, 0x1c, 0x2c, 0xf4, 0x0f, 0x1d, 0x38, 0x0f, 0x70, + 0x0b, 0xb0, 0x0f, 0x70, 0x1d, 0x38, 0xf4, 0x0b, + /* '9', offset=204 */ + 0xf4, 0x0b, 0x1d, 0x2d, 0x0f, 0x34, 0x0b, 0x70, 0x0b, 0x70, 0x0f, 0xb4, 0x1d, 0xbc, 0xf4, 0x77, + 0x00, 0x70, 0x00, 0x34, 0x04, 0x1d, 0xfc, 0x07, + /* '.', offset=228 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, + /* 'V', offset=237 */ + 0x0d, 0x80, 0x73, 0x00, 0xcf, 0x02, 0x1c, 0x0e, 0x34, 0x34, 0xe0, 0xc0, 0xc1, 0x02, 0x0a, 0x07, + 0x34, 0x0d, 0xc0, 0x39, 0x00, 0x7b, 0x00, 0xf8, 0x00, 0xd0, 0x03, + /* 'A', offset=264 */ + 0x40, 0x0f, 0x00, 0x3e, 0x00, 0xec, 0x02, 0x70, 0x0e, 0xd0, 0x34, 0xc0, 0xc3, 0x01, 0x0b, 0x0b, + 0x1d, 0x38, 0xf8, 0xff, 0xb1, 0x00, 0xdb, 0x01, 0xb8, 0x03, 0xd0, }; const uint8_t font_meter_small_widths[96] = { - 4u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 2u, 0u, - 6u, 4u, 6u, 6u, 6u, 6u, 6u, 6u, - 6u, 6u, 0u, 0u, 0u, 0u, 0u, 0u, + 10u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 3u, 0u, + 8u, 7u, 7u, 8u, 8u, 7u, 8u, 7u, + 8u, 8u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 9u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 9u, 0u, @@ -60,9 +61,9 @@ const uint8_t font_meter_small_widths[96] = { const uint8_t font_meter_small_sizes[96] = { 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 6u, 0u, - 18u, 12u, 18u, 18u, 18u, 18u, 18u, 18u, - 18u, 18u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 9u, 0u, + 24u, 21u, 21u, 24u, 24u, 21u, 24u, 21u, + 24u, 24u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 27u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 27u, 0u, @@ -75,12 +76,12 @@ const uint8_t font_meter_small_sizes[96] = { const uint16_t font_meter_small_offsets[96] = { 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 174u, 0u, - 0u, 18u, 30u, 48u, 66u, 84u, 102u, 120u, - 138u, 156u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 207u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 228u, 0u, + 0u, 24u, 45u, 66u, 90u, 114u, 135u, 159u, + 180u, 204u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 264u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 180u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 237u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, diff --git a/opendps/font-meter_small.h b/opendps/font-meter_small.h index cf66829d..a89c87a7 100644 --- a/opendps/font-meter_small.h +++ b/opendps/font-meter_small.h @@ -1,4 +1,4 @@ -/** Font generated from gfx/Ubuntu-C.ttf 18pt */ +/** Font generated from gfx/nf.ttf 16pt */ #ifndef __FONT_METER_SMALL_H__ #define __FONT_METER_SMALL_H__ @@ -7,15 +7,15 @@ #define FONT_METER_SMALL_MAX_GLYPH_HEIGHT (12) #define FONT_METER_SMALL_MAX_GLYPH_WIDTH (9) -#define FONT_METER_SMALL_MAX_DIGIT_WIDTH (6) -#define FONT_METER_SMALL_DOT_WIDTH (2) +#define FONT_METER_SMALL_MAX_DIGIT_WIDTH (8) +#define FONT_METER_SMALL_DOT_WIDTH (3) #define FONT_METER_SMALL_SPACING (1) -#define FONT_METER_SMALL_SPACE_WIDTH (4) +#define FONT_METER_SMALL_SPACE_WIDTH (10) extern const uint32_t font_meter_small_height; extern const uint8_t font_meter_small_widths[96]; extern const uint8_t font_meter_small_sizes[96]; extern const uint16_t font_meter_small_offsets[96]; -extern const uint8_t font_meter_small_pixdata[234]; +extern const uint8_t font_meter_small_pixdata[291]; #endif // __FONT_METER_SMALL_H__ \ No newline at end of file diff --git a/opendps/gfx/nf.ttf b/opendps/gfx/nf.ttf new file mode 100644 index 0000000000000000000000000000000000000000..dcc778028924717560b46984f82ee73ffc749338 GIT binary patch literal 1281428 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⩔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

+tHUpXl4<%0dOq0TAAZJ%g~Bwz>4Fg9ksggo()T zC*O2NwV~_BpZvmWw3p)LOr{*)TBmBP;G@@&EfgO}gV;Ngr)Mw_*vo?KH+BB6Pkj*p=mG!&qHG5o3J9u&|1f9xA4}^v3qC z^|*W2@yVmpQzbL&i8~)TaPXd+H{)71y}N$MpPE=t*}YQsWM|{awLRCz z6K^|x?iZgpV`y_XJ-BH+!k$4a8c}y5;@344=DIfRO&|UE^_PEX^}urrgR?V(+gDZ| ze&XqahhKlw?o|DqC(b@SQ(dVP^Kt*Jv(vBHXsv~duPRKPSXh4M#!HVja%bQ2$y-jo z`wg#ZM{@hID88S`>Gks1SP8j%OJ;5)T&AldNi?VtHYk6Sd# zfscz+0-~`=+(uRb%$i^O;hg@H{z7B+LNnh^7UytK&>g(3m%aEKQPq7bxcK_lwNe?U zTj*pa8`B3J_tE9$+;nQLjBnf0;ZiK=R`V0=pUB)q$g)~Ja}Xw5vj#sLm|y?lx2s(z zk;oBZ+b2i4<%h)KEhkUUo%qPf8-Dim!i8>gxav0AK_L^OXK!IqJv%<$?|yJGQ$Y{_ z-%^RCv0N-?il&VN2>}#~$=1=S@fnjmh(8)zAgAsn^pTyhHRvcJ5E*|mH%A1+4?3+y z2W-K@z(5a2zXxk?JU3n}PSmr;`u!JHP5t(RTMwlO1qr8qc?HJ+b-pQ%~+b^OkkJKbC*_M=$>@x{kje^R*9Z z2($E?^mpmc>YvwtU_5Mm(D-L_$$YQ*1@o`Wf3&LB5$hJ~N$WY(ugnh!UlN=^YVaIOGNMEfIwwJJt006Urk5@;yu z6<wHF(pe8HzGG)DTH2!G7-W+NN6kcOQm24aI1<6 zl&)D_Tv6bX)MbfqvOF+S*GSJ^`5xgn8V-s@nnQV3%_?ZEx4I<34e$q3*onFk)hWeB zf$SK8Yl}BeU8BQS=JVYFf7IjAV5-9OmKH?Q#itMI6sf67Wz~Bn&=7zkEZ`N8qt9qW z7$AObe~;z^6)MGnphS_mIO3^UA%QclbwxTTgdUB>oGxmKo%}`00U*qcKotU_E`?m4 z;jLyN)$ug~H^N6m8Pa?-9V58OXd}tJDK2eAasDFoj=H@~Pkl7C3L{iYG9_w@fCG_G z6%IAH{Lxv6LH;Omq*C7e1ZA>PD8$hb`4a6c3WlhjS1uS)neBc^ea2|S^SFqpjzsGY zBqwM91}P+i7LERP?GY%FwkIM3Rvjt=#!yYpR}9@UDjdUR9@DCt2GPW1L?g(dzG&oV zuEWAb4|m?GlPk+BI2fU?TM>7Pl{RRlW6WfckAMa6qWZ7U-0nyr&iIo_&S}@xcO(z3#-fy(riBzvWg>go9y3n`$wGbv;%#1J$B5Or@ zx=ZpNBFkf7FJ`OGY^vJr&gPNSg{9ezxtWV~mpI7?*%BPEB?6t-DiZz<3nZUJwv}u( z4|{5P#l?e#n6-L%aeN$WDz{xlmXWPx7t=N0PBkVNbV(c$8uZa>lpQ+F8B8oAQD%wl zRUAJ{jJdJw%X5YlQ~GQ=>n7rBjb$V+nEE2K4Bhf0tz4mm3$T-|PW~o_eEGwt=W5fY z_3GVoZ+q>yjsN;TEp1|<xAJ83Xk0u!dtENbX1wkL zYyCHsQ92l##r5}1dJWsk7iVuCF3gPU0jF80keA!S&M$|8Enmi9pEzo^;W{?9Ft(lg zEJJSj;1yp9?qPyQ)_IHv5gl_BMi+rVMMSkAB9$!9xmB=BovqCqhG#2TZ)6HMKpFj#?7-uC`F_b5y0M}7?@i!UQLpLvy zVhrw3>bXmiZvYGk2BhwtBIDB2bCp%EAju|>v0-p4a(}E9UB_5#=+77T+n)FnCnT-5 zYqc}wg$7JYj_f75@SLM*@5}ZMikYvZvCs`NAG=qwZz*EMEcHNR46a2)`Z$5*&>FO| zY28nmiTvg3>jbRBv*tQNBAGD^I>Emc7S~pn4u*uN6uR^*FPoht7Xj$AzhRZ!yiw}} z-6C1y<7ZqZIsBX$nq&5EYb#=yDd=R{_)gO=`f00?NtJbbDeq&$Um&`kqsOf`5mmtT zyVL0oJeU>i&SIAs_wM(HYh7fa`TKD_5h-~*V^~urYn77{qk0@`hzAIU5csFlU{g=} zoxC^*Fsn!&aumz_OmdH{7gFh2zv!W>_+uif;n@tCJGq35CW}QZpZGfutu@me6*8S9 zRgFy^ZF+$fH42YJ-gYzYWITv_p+m^E+&G4!_%Vw}G40F|j>058#fJgg%tSJ5<*KY!B-R-(+U+z9yJx3@Bq9HN)Nbgp zn4zh_&FW4pxqmi`LwY9fVk1p9_BEgUO9g^p#I17v{2~^-q@D{unDv^ia*9~zdh~1=^;L{? zPb|dQB1#dL8E81(YIR!7mi0y&K<@d_5lifvS&$|R{VWO1nMSfSpgzgEXj71)r;XT< zSqJ4xKn5azmI&Q;j-)TuA!fu1)An2o?zA_tzty;v_@-X%xM{GlR=U_?GsSTYAfO!v zyhLTd%OB|r8uGN$&$bBRkHEAnQ=xcsDqS{>%4|7EX7>8T?eOj5Da520ES^ps)R*-hgx@2lE%z1WiF6$*BExXZ}OXaVN zV~u^h5>9|#$)lv9!VTF)g0w?Cic~q9H|_f%^hMj*`cAf{8>i3NdZkfzJ4Zc|xvet+ zT~WHW^6hMnU3H>Z+`}dkuWgnaS=aWnmQ(h^T#zbcy}Y;}&LMw&fWkFB8**LuYXHtYAK%uLb`S(;PTqr{;>F^$k&q|*pl0%h@<{o7KgTc1CKNW z4%PK_)@{P&_~DUEEX!`IndM5Alpi?afq$_~!TKLnBSC>}jwoACB=U|g$z4U|bH;Ek9o3NywM{G2oC{2+eZZh?kfkS(3-av~2P;QB7Q;i-e3DmBdl9AS*&! z`d(R}WcrZ7;{XZ7*n!MtRt>L=rV3rB=VA6>o7gm9bdNU!5ky66&Z_NlKp=jE2n|`6 zve`ALXz1?wD#qgo4IM3RlBf=RTGm2KA_)le?jPUo`4{J_WOl+su#?e1I>x<18MuEcD;%Hk~$dPq= z=iIzN4&aD~*{5Sp&9Qc$2zikU5Sn3`x;o<#d%)3HRoF@C$oo6tV#B})n~Gp07sHVe zT3xH@lJ!8nse@F-3;6ECf=S9_BA>wb5M)ffw;8yUzAXE z5MlY%P&ITi1WW8JL3Jd$sGkg=t&u!nH43&;f5B{B3G(U~O$bZ?nlu>B>$kT5*a z5R$J0B?ZQ%Xf@ET*kHc{+I23W0wEZOf*mP>z5vVHrn+g7(yBN4WTxS!wtsRl8fy6@ zfXDXr?eWK)Scj7W`zb>W_sFB2E+Lozg9@>Li{c`pNYN>g{(88;fJSg^*D28w=-(>g zoAp(!<#|dn8k4bBM4^1Dksb9kdI*jUaG@PkQo@`Pe4&`pw#yLru zMuqAIE2-Sxc|u`I+SO5ghuLCNRdWpOIjrL zrGj0Wj9z?+-uxBUN3yk%$5i-4^^#u8e}P-U&JS?FaPdn4%$Y4us$1eZMKud3JC%~~ zjT%WDNnwD*nT%T$M8`+YkuWx(644)12PCc+0I9n;g)|&?l*XiFXdVq&K5i^bI)C zO@K<6KCX<~q)7CQFF*t4uRXW@ygVtiL2u*|eTzCtH3BVtC!HLCM)**eiK>a7Q(g6- z2`Np;EYikFT0`3TdNjGV=T_YNC)K3%IqCpqqA}%*z$F#NeTIZC$iz@smO|>eXmF*N zqQvM)xkJ0#B~&$Jp^j!KKyl0)4QteddK5vj60w%-zHs#D7d|!|!usYU!{YXRRW?GKB&Utu5rNPG?L_OS)D~e|S|{U?42>X$ zbu{_{^wL>H0+Je?-U(gu8BKh-7tx#m2HnZbW8YBz#iMzqKqiSKk{B>c#&RJ`m8Lq{ zqEM{8{PNg7>;_L5FQIw6&isEFdlNXxs`Bo??!C2dw{BJ4+N-O&s;jE^t-8Cqr)Qt( z*=HDL-x!!-7#Lt2Kn4U^MnpvvQ8db+xPxfo>k^b0*J#wJ7~>i-F+%btCU2tt6JuPM zDc?fu$6jAI5cDOuq5JGFr+q*{tKENV$yJ78)=ljMA0GmvwGza!=< z4M99xp-s_d3`KOun+G;H%Vy%wjFvl=IBkXsN@Fk`R6=O^uq=b_^C= z^-h;ItG9%moP=v{HH9y1aX6UKT7;bgzQ|#$I>n3v)X-EcJBP3$AdJGY5%Dg?bP&FE zis2udY~f@>N8)%S?lzog_^v3gFx4O#Uh2!o=S(iKtm0a}M+X4#@3fn#;~eK0QA0Gm zV}ho{K|*PRnz&R^s|&4@uJ6oV$wZgz8j>m2SqAeK9-M>dP!lV$-Gx1z*vHT#i@#ZOOMVn@8o2aoYnc! zanIur#G!1AWq^GZ?DqUhkb{~&|AW>wJV}OFj(%cY>*X)CbQ)$eujZ!&rx!UH@spmW zr+}=R&xCPvhO4A2@2G0RQD$)_m{+|`VnrePCk0wZfAYXbqh*arsdCip^d%j|>8rCY zI7dyWY03EFFU4^c{Zg~V3EL@~g4Nha@yV3W{Vl9@5bVW!l4t=uK_du;1a{X!{PIP% zCjvhHV4y7sNr*QP0eeip$1ncAsCN)P7{PQXoDKz(NF5NLMf_Nz`-2`(dP#ugG++FY zFC-TjWdUp~)=pwWE)U6v56LMzE-#`HQmNIK^Coqm*dV4##5!VD#NF<`n{K)F#y&%Z zs?Cb=zj{*y=DfG)RfH|_CSXB?mlJWi2yr?Ei|mA)#X?NAwezA=WtuDRMF4Q{k)a++ zVnrVgiCB^9lL>Mb`T@Zf8FYGw4Oe9LPQM{SLS@0P2t~`SWKSH>1%xx=Y%dScQ6aAZ z>Dly$OEI$$QT4_M3Rz<=g7gMO4`Mcw=*aNZ|1`(+$Gc6w0hVyuszyR|LaIG<1u6Mr z5b4pN-It{5GKkVS6fXQY_DULPA!IFm<@W@0iYr9KERriv;o8ZmYYWmmJ;y%|GC53^ zNl7MN-s5FTkRs9Xkq2{tLi%iqGo;NIs=%d`$Uo_LX@UpaIjY|s=i9l%UCu=0ObvBR zNRdWGm{2McT-yprGQ;$&9^h8oic!p zNJk>s2wrcbm6;%Keb)^7>1b4+a`)$qQ!qyPeiW1*?NPGif6;3Ovt%kGOO!5EIJKnJ z2u+#sa)W_1$eIEoX$-d1i-vYPs9pq!HK`ZP4wuYWcMR7QnW`!mskY2B@>cQ8Lf|gY z>uNw{%9Fe5T{VY23^*T^Rx*%5pu1qzr1CP>vMl-dIjs^k| zA(J`8A(NAi{Nhfk* z5sW1@%NQI@{Z)Kvgb8Z7s6mqV`QQ1YuBB}0G$~#>N$fu@{{0lZ;YVDyYuGjI+OA!Ucg{81Y3=2B z`oB)QUwe!8PVG_caqTl=*N2Y@8zlm-ren({wjpBA$aX2u*gjjzGlt*r5kS_my>sos zwT3^k+4D!qDH~X&jEOW`?B683LZhyD!W1%KvZ55e0e*BYobQGE{FL2&sxEdbNg`S>#6UUY8l7YU>bv!58Rr>mN43)-?jmB&7;QSw=c)_9swkv(kJQ zuk(%?>;9(8Xn2i$EHa$xzxt&+yH?oCmzPR5g!kfQcFCQ4d>rH9ux&MV$Ae!h4eu$3 z^=5noTM}#+V!erkQ8uk7j&A$hORQXE^-y24c)W{nyv1zDn?m=fd)w=<-QoOhc=PNJ z7!knP?Sn?(dgBdvM>Vh4h}Ezz!U&{??FWh0FpiPE=x*cvP-8%sjQ8`5EwX(Ny7`b1 zO%2+Ck!-MFuSl4QK6f})vOS@=H(d**n~88tl)d474O;HlZSqZNqx?d8?O6V18mjGaRzmko#d`}^P0)WQIYUpX9X8kubc zL>JL9J%6Zbju8Sdk{n3KyQ7)@qLm;@KoPYj?uNs*H>^z>MZ+2_Xr9JoY3%q?zv+z@ zB8gf^pSiU{Yz=RJ)Suui?)T=D=!xAW)a9wwTC%&CJ|j8mjt|*^Tueh^m@`s6!O`%# z>8=o_5k2;fl}iJ@wNrM}N^PvPYHOFitS1md2}?YLfEP%$a6S_ONoKOgsJ6Q7PzKhG zSfbu?Zd<;8v}?&opxS&*PbMAmVyB#lyM0zVg=K1Z0Lf6gy5=y-C8v27o41EI zyXV7C67NDeN3bi(*6qjqCKhaJp|Af|yKI<; z7<9l8VEaWR3gJA=yAI#f{={89#_Yh#Us3x~_mmITCWyEEvQS}g$*>k~PEK#yHQYBn zy~D)kV*29tKmF^VNl4GJwJ$03^cuQFC=Gw=_^z?Kr~MCI!#n=_+*6b3V1#2sy62zI zezyI#ZZ>a!B$8@sZ~WlFx7A^8JqY#L-7gxLd(%~4Y=5>Xp3tzS!Jy|e$s=>YYgQgv zZ^q;4^s>Xtjs+vhNcLSbEkF z@64NsUpTAFTvHz>&}vE~8VtMKtBbJ6d4n5uZ%Nbd3Y*2*;*rMiphthphc|41y$$A{ zYX4%}(HoM1Y-rQdU;oje*(HP1b9jrwW+W%S^})>tdh(dk5qPc<8{9dV#9h?ah{cP+ zWnIgb7PGpQFzO>q^vV40O5cdb*nPaOx13xR!r)+LbjtFDwOC3w28(@zOHMDh_Y7_r z={s>c704#7G*)aGj0X}#4;8oyPk4)&^lJG;B_VMZao}K0x(>1?NATJkb8T^5NzbU( z(JuPN5&k(Vu<9K7MS`GY3Y~?4T);ruGOy1U@GlWKIFg7~_aAF^w$&GWHH?G_C=_`(XV&jHw+cvC!{7P?rcXR8Bt1fQtO>c?T zvIC8t;m|;2mv$__dt&p6D|Sro&Tfe|GW~tE;qX9Yr)T)!-UI)5>uo>Tx9`$R5A6Q? zGk5&MzWoPZvSs6jCyrnB_}u2LTQ{!%)aA!MwQ=L-_O&Ae#}6DjHaXZRWmb$1uSk>z zUVI0)7MDxMroq_n%HiiSLA;jRpkZ%y{juvw*H2x)0;wwwJF!yR4_A0OeBl}G9_>Ba zpKIUO{y%#34|W1(3nG%~bQq}kbi0V6kddaFP9G8oX3+)0Enx!Xd$MYS5U2Y2|COfo z|E~m^i;BLfn{!y+n$Jzp7oen{pq$@FdQNl{(IglPw%vt1TWPBy1sB zY!Jfq|50k~4^3@bNwa>>)OPy1Q=jKgZEE(S_H|~xcBijsX1lwy#B$0)hq7V{$5#Eja6X(U&6!4+*yhn}B2ifvAe^|zKKIezU!PzlVj38$ zR-VY0@}*KfNp;CD5Z|!_9f?1xjl3I6F+s`c#m&3 zu!O;L!z40Nk^hD(eLc2j_xz)iZKC+XY|ni*KVl`4$pm(<*^xv%!Dl3!s>Px)K8<9m zZbswrs98_xUMmz!*%m=BO+-utX9mi`ur_%T7{jKlkmZTtnIDA5H2j98ztJ?iyShqN zG!gc_S>9u6ha-B|i!Oq#qk7VR!}mE%zmbCM>6HxxavhL|}e4$6_!&3u2QoJEoo z2?fFy!iW$mZ|uB8hwQIo>_=cTv`j=fOj(FLFs#B1ZbhL|v6q8$oOkr&resN~wi9})~m!+F+qJoWNb0Z1M&X}=iBW2UiR?LjmYIK>$!35x*Ioa-MD3g z_L*(letv^CcEeWB;E_k4K6B>jM~}?^J%9G}Hy=81;Gu7x=I_3J{QZ^oO#2CKW4ol? z*1lW)dxq;bZQtHLCGC0cx#!C6?|84qgFeIwzu$<^o*5lGE1aLl8-{Xm7V$f37$^sn z2huDK&68u?(cmMIn4|O(eGa+<_*6vnd~=ICOHpzxlfx??^dj<>T&Y`_;-EFbmdkMg z>I7&I-38=JOn)XspP}BB3oOPUHcnQHE+pp#dn1xbeq(ZTbkZr>VOND?9b2MJk^;2~ z4dL)VrYIpBdFKPq39;pac~$|Zd!^8_m5;S^?U9n?97+ek&;WQR76m9syb7=dC+H$x9jMyU!`lgjlg*bom}1%?wE&?6 zR|oz`N!;P=Ax;l&Y}}`nbgpy%9Hv4JxX)IA*WYF z#X)<*$*?4oI!PH)P1Q@$vU2)YT`x~mR^=sG%xqNxxkG9Y$C1*5C#Kp=KRFo~-YXIJ zKKtJDc~Ys-;_u;jBhGWFjs_GpmI=ULsqPYeQ6LyYlEGs}hTjPsOH`GJ78(TIj!>UT zd@dvf9!T<*A$=iN$w3>FVi2pzk=BN|%R~U%O1iqSd$hPDo35+)9nv^N{yM6e^b8QP z<1@Fd%ufQ=MUVlyMCOVF%MkEtstvRj5b@MQdPfSDwqY->`W1_fpqna5KLm&#BR6Fj zxrenJm%Jj`iCZ=)RVGoJ%zVfy7*}$pBXA>;48a``cN|7Y)g1e1u=z17mrBW-om_A= z2P#Nxr13NBip092%n_jD~#%=pke^%o0v;&S8} zYuW;;w!A7GAd|^JiO1wZJ;8njuC;a}GUychZ?CK6y4iKs^{DK?^#5a}{NxQdd-;v1mv5xN3)d#sF z??xK(fe_l!S*NB%h70LUi$F%aPxS`Qht8ovPB_}FxCnvaUAwKS>xETWIxIC>V1=!S znl(F7OL%?xo|o6o--7zqxBnL3O*b8gRpa_wgQ3FI1|)wYebGu{^(unFdgA3?tIuB1 z%_-kkH40s0b|KvaqrTMe4M)v^!Rglasn-6%{=58J!d*c;T^hhv#o5xfW4PfjwEY)gjg?xmk`;q&54~NHUFoxdh8t#1@`CaAHWiy*Q9H?g6 zIavGaR)Y_)^hBLiGW^yZ;X-unT}|xbmwjYMFdJU>+F5^BeBFaf1My&aYyXxtYd395 zR8Rb~87$kqJw3@pZ*GtZc~@N7tE0_I+?CP?2ChGqKILHQhhi@MxnH?%aQ{6qzApix z+{H1mvtJ<-SC$BlkLiWo8#x9;k&OiKEXRJ+%4c zz=8fav(@V^MDk`MGghtya>2Qkm0V~jJ5X+Hu4gJff8PLaYJYO-nV&p!^3+dGUH8l> zPugRq3jFqIt#XWr32$T=$< zHtZhT?j9Z57B};8!<)%uyk=KC-_;*C<5RYI_wfUFpt!vF?6vQG;>qSxW2QNT0D5ZF z`$c?d^Wo9sqoW&4Gcz@G*^t@jwx>=^?Rs?Y9qniDeslXLZ#;3@{f3oYh+K+zt zHtp!>Z%$2(jxL=V8l8a%glWp^y5Y_DP2(uzH;l zX1>U*nYTVt!b}mf!gffL>%w-T-*Ngx`9W7}<4Kr7p&KA`2zN0C9<<;j;Yg3_MT7!8 z^H%unpbK=TrZiU+Ewz^hU`+=3QjX+Y zDARpX!?u%$7_QMhAWCMxmP^M=c$Ps#@t(r4 z0Hj=$u;{`g*rep*=VsN;D9}N&xezrBM#RuAV>gza9;aP4JOdbV-T?se@UEy3ifi<)Pt#f8HnJQb+89CS_TCb zGZJ*aiCQj{#DJWr+!zyytRDssS3}Aa6LB!cYJYABDLLyauok#GDQOFS795CHy@O7C1zv08Y$It9S*A0qLOZP`Vl_ z;3^o@s+>EQ`d+7U%O}#MTrySGB)d<@z~GH0A#M;`U`>Eb9}Wj4y_rYW5+!^dRvUr* zL^@XYe%I+$j46cf8pNelkw7$~cVjc$? zC-3|4aoj@ZcIf(FT>sEBrC-_^hGAd7)W%=q_f!~2H`Og}XlvIa2G z*Ux`DJD3W@^d!8r$NkcOyJ`8WHr}my@9vt;?|SUfM|b5XbJqjA6f$uBGxf^qZc^!= zh_CM6_S)+&sYF7pfz)W~_y=EiO#{@|ZTr5CA1>zR+uyUpm$l$m{jrk=c70&iUC-SK z5_SLfIt*>~*z)b~+8&69&fg%=P*z~Ynbn|M*Ejd9ym|!3W;Bzi<~+o27VLzVUBB{< zm1qOK0nbGbZ}CL}jD`ETUu(PFKX5nM1NXV^cl{lEgwvaJT4(Q*J+ZT8sJ`uR9Q2{X zEI_Rsm3;?+LkO7KM=zvMD)(Acv5QXj3%ii)5zyj!vQ9w@gCp;wmUmuI^jZcU60E90 zt=I!PJm|2R6L7T-fI6=%s=P|cu3c}q?^yTF1Gk@l<@Aj+fv}M;`pjCx9SZgCXsmtp zik=mg4km6gxa^i?eY*#&VlbTXmcm=kzrC`)w(j+Fc+rRR5&Zs()4B4pQffF;TUQ~z z5CF-MzMOtzVz@GVaA@1RcbeU1CS`!V#qso>U*7;YL7*$M_TGD5z4oT>>?c$>qiRGF z%~cQV-ujO1%WhuUSZTA0Scl7RTQ+%R^XkX9@{{9RW(-WYa3F=3GKWQv-nV;@M8wI_ z6WLrdf8xhCxN)xOGlo`Nnr~Ea+k_B}pP0VoKW+^Au#XQ!y1UGwhA422M4uJ05rsyr zinZnJy7rF}8NXS=4lS_!_GP%W_yQ4(6fh`@`fL!rBc6Oc5-fxCmA8r`Krwiu!}$6nTxFC zMIX2^X2X2nDKgh&|mbS8(-18@1Jk$*-#xiFkIj6HlqE71Ivc5zwK3P zW?wd}6(`Q!>>}c~WB2o3*OcoP*3DzY1^NwWcgwU*+9~Ze?X}ulvHJN_?F*n<{z&_& z_TSL_sJ>L+sNb&Nr@v1)F=BLexB+bEsXH8igAW9#i?kKKE49e0jRgWfR#R(AI3tH| zb1Z$G^+3`<9T@j5$t0cDW0ArzLu&a{ms^7V}`ZBmT~r0S#g_EYx7U2 zwGW77DMXdgXi*i_V!G2OXqhT^p-2sSoF7WVloqQiB*e}XS0hi=N##q{g->3%laftv z1ad3eqvF`@8vUXAO@_E$=`gbtzyL82G=K~oo?2PYGlD88g(_H{VFNCECC#9sYRpu3 z;u!ueV89a?$HhEBT=+d!Pc#gA1b{dL;gszoBqD+k(`R>q*#SWa;Fxl5xjmc;10Dd6 zgdHdH5ChEt{_B_|0u=<%eQq=ZbxV!s~Tdcx+yjvC=`C9Q9vVWAR0L!qKs@BweCebpDpk7ob^$&6y~%_s#t z39NTHAH{HP0>pvvjk*S2aXFS3cz9j^XoN7jMA2JS!GtzoiqtFN9@;yAwsh&OOJ!!I zVpJrNV>1r#|JZ(jmfV5N%=Ob2m@qcy1np%@YO#hC$Zu1nGeOvJ!fHCTF2= zOr6mat#TZ#K{idNw+&+30b9+iB#UH}cnL9|Li7+^{2UnD!7xBNfc-Dk|EG_s)Cijc z=Qo4zDuzJtd0?OVv2jmGs1&`FmI`mi8Xpnt6qzLDpu}^#p>l~`!6fOU{7}> zQhfztsc6Z}goC+SSRXBLQsM9u3YUJA2s82HQ7e&mqtL?`$c(xNEx&Fumw@gdlCg=x z57Qj|XHg{CGLw8}`;%T17#H9p0zDj$@SCGUg5LB0o1Pl4Go|oQ3yE#9!O*f|0~~BH zIHd|?6bBby*-mu_ zFUCHfGgKuSi+Gat#7E>{!O044C17-+_(UOD5;GlzXZ@$hIseubbEP>uxU_C|qQ&^t z*on4a6g=JN5Z$*v`{SNwv&UVP?{iZh``A7$(Ejy4{fq5)X-C{YXx7iYvEFRfjqB>o z^AG;7kL_>&Py4s~`A^Exc2LeVn$3XAbh!dL`6il)YR!keD3HzVztKiFe)F5l@BaR) zwKNwSwNZDgeSiDDo6bLb{_Xk?JU2ai{wD3E)S0)ni^*%oRdbEI=8(%=<9eCvRjvoH z5cxCLKY)V$8&GKl8CwW%y^6$*HbJ)ez}j$gi6M{!TpN{gm8z6!)4!P-{TE&z9XTNi;qH-b&^OMINh;!WgD{naZ{30Z|+iW%BDCGAW=w~^vvFk%rfIrLQ>7i6AnMkcXv)t?TtbD~PyAf}{Ge40-t?^Spb_TIv3$w3Q z02bA<#h3i}R34MA)XhJ?xpm^(C-_iJjp~BXPpBmTx}tj6Z)*flacX}EX#H((-90w5LhI@o%zq_LypMDwGZCA>00Bu)Ac=!vX5(TV}^q9?MyaC4#wpLAH4QBdogY5 zOLf?vNz~eCOohn+?HH9O3QRo5m|6l{%XCn(G$sWp_>77x-}64$t~;e+kqy6g;n4Yl zbPIS8&SY}lQQsZO9<_x-dSPwHCOxoE&O6RGcHl2a^n#x+DA-vQ%x|UB6-J5=zM^!5 zL4hJXRm>RWBT-#k64wg{NlI)Y+YdRQlZAYpM`a ztSIaOdvNzaW+GqTQUe|dVPD5p-Ow-l?596>Dch@3ENT4w?B@^5PtknfKm#lC0cFws&2M6GCY5pR=GoX7NrHut~yr}*DUD}jPQpq879Os=s(>-a%3I`ngwP_EM4UG~|}eO`V@=K@g~_DvjbcCYT9 zymm@7goJUPDM*v_dtl12vI;q^#H|TjC?aHI6^lW*CZUW8f!U3=9=@@E=->)(fVg2h*S`$4Wc_B{;cgM;=M-!f< zI|TC(EGAf~Ru!pmt$uNr$a2aF0rW_lnUy(T6yLN!V{I3sM8p@vcXJQ+4w{v=$Fq?% zDz|ceEE3NWgd-H{t0hr&1!7&@>vG-EGy!7?766EsHCib4fTJ2i4=E0PNY2sPGkgQJ zp4GCD+RP*E;ZyH?=c!W$UxY4#@*g>VX1$i$UGH&Z!=JW`CIn{KAFv58E6BnA@?*rr)GwElE;G?$yI zRtLf0h)iXQV}$O`7WNQUB^=9Jfs`NcAAN+ZbPcQxLL(3($qyM2^hH7-AX_w&{ZTX= zgXcf}@F}O-A4Js!TZX=C(ET0bQmksvY9H0UsC`X)N`I+-M!%2U3T+;P@0_VIykg^- zXRJg&!w9O~>cW&^?kETYCR%4|s7WNEmidFZvmuG7Le02NviWV~LROUPoVryGYW^x2 zYDWa4Dn^=xr;c`ZQMt%PWD6CK0;x7BJA0v;?D9x)Qc?kt42(+=U1EhM-_Esj!8Lmd zud}D9!@oRL@^8oP$w@40&JpGEba_W`P!+fZ;nc`hI>C|7tJTw*8tdfgtXHL~6Lt~9 zEL^Fa6Zz11BP0n_&=?F@msg%Y|C-VaJJ-ATf5n zq8qJpG#eIRKDGrsUQ^-emhABcM*d)|B+&%0DSHWZ4A?3semGjel;o@?yEWw?u0cU0 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%0DS>8@C9 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

CDc{OZr={xcuPRAb~49)%t6zcLxhY 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

{`??zpNYZZMXd;jHYIH#(|&YjV_XODD^cH~;r0 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%0DT8F1uU2#bt2>-?uuC(exD{T~ZKt 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 literal 0 HcmV?d00001 From 6c819bf4d591a64f9b7246bc6b5448b4d1a21e22 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 29 Sep 2019 01:04:37 -0600 Subject: [PATCH 024/175] gen_lookup.py will also include 'W' --- opendps/gen_lookup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opendps/gen_lookup.py b/opendps/gen_lookup.py index 28f1fff6..5bc5159f 100644 --- a/opendps/gen_lookup.py +++ b/opendps/gen_lookup.py @@ -374,7 +374,7 @@ def main(): # If this is a font file ensure that a font_size has been specified if args.font_size: - characters = "0123456789.VA" # The characters to generate a lookup table of + characters = "0123456789.VAW" # The characters to generate a lookup table of if args.ascii: characters = "" for ch in range(0x21,0x7F): # skip , From 1088202b9e5bdb8fb9c8a9174616de6a907a4c9c Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 29 Sep 2019 01:05:33 -0600 Subject: [PATCH 025/175] Adding the compiled fonts with missing 'w' --- opendps/font-meter_large.c | 17 +++++++++++++---- opendps/font-meter_large.h | 6 +++--- opendps/font-meter_medium.c | 13 +++++++++---- opendps/font-meter_medium.h | 2 +- opendps/font-meter_small.c | 11 +++++++---- opendps/font-meter_small.h | 4 ++-- 6 files changed, 35 insertions(+), 18 deletions(-) diff --git a/opendps/font-meter_large.c b/opendps/font-meter_large.c index e56c0f11..aea9fc72 100644 --- a/opendps/font-meter_large.c +++ b/opendps/font-meter_large.c @@ -3,7 +3,7 @@ #include "font-meter_large.h" const uint32_t font_meter_large_height = 25; -const uint8_t font_meter_large_pixdata[1271] = { +const uint8_t font_meter_large_pixdata[1396] = { /* '0', offset=0 */ 0x00, 0xf4, 0x6f, 0x00, 0x40, 0xff, 0xff, 0x02, 0xc0, 0xff, 0xff, 0x0b, 0xf0, 0x1f, 0xf4, 0x1f, 0xf4, 0x07, 0xc0, 0x3f, 0xfc, 0x02, 0x80, 0x7f, 0xfc, 0x01, 0xc0, 0xbf, 0xfd, 0x00, 0xf0, 0xff, @@ -105,6 +105,15 @@ const uint8_t font_meter_large_pixdata[1271] = { 0x01, 0xfc, 0xff, 0xff, 0xbf, 0x40, 0xff, 0xff, 0xff, 0x3f, 0xe0, 0x0b, 0x00, 0xd0, 0x0f, 0xfc, 0x01, 0x00, 0xf0, 0x47, 0x3f, 0x00, 0x00, 0xf8, 0xe3, 0x0f, 0x00, 0x00, 0xfd, 0xfc, 0x02, 0x00, 0x00, 0x7f, 0x3f, 0x00, 0x00, 0xc0, 0x2f, + /* 'W', offset=1271 */ + 0x7f, 0x00, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00, 0xfc, 0xbe, 0x00, 0x00, 0x00, 0xfc, 0xbd, + 0x00, 0x00, 0x00, 0xfc, 0xfd, 0x00, 0x00, 0x00, 0xfd, 0xfc, 0x00, 0x00, 0x00, 0xbd, 0xfc, 0x00, + 0x00, 0x00, 0xbe, 0xfc, 0x00, 0xfe, 0x00, 0x7e, 0xf8, 0x01, 0xff, 0x01, 0x3f, 0xf8, 0x01, 0xff, + 0x02, 0x3f, 0xf4, 0x41, 0xff, 0x02, 0x3f, 0xf4, 0x82, 0xef, 0x03, 0x3f, 0xf0, 0x82, 0xdb, 0x43, + 0x2f, 0xf0, 0xc3, 0xcb, 0x47, 0x1f, 0xf0, 0xc3, 0xc7, 0x4b, 0x1f, 0xe0, 0xd3, 0x83, 0x8f, 0x0f, + 0xe0, 0xe3, 0x43, 0x8f, 0x0f, 0xd0, 0xf7, 0x02, 0xcf, 0x0f, 0xd0, 0xf7, 0x01, 0xdf, 0x0b, 0xc0, + 0xfb, 0x00, 0xee, 0x0b, 0xc0, 0xff, 0x00, 0xfd, 0x07, 0xc0, 0xbf, 0x00, 0xfc, 0x07, 0x80, 0x7f, + 0x00, 0xfc, 0x03, 0x80, 0x3f, 0x00, 0xfc, 0x03, 0x40, 0x3f, 0x00, 0xf8, 0x03, }; const uint8_t font_meter_large_widths[96] = { @@ -114,7 +123,7 @@ const uint8_t font_meter_large_widths[96] = { 16u, 16u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 19u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 18u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 18u, 20u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, @@ -129,7 +138,7 @@ const uint8_t font_meter_large_sizes[96] = { 100u, 100u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 119u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 113u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 113u, 125u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, @@ -144,7 +153,7 @@ const uint16_t font_meter_large_offsets[96] = { 801u, 901u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 1152u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 1039u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 1039u, 1271u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, diff --git a/opendps/font-meter_large.h b/opendps/font-meter_large.h index 3f6fbdcb..eaac85a0 100644 --- a/opendps/font-meter_large.h +++ b/opendps/font-meter_large.h @@ -6,16 +6,16 @@ #include #define FONT_METER_LARGE_MAX_GLYPH_HEIGHT (25) -#define FONT_METER_LARGE_MAX_GLYPH_WIDTH (19) +#define FONT_METER_LARGE_MAX_GLYPH_WIDTH (20) #define FONT_METER_LARGE_MAX_DIGIT_WIDTH (17) #define FONT_METER_LARGE_DOT_WIDTH (6) -#define FONT_METER_LARGE_SPACING (3) +#define FONT_METER_LARGE_SPACING (4) #define FONT_METER_LARGE_SPACE_WIDTH (20) extern const uint32_t font_meter_large_height; extern const uint8_t font_meter_large_widths[96]; extern const uint8_t font_meter_large_sizes[96]; extern const uint16_t font_meter_large_offsets[96]; -extern const uint8_t font_meter_large_pixdata[1271]; +extern const uint8_t font_meter_large_pixdata[1396]; #endif // __FONT_METER_LARGE_H__ \ No newline at end of file diff --git a/opendps/font-meter_medium.c b/opendps/font-meter_medium.c index b6b72f62..db244f69 100644 --- a/opendps/font-meter_medium.c +++ b/opendps/font-meter_medium.c @@ -3,7 +3,7 @@ #include "font-meter_medium.h" const uint32_t font_meter_medium_height = 18; -const uint8_t font_meter_medium_pixdata[665] = { +const uint8_t font_meter_medium_pixdata[728] = { /* '0', offset=0 */ 0x00, 0xfe, 0x01, 0xd0, 0xff, 0x0f, 0xf0, 0x42, 0x2f, 0xf8, 0x00, 0x3e, 0x7c, 0x00, 0x7f, 0x3c, 0x80, 0xbf, 0x3d, 0xc0, 0xbb, 0x3d, 0xf0, 0xf8, 0x3d, 0x78, 0xf8, 0x3d, 0x3c, 0xf4, 0x3d, 0x0f, @@ -67,6 +67,11 @@ const uint8_t font_meter_medium_pixdata[665] = { 0x0f, 0x00, 0xf0, 0xf1, 0x01, 0x00, 0x0f, 0x2e, 0x00, 0xb4, 0xd0, 0x03, 0x80, 0x07, 0x3c, 0x00, 0x3c, 0x80, 0x07, 0xd0, 0x03, 0xf4, 0x00, 0xfe, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0x01, 0x0f, 0x00, 0x2e, 0xf8, 0x00, 0xd0, 0xc3, 0x0b, 0x00, 0x7c, 0x7c, 0x00, 0xc0, 0xdb, 0x03, 0x00, 0xf8, + /* 'W', offset=665 */ + 0x1f, 0x00, 0x00, 0xff, 0x01, 0x00, 0xf0, 0x2e, 0x00, 0x00, 0xdf, 0x02, 0x00, 0xf4, 0x3d, 0xf0, + 0x42, 0xcf, 0x43, 0x2f, 0xb4, 0x3c, 0xf4, 0x83, 0xcb, 0x83, 0x3b, 0x78, 0x7c, 0x7c, 0xc7, 0x83, + 0xc7, 0xb2, 0x3c, 0xb4, 0x1d, 0xcb, 0x43, 0xdb, 0xf0, 0x3c, 0xf0, 0x0e, 0xde, 0x02, 0xff, 0xd0, + 0x1e, 0xf0, 0x0b, 0xfc, 0x01, 0x7f, 0xc0, 0x0f, 0xe0, 0x03, 0xf8, 0x00, 0x3d, 0x80, 0x0f, }; const uint8_t font_meter_medium_widths[96] = { @@ -76,7 +81,7 @@ const uint8_t font_meter_medium_widths[96] = { 12u, 12u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 14u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 13u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 13u, 14u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, @@ -91,7 +96,7 @@ const uint8_t font_meter_medium_sizes[96] = { 54u, 54u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 63u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 59u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 59u, 63u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, @@ -106,7 +111,7 @@ const uint16_t font_meter_medium_offsets[96] = { 412u, 466u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 602u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 543u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 543u, 665u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, diff --git a/opendps/font-meter_medium.h b/opendps/font-meter_medium.h index 5955c86b..e9241fe7 100644 --- a/opendps/font-meter_medium.h +++ b/opendps/font-meter_medium.h @@ -16,6 +16,6 @@ extern const uint32_t font_meter_medium_height; extern const uint8_t font_meter_medium_widths[96]; extern const uint8_t font_meter_medium_sizes[96]; extern const uint16_t font_meter_medium_offsets[96]; -extern const uint8_t font_meter_medium_pixdata[665]; +extern const uint8_t font_meter_medium_pixdata[728]; #endif // __FONT_METER_MEDIUM_H__ \ No newline at end of file diff --git a/opendps/font-meter_small.c b/opendps/font-meter_small.c index f4fb1dc9..a249dd5f 100644 --- a/opendps/font-meter_small.c +++ b/opendps/font-meter_small.c @@ -3,7 +3,7 @@ #include "font-meter_small.h" const uint32_t font_meter_small_height = 12; -const uint8_t font_meter_small_pixdata[291] = { +const uint8_t font_meter_small_pixdata[321] = { /* '0', offset=0 */ 0xe0, 0x0b, 0x2c, 0x2c, 0x0d, 0x3c, 0x0e, 0x7d, 0x0b, 0xb7, 0x8b, 0xb2, 0xcb, 0xb0, 0x7b, 0xb0, 0x3e, 0x70, 0x1d, 0x34, 0x2c, 0x2c, 0xe0, 0x0b, @@ -42,6 +42,9 @@ const uint8_t font_meter_small_pixdata[291] = { /* 'A', offset=264 */ 0x40, 0x0f, 0x00, 0x3e, 0x00, 0xec, 0x02, 0x70, 0x0e, 0xd0, 0x34, 0xc0, 0xc3, 0x01, 0x0b, 0x0b, 0x1d, 0x38, 0xf8, 0xff, 0xb1, 0x00, 0xdb, 0x01, 0xb8, 0x03, 0xd0, + /* 'W', offset=291 */ + 0x0b, 0x00, 0xbb, 0x00, 0x70, 0x0e, 0x00, 0xd7, 0xb0, 0x34, 0x4d, 0x4f, 0xc3, 0xe8, 0x38, 0x9c, + 0x9d, 0xc2, 0x8d, 0x2e, 0xec, 0xe4, 0x81, 0x0f, 0x1f, 0xb4, 0xf0, 0x40, 0x07, 0x0e, }; const uint8_t font_meter_small_widths[96] = { @@ -51,7 +54,7 @@ const uint8_t font_meter_small_widths[96] = { 8u, 8u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 9u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 9u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 9u, 10u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, @@ -66,7 +69,7 @@ const uint8_t font_meter_small_sizes[96] = { 24u, 24u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 27u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 27u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 27u, 30u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, @@ -81,7 +84,7 @@ const uint16_t font_meter_small_offsets[96] = { 180u, 204u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 264u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 237u, 0u, + 0u, 0u, 0u, 0u, 0u, 0u, 237u, 291u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, diff --git a/opendps/font-meter_small.h b/opendps/font-meter_small.h index a89c87a7..9ea31308 100644 --- a/opendps/font-meter_small.h +++ b/opendps/font-meter_small.h @@ -6,7 +6,7 @@ #include #define FONT_METER_SMALL_MAX_GLYPH_HEIGHT (12) -#define FONT_METER_SMALL_MAX_GLYPH_WIDTH (9) +#define FONT_METER_SMALL_MAX_GLYPH_WIDTH (10) #define FONT_METER_SMALL_MAX_DIGIT_WIDTH (8) #define FONT_METER_SMALL_DOT_WIDTH (3) #define FONT_METER_SMALL_SPACING (1) @@ -16,6 +16,6 @@ extern const uint32_t font_meter_small_height; extern const uint8_t font_meter_small_widths[96]; extern const uint8_t font_meter_small_sizes[96]; extern const uint16_t font_meter_small_offsets[96]; -extern const uint8_t font_meter_small_pixdata[291]; +extern const uint8_t font_meter_small_pixdata[321]; #endif // __FONT_METER_SMALL_H__ \ No newline at end of file From f9f4ea9639a734cbae436d230b14a5a81335c0e7 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 29 Sep 2019 15:05:31 -0600 Subject: [PATCH 026/175] Added power limit feature to DPSMode. Maximum power can be defined and a warning icon will be displayed if output power exceeds 80%. Power will cut if it exceeds 100% and a flashing icon will display. Reset by pressing power button once. --- opendps/Makefile | 2 + opendps/func_dpsmode.c | 305 ++++++++++++++++++++++++------------- opendps/gfx-oppbar.c | 38 +++++ opendps/gfx-oppbar.h | 13 ++ opendps/gfx-ppbar.c | 38 +++++ opendps/gfx-ppbar.h | 13 ++ opendps/gfx/png/oppbar.png | Bin 0 -> 1117 bytes opendps/gfx/png/ppbar.png | Bin 0 -> 1115 bytes 8 files changed, 307 insertions(+), 102 deletions(-) create mode 100644 opendps/gfx-oppbar.c create mode 100644 opendps/gfx-oppbar.h create mode 100644 opendps/gfx-ppbar.c create mode 100644 opendps/gfx-ppbar.h create mode 100644 opendps/gfx/png/oppbar.png create mode 100644 opendps/gfx/png/ppbar.png diff --git a/opendps/Makefile b/opendps/Makefile index 44503224..f3956bff 100644 --- a/opendps/Makefile +++ b/opendps/Makefile @@ -105,6 +105,8 @@ OBJS = \ gfx-iconpower.o \ gfx-cvbar.o \ gfx-ccbar.o \ + gfx-ppbar.o \ + gfx-oppbar.o \ gfx-padlock.o \ gfx-power.o \ gfx-thermometer.o \ diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index ccb45dcc..a1b8aa51 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -30,6 +30,8 @@ #include "gfx-iconpower.h" #include "gfx-cvbar.h" #include "gfx-ccbar.h" +#include "gfx-ppbar.h" +#include "gfx-oppbar.h" #include "font-meter_large.h" #include "hw.h" #include "func_dpsmode.h" @@ -42,16 +44,17 @@ #include "opendps.h" /* - * This is the implementation of the CV screen. It has two editable values, - * constant voltage and current limit. When power is enabled it will continously - * display the current output voltage and current draw. If the user edits one - * of the values when power is eabled, the other will continue to be updated. - * Thid allows for ramping the voltage and obsering the current increase. + * This is the implementation of the DPS look-alike screen. It has 3 editable + * properties. + * Voltage limit (constant voltage) + * Current limit (constant current) + * Power limit (over power protection, 0 to disable) */ static void dpsmode_enable(bool _enable); static void voltage_changed(ui_number_t *item); static void current_changed(ui_number_t *item); +static void power_changed(ui_number_t *item); static void dpsmode_tick(void); static void activated(void); static void deactivated(void); @@ -61,14 +64,13 @@ static void past_restore(past_t *past); static set_param_status_t set_parameter(char *name, char *value); static set_param_status_t get_parameter(char *name, char *value, uint32_t value_len); -static void clear_bars(void); -static void clear_ccbar(void); -static void clear_cvbar(void); +static void clear_bars(bool all); +static void draw_bars(void); /* We need to keep copies of the user settings as the value in the UI will * be replaced with measurements when output is active */ -static int32_t saved_v, saved_i; +static int32_t saved_v, saved_i, saved_p; // single edit mode, with M1/M2 buttons, not select. // pressing any other button when in this mode will exit the edit mode @@ -79,11 +81,14 @@ enum { CUR_GFX_NOT_DRAWN = 0, CUR_GFX_CV = 1, CUR_GFX_CC = 2, + CUR_GFX_PP = 4, + CUR_GFX_OPP = 8, } dpsmode_graphics; #define SCREEN_ID (6) -#define PAST_U (0) +#define PAST_V (0) #define PAST_I (1) +#define PAST_P (2) #define XPOS_CCCV (25) #define XPOS_METER (117) @@ -147,7 +152,7 @@ ui_number_t dpsmode_power = { .id = 12, .x = XPOS_METER, .y = YPOS_POWER, - .can_focus = false, // TODO: OPP feature, with warning bar when approaching power limit + .can_focus = true, }, .font_size = FONT_METER_LARGE, .alignment = ui_text_right_aligned, @@ -155,12 +160,12 @@ ui_number_t dpsmode_power = { .color = COLOR_WATTAGE, .value = 0, .min = 0, - .max = 0, + .max = 0, // set at init .si_prefix = si_micro, .num_digits = 2, .num_decimals = 2, .unit = unit_watt, - .changed = NULL, + .changed = &power_changed, }; @@ -223,19 +228,19 @@ static set_param_status_t set_parameter(char *name, char *value) int32_t ivalue = atoi(value); if (strcmp("voltage", name) == 0 || strcmp("u", name) == 0) { if (ivalue < dpsmode_voltage.min || ivalue > dpsmode_voltage.max) { - emu_printf("[CL] Voltage %d is out of range (min:%d max:%d)\n", ivalue, dpsmode_voltage.min, dpsmode_voltage.max); + emu_printf("[DPS] Voltage %d is out of range (min:%d max:%d)\n", ivalue, dpsmode_voltage.min, dpsmode_voltage.max); return ps_range_error; } - emu_printf("[CL] Setting voltage to %d\n", ivalue); + emu_printf("[DPS] Setting voltage to %d\n", ivalue); dpsmode_voltage.value = ivalue; voltage_changed(&dpsmode_voltage); return ps_ok; } else if (strcmp("current", name) == 0 || strcmp("i", name) == 0) { if (ivalue < dpsmode_current.min || ivalue > dpsmode_current.max) { - emu_printf("[CL] Current %d is out of range (min:%d max:%d)\n", ivalue, dpsmode_current.min, dpsmode_current.max); + emu_printf("[DPS] Current %d is out of range (min:%d max:%d)\n", ivalue, dpsmode_current.min, dpsmode_current.max); return ps_range_error; } - emu_printf("[CL] Setting current to %d\n", ivalue); + emu_printf("[DPS] Setting current to %d\n", ivalue); dpsmode_current.value = ivalue; current_changed(&dpsmode_current); return ps_ok; @@ -272,35 +277,43 @@ static set_param_status_t get_parameter(char *name, char *value, uint32_t value_ */ static void dpsmode_enable(bool enabled) { - emu_printf("[CL] %s output\n", enabled ? "Enable" : "Disable"); + emu_printf("[DPS] %s output\n", enabled ? "Enable" : "Disable"); if (enabled) { /** Display will now show the current values, keep the user setting saved */ saved_v = dpsmode_voltage.value; saved_i = dpsmode_current.value; + saved_p = dpsmode_power.value; + (void) pwrctl_set_vout(dpsmode_voltage.value); (void) pwrctl_set_iout(dpsmode_current.value); (void) pwrctl_set_ilimit(0xFFFF); /** Set the current limit to the maximum to prevent OCP (over current protection) firing */ pwrctl_enable_vout(true); + // clear all bars, including over power protection + clear_bars(true); + } else { + // already off, turning off again will reset any pp warnings + if ( ! pwrctl_vout_enabled()) { + clear_bars(true); + } else { + // when disabled first, clear only cc/cv, not power + clear_bars(false); + } + pwrctl_enable_vout(false); + /** Make sure we're displaying the settings and not the current * measurements when the power output is switched off */ - dpsmode_voltage.value = saved_v; - dpsmode_voltage.color = COLOR_VOLTAGE; dpsmode_voltage.ui.draw(&dpsmode_voltage.ui); dpsmode_current.value = saved_i; - dpsmode_current.color = COLOR_AMPERAGE; dpsmode_current.ui.draw(&dpsmode_current.ui); - dpsmode_power.value = 0; - dpsmode_power.color = COLOR_WATTAGE; + dpsmode_power.value = saved_p; dpsmode_power.ui.draw(&dpsmode_power.ui); - - clear_bars(); } } @@ -326,6 +339,17 @@ static void current_changed(ui_number_t *item) (void) pwrctl_set_iout(item->value); } +/** + * @brief Callback for when value of the power item is changed + * + * @param item The current item + */ +static void power_changed(ui_number_t *item) +{ + saved_p = item->value; + // (void) pwrctl_set_iout(item->value); +} + static bool event(uui_t *ui, event_t event) { @@ -385,6 +409,7 @@ static bool event(uui_t *ui, event_t event) { * @brief Callback when screen is activated */ static void activated(void) { + clear_bars(true); } @@ -393,7 +418,6 @@ static void activated(void) { */ static void deactivated(void) { - clear_bars(); tft_clear(); } @@ -405,12 +429,15 @@ static void deactivated(void) static void past_save(past_t *past) { /** @todo: past bug causes corruption for units smaller than 4 bytes (#27) */ - if (!past_write_unit(past, (SCREEN_ID << 24) | PAST_U, (void*) &saved_v, 4 /* sizeof(dpsmode_voltage.value) */ )) { + if (!past_write_unit(past, (SCREEN_ID << 24) | PAST_V, (void*) &saved_v, 4 /* sizeof(dpsmode_voltage.value) */ )) { /** @todo: handle past write failures */ } if (!past_write_unit(past, (SCREEN_ID << 24) | PAST_I, (void*) &saved_i, 4 /* sizeof(dpsmode_current.value) */ )) { /** @todo: handle past write failures */ } + if (!past_write_unit(past, (SCREEN_ID << 24) | PAST_P, (void*) &saved_p, 4 /* sizeof(dpsmode_power.value) */ )) { + /** @todo: handle past write failures */ + } } /** @@ -422,7 +449,7 @@ static void past_restore(past_t *past) { uint32_t length; uint32_t *p = 0; - if (past_read_unit(past, (SCREEN_ID << 24) | PAST_U, (const void**) &p, &length)) { + if (past_read_unit(past, (SCREEN_ID << 24) | PAST_V, (const void**) &p, &length)) { saved_v = dpsmode_voltage.value = *p; (void) length; } @@ -430,6 +457,10 @@ static void past_restore(past_t *past) saved_i = dpsmode_current.value = *p; (void) length; } + if (past_read_unit(past, (SCREEN_ID << 24) | PAST_P, (const void**) &p, &length)) { + saved_p = dpsmode_power.value = *p; + (void) length; + } } /** @@ -444,49 +475,55 @@ static void dpsmode_tick(void) { uint16_t i_out_raw, v_in_raw, v_out_raw; hw_get_adc_values(&i_out_raw, &v_in_raw, &v_out_raw); + /** Continously update max voltage output value * Max output voltage = Vin / VIN_VOUT_RATIO * Add 0.5f to ensure correct rounding when truncated */ dpsmode_voltage.max = (float) pwrctl_calc_vin(v_in_raw) / VIN_VOUT_RATIO + 0.5f; + // set the maximum power based on max voltage and max amps + dpsmode_power.max = dpsmode_voltage.max * CONFIG_DPS_MAX_CURRENT; + + // power enabled if (pwrctl_vout_enabled()) { + // get the actual voltage and current being supplied int32_t vout_actual = pwrctl_calc_vout(v_out_raw); int32_t cout_actual = pwrctl_calc_iout(i_out_raw); + int32_t power_actual = vout_actual * cout_actual; + + // TODO: Issue where focus causes a brief frame where value is incorrect + + // Voltage setting has focus, update with the desired value and not output value + if (dpsmode_voltage.ui.has_focus && dpsmode_voltage.value != saved_v) { + dpsmode_voltage.value = saved_v; + dpsmode_voltage.ui.draw(&dpsmode_voltage.ui); + } + // Voltage setting is not focused, update with actual output voltage + if ( ! dpsmode_voltage.ui.has_focus && dpsmode_voltage.value != vout_actual) { + dpsmode_voltage.value = vout_actual; + dpsmode_voltage.ui.draw(&dpsmode_voltage.ui); + } - dpsmode_power.value = vout_actual * cout_actual; - dpsmode_power.color = COLOR_WATTAGE; - dpsmode_power.ui.draw(&dpsmode_power.ui); - - if (dpsmode_voltage.ui.has_focus) { - /** If the voltage setting has focus, make sure we're displaying - * the desired setting and not the current output value. */ - if (dpsmode_voltage.value != saved_v) { - dpsmode_voltage.value = saved_v; - dpsmode_voltage.ui.draw(&dpsmode_voltage.ui); - } - } else { - /** No focus, update display if necessary */ - if (dpsmode_voltage.value != vout_actual) { - dpsmode_voltage.value = vout_actual; - dpsmode_voltage.color = COLOR_VOLTAGE; - dpsmode_voltage.ui.draw(&dpsmode_voltage.ui); - } + // Same for amperage. update with desired value if focused + if (dpsmode_current.ui.has_focus && dpsmode_current.value != saved_i) { + dpsmode_current.value = saved_i; + dpsmode_current.ui.draw(&dpsmode_current.ui); + } + // Update with actual output voltage if not in focus + if ( ! dpsmode_current.ui.has_focus && dpsmode_current.value != cout_actual) { + dpsmode_current.value = cout_actual; + dpsmode_current.ui.draw(&dpsmode_current.ui); } - if (dpsmode_current.ui.has_focus) { - /** If the current setting has focus, make sure we're displaying - * the desired setting and not the current output value. */ - if (dpsmode_current.value != saved_i) { - dpsmode_current.value = saved_i; - dpsmode_current.ui.draw(&dpsmode_current.ui); - } - } else { - /** No focus, update display if necessary */ - if (dpsmode_current.value != cout_actual) { - dpsmode_current.value = cout_actual; - dpsmode_current.color = COLOR_AMPERAGE; - dpsmode_current.ui.draw(&dpsmode_current.ui); - } + // update the power with desired value if focused + if (dpsmode_power.ui.has_focus && dpsmode_power.value != saved_i) { + dpsmode_power.value = saved_p; + dpsmode_power.ui.draw(&dpsmode_power.ui); + } + // Update with actual output power if not in focus + if ( ! dpsmode_power.ui.has_focus && dpsmode_power.value != power_actual) { + dpsmode_power.value = power_actual; + dpsmode_power.ui.draw(&dpsmode_power.ui); } /** Determine if we are in CV or CC mode and display it */ @@ -495,68 +532,127 @@ static void dpsmode_tick(void) if (cout_diff < vout_diff) { // current diff smaller than voltage diff (constant current) - if (dpsmode_graphics & CUR_GFX_CV) { - clear_cvbar(); - } - - if ((dpsmode_graphics & CUR_GFX_CC) == 0) { - dpsmode_graphics |= CUR_GFX_CC; - - // mine, draw cc bar beside current - tft_blit((uint16_t*) gfx_ccbar, - GFX_CCBAR_WIDTH, GFX_CCBAR_HEIGHT, - TFT_WIDTH - GFX_CCBAR_WIDTH, - YPOS_CURRENT + FONT_METER_LARGE_MAX_GLYPH_HEIGHT - GFX_CCBAR_HEIGHT ); - } + dpsmode_graphics |= CUR_GFX_CC; + dpsmode_graphics &= ~CUR_GFX_CV; } else { // current diff larger than voltage diff (constant voltage) + dpsmode_graphics |= CUR_GFX_CV; + dpsmode_graphics &= ~CUR_GFX_CC; + } - if (dpsmode_graphics & CUR_GFX_CC) { - clear_ccbar(); - } - if ((dpsmode_graphics & CUR_GFX_CV) == 0) { - dpsmode_graphics |= CUR_GFX_CV; + // OPP / PP warnings + // over power limits (if defined, or absolute maximum of this device) + if ( (saved_p > 0 && power_actual >= saved_p) || power_actual >= dpsmode_power.max) { + // show opp warning + dpsmode_graphics |= CUR_GFX_OPP; + dpsmode_graphics &= ~CUR_GFX_PP; - // mine, draw cv bar beside voltage - tft_blit((uint16_t*) gfx_cvbar, - GFX_CVBAR_WIDTH, GFX_CVBAR_HEIGHT, - TFT_WIDTH - GFX_CVBAR_WIDTH, - YPOS_VOLTAGE + FONT_METER_LARGE_MAX_GLYPH_HEIGHT - GFX_CVBAR_HEIGHT ); - } + // power off + dpsmode_enable(false); + opendps_update_power_status(false); + } + + // over 80% power (if defined, or absolute maximum), show warning + else if ( (saved_p > 0 && power_actual >= (saved_p * 0.8f)) || power_actual >= (dpsmode_power.max * 0.8f) ) { + // show opp warning + dpsmode_graphics |= CUR_GFX_PP; + dpsmode_graphics &= ~CUR_GFX_OPP; + + } else { + // no pp or opp warning + dpsmode_graphics &= ~CUR_GFX_PP; + dpsmode_graphics &= ~CUR_GFX_OPP; } } + + // draw bars on right + draw_bars(); } -static void clear_bars() { - /** Ensure the CC or CV logo has been cleared from the screen */ +/** + * @brief draws bars on the right hand side of the screen. + * These include the CV / CC / PP and OPP warnings + */ +static void draw_bars() { + // TODO: Keep track of what's drawn and what's not to optimze draws + + // draw cc bar + if (dpsmode_graphics & CUR_GFX_CC) { + tft_blit((uint16_t*) gfx_ccbar, + GFX_CCBAR_WIDTH, GFX_CCBAR_HEIGHT, + TFT_WIDTH - GFX_CCBAR_WIDTH, + YPOS_CURRENT + FONT_METER_LARGE_MAX_GLYPH_HEIGHT - GFX_CCBAR_HEIGHT ); + } else { + // clear cc bar + tft_fill(TFT_WIDTH - GFX_CCBAR_WIDTH, YPOS_CURRENT + FONT_METER_LARGE_MAX_GLYPH_HEIGHT - GFX_CCBAR_HEIGHT, + GFX_CCBAR_WIDTH, GFX_CCBAR_HEIGHT, + BLACK); + } + + // draw cv bar if (dpsmode_graphics & CUR_GFX_CV) { - clear_cvbar(); + tft_blit((uint16_t*) gfx_cvbar, + GFX_CVBAR_WIDTH, GFX_CVBAR_HEIGHT, + TFT_WIDTH - GFX_CVBAR_WIDTH, + YPOS_VOLTAGE + FONT_METER_LARGE_MAX_GLYPH_HEIGHT - GFX_CVBAR_HEIGHT ); + } else { + tft_fill(TFT_WIDTH - GFX_CVBAR_WIDTH, YPOS_VOLTAGE + FONT_METER_LARGE_MAX_GLYPH_HEIGHT - GFX_CVBAR_HEIGHT, + GFX_CVBAR_WIDTH, GFX_CVBAR_HEIGHT, + BLACK); } - if (dpsmode_graphics & CUR_GFX_CC) { - clear_ccbar(); + + + // draw opp + if (dpsmode_graphics & CUR_GFX_OPP) { + // blink the opp warning + if ((get_ticks() >> 10) & 1) + tft_blit((uint16_t*) gfx_oppbar, + GFX_OPPBAR_WIDTH, GFX_OPPBAR_HEIGHT, + TFT_WIDTH - GFX_OPPBAR_WIDTH, + YPOS_POWER + FONT_METER_LARGE_MAX_GLYPH_HEIGHT - GFX_OPPBAR_HEIGHT ); + else + tft_fill(TFT_WIDTH - GFX_PPBAR_WIDTH, YPOS_POWER + FONT_METER_LARGE_MAX_GLYPH_HEIGHT - GFX_PPBAR_HEIGHT, + GFX_PPBAR_WIDTH, GFX_PPBAR_HEIGHT, + BLACK); + } + // draw pp + else if (dpsmode_graphics & CUR_GFX_PP) { + tft_blit((uint16_t*) gfx_ppbar, + GFX_PPBAR_WIDTH, GFX_PPBAR_HEIGHT, + TFT_WIDTH - GFX_PPBAR_WIDTH, + YPOS_POWER + FONT_METER_LARGE_MAX_GLYPH_HEIGHT - GFX_PPBAR_HEIGHT ); + // or clear + } else { + tft_fill(TFT_WIDTH - GFX_PPBAR_WIDTH, YPOS_POWER + FONT_METER_LARGE_MAX_GLYPH_HEIGHT - GFX_PPBAR_HEIGHT, + GFX_PPBAR_WIDTH, GFX_PPBAR_HEIGHT, + BLACK); } - dpsmode_graphics = CUR_GFX_NOT_DRAWN; -} -static void clear_ccbar() { - // clear cc bar - tft_fill(TFT_WIDTH - GFX_CCBAR_WIDTH, YPOS_CURRENT + FONT_METER_LARGE_MAX_GLYPH_HEIGHT - GFX_CCBAR_HEIGHT, - GFX_CCBAR_WIDTH, GFX_CCBAR_HEIGHT, - BLACK); - dpsmode_graphics = dpsmode_graphics & ~CUR_GFX_CC; + } -static void clear_cvbar() { - // clear cv bar - tft_fill(TFT_WIDTH - GFX_CVBAR_WIDTH, YPOS_VOLTAGE + FONT_METER_LARGE_MAX_GLYPH_HEIGHT - GFX_CVBAR_HEIGHT, - GFX_CVBAR_WIDTH, GFX_CVBAR_HEIGHT, - BLACK); +/* + * @brief Clears bars on the right hand side + * + * @param all if true will clear all bars. Otherwise, only cc/cv/pp + */ +static void clear_bars(bool all) { + if (all) { + // clears opp as well as the others + dpsmode_graphics = CUR_GFX_NOT_DRAWN; + return; + } + + // clear just cc/cv/pp otherwise + dpsmode_graphics = dpsmode_graphics & ~CUR_GFX_CC; dpsmode_graphics = dpsmode_graphics & ~CUR_GFX_CV; + dpsmode_graphics = dpsmode_graphics & ~CUR_GFX_PP; } + /** * @brief Initialise the DPS Mode module and add its screen to the UI * @@ -566,6 +662,8 @@ void func_dpsmode_init(uui_t *ui) { dpsmode_voltage.value = 0; /** read from past */ dpsmode_current.value = 0; /** read from past */ + dpsmode_power.value = 0; /** read from past */ + uint16_t i_out_raw, v_in_raw, v_out_raw; hw_get_adc_values(&i_out_raw, &v_in_raw, &v_out_raw); (void) i_out_raw; @@ -578,6 +676,9 @@ void func_dpsmode_init(uui_t *ui) accidentally cranking up the setting 10V or more */ dpsmode_voltage.cur_digit = 2; + // set the maximum power based on max voltage and max amps + dpsmode_power.max = dpsmode_voltage.max * CONFIG_DPS_MAX_CURRENT; + number_init(&dpsmode_current); number_init(&dpsmode_power); diff --git a/opendps/gfx-oppbar.c b/opendps/gfx-oppbar.c new file mode 100644 index 00000000..f26f4d71 --- /dev/null +++ b/opendps/gfx-oppbar.c @@ -0,0 +1,38 @@ +/** Gfx generated from gfx/png/oppbar.png */ + +#include "gfx-oppbar.h" + +const uint8_t gfx_oppbar[500] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, + 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x06, 0xdf, + 0x06, 0xdf, 0x06, 0xdf, 0x06, 0xdf, 0x06, 0xdf, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, + 0x00, 0x1f, 0x06, 0xdf, 0x06, 0xdf, 0x06, 0x9f, 0x06, 0xdf, 0x06, 0xdf, 0x00, 0x00, 0x00, 0x1f, + 0x00, 0x1f, 0x00, 0x1f, 0x06, 0xdf, 0x06, 0xdf, 0x06, 0xdf, 0x06, 0x9f, 0x06, 0xdf, 0x06, 0xdf, + 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x06, 0xdf, 0x06, 0xdf, 0x06, 0xdf, 0x06, 0x9f, + 0x06, 0xdf, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x06, 0xdf, 0x06, 0xdf, + 0x06, 0x9f, 0x06, 0xdf, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x06, 0xdf, + 0x06, 0xdf, 0x06, 0xdf, 0x06, 0xdf, 0x06, 0xdf, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, + 0x00, 0x1f, 0x06, 0xdf, 0x06, 0xdf, 0x06, 0xdf, 0x06, 0xdf, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, + 0x00, 0x00, 0x00, 0x1f, 0x06, 0xdf, 0x06, 0xdf, 0x06, 0xdf, 0x06, 0xdf, 0x00, 0x1f, 0x00, 0x1f, + 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x06, 0xdf, 0x06, 0xdf, 0x06, 0xdf, 0x06, 0xdf, + 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x06, 0xdf, 0x06, 0xdf, + 0x06, 0x9f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, + 0x06, 0xdf, 0x06, 0xdf, 0x06, 0xdf, 0x06, 0xdf, 0x06, 0xdf, 0x06, 0xdf, 0x06, 0x9f, 0x00, 0x1f, + 0x00, 0x00, 0x00, 0x1f, 0x06, 0xdf, 0x06, 0xdf, 0x06, 0xdf, 0x06, 0xdf, 0x06, 0xdf, 0x06, 0xdf, + 0x06, 0xdf, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, + 0x06, 0xdf, 0x06, 0xdf, 0x06, 0xdf, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, + 0x00, 0x1f, 0x00, 0x1f, 0x06, 0xdf, 0x06, 0xdf, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, + 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x06, 0xdf, 0x06, 0xdf, 0x06, 0xdf, 0x00, 0x1f, 0x00, 0x1f, + 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x06, 0xdf, 0x06, 0xdf, 0x00, 0x1f, + 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x06, 0xdf, 0x06, 0xdf, + 0x06, 0xdf, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, + 0x06, 0xdf, 0x06, 0xdf, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, + 0x00, 0x1f, 0x06, 0xdf, 0x06, 0xdf, 0x06, 0xdf, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, + 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x06, 0xdf, 0x06, 0xdf, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, + 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x06, 0xdf, 0x00, 0x1f, 0x00, 0x1f, + 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x06, 0xdf, 0x00, 0x1f, + 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, + 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x1f, + 0x00, 0x1f, 0x00, 0x1f +}; \ No newline at end of file diff --git a/opendps/gfx-oppbar.h b/opendps/gfx-oppbar.h new file mode 100644 index 00000000..6cdf77ff --- /dev/null +++ b/opendps/gfx-oppbar.h @@ -0,0 +1,13 @@ +/** Gfx generated from gfx/png/oppbar.png */ + +#ifndef __GFX_OPPBAR_H__ +#define __GFX_OPPBAR_H__ + +#include + +#define GFX_OPPBAR_HEIGHT (25) +#define GFX_OPPBAR_WIDTH (10) + +extern const uint8_t gfx_oppbar[500]; + +#endif // __GFX_OPPBAR_H__ \ No newline at end of file diff --git a/opendps/gfx-ppbar.c b/opendps/gfx-ppbar.c new file mode 100644 index 00000000..69a87ddc --- /dev/null +++ b/opendps/gfx-ppbar.c @@ -0,0 +1,38 @@ +/** Gfx generated from gfx/png/ppbar.png */ + +#include "gfx-ppbar.h" + +const uint8_t gfx_ppbar[500] = { + 0x00, 0x00, 0x00, 0x00, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, + 0x05, 0xff, 0x05, 0xff, 0x00, 0x00, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, + 0x05, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xff, + 0x05, 0xff, 0x05, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, + 0x00, 0x00, 0x05, 0xff, 0x00, 0x00, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x41, 0x00, 0x00, 0x05, 0xff, 0x05, 0xff, 0x00, 0x00, 0x05, 0xff, 0x05, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xff, 0x05, 0xff, 0x00, 0x00, 0x05, 0xff, + 0x05, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, + 0x00, 0x00, 0x05, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xff, 0x05, 0xff, + 0x05, 0xff, 0x05, 0xff, 0x00, 0x00, 0x05, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x00, 0x00, 0x05, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x41, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x00, 0x00, 0x05, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x05, 0xff, + 0x00, 0x00, 0x05, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x05, 0xff, 0x00, 0x00, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xff, 0x00, 0x00, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, + 0x05, 0xff, 0x05, 0xff, 0x00, 0x00, 0x00, 0x00, 0x05, 0xff, 0x05, 0xff, 0x00, 0x00, 0x05, 0xff, + 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xff, 0x05, 0xff, + 0x00, 0x00, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x00, 0x00, 0x00, 0x00, 0x05, 0xff, + 0x05, 0xff, 0x05, 0xff, 0x00, 0x00, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x00, 0x00, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x00, 0x00, 0x05, 0xff, + 0x05, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, + 0x00, 0x00, 0x05, 0xff, 0x05, 0xff, 0x00, 0x00, 0x00, 0x00, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, + 0x05, 0xff, 0x05, 0xff, 0x00, 0x00, 0x05, 0xff, 0x05, 0xff, 0x00, 0x00, 0x05, 0xff, 0x05, 0xff, + 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x00, 0x00, 0x05, 0xff, 0x00, 0x00, 0x05, 0xff, + 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x00, 0x00, 0x05, 0xff, + 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, 0x05, 0xff, + 0x05, 0xff, 0x05, 0xff +}; \ No newline at end of file diff --git a/opendps/gfx-ppbar.h b/opendps/gfx-ppbar.h new file mode 100644 index 00000000..eb6ef15d --- /dev/null +++ b/opendps/gfx-ppbar.h @@ -0,0 +1,13 @@ +/** Gfx generated from gfx/png/ppbar.png */ + +#ifndef __GFX_PPBAR_H__ +#define __GFX_PPBAR_H__ + +#include + +#define GFX_PPBAR_HEIGHT (25) +#define GFX_PPBAR_WIDTH (10) + +extern const uint8_t gfx_ppbar[500]; + +#endif // __GFX_PPBAR_H__ \ No newline at end of file diff --git a/opendps/gfx/png/oppbar.png b/opendps/gfx/png/oppbar.png new file mode 100644 index 0000000000000000000000000000000000000000..eed4facc02044466c0edc47fffa89b0b19cab5e3 GIT binary patch literal 1117 zcmbVLPe>F|7@z(KA{t?*5@Hyk44S_?v+fMLiSF#?qN}nlD0ryZd2e;voq6NT(_N(? z3XKjDbP1#^Iz$mhm*^lQm6r|$bxXuZI@GB{hYAdPd?OcgL~r|4)|BMxkc4Z3U>9bYTQm`%SLv4d-#p*JD85MwH$2Gf0X9C?sd zxG-yqvO>42oEQ$ts(O-^1Tn%35nc?jVpx*}O_J!Xhau5Ckk>MLaw`@&#h4L{U5)2U zr4m;PamX9yMO9UKLE92&zhhA6G1V7uw` zwqwWNDikRhUp8D`sh2JMo~xRm<=7A(qjzy!vPCu5!no>Vm`;VN+8GP1X*SyGB8;Q$O_0A`3O)z)z40R zNm1h=sUw__60#^J)JRg*JCdR(CS@_9gj%cIl;dN=F<~{fMPhGpm0h`7+=B*2UKXKZ zbqe}M5Jvt8a_M+H=(d)k%_4|j`X3n_Z zHx|F}k!GgxL04hrAotRlWxLZ;kHfFQi#-d{(%swa%8kY)MV%{-U;FfV`uJ3hfaIBP zV18|N_Rh~zb9D9A!_m3a^ZWH5dz-p8TBnB&JyqV#*Ia)4<6dIiYbi&eyU<&G>IJyj5C~Duh znI6Cc$u8AE7N`3du3$NYO;Iha1xGiAA*M5M$h0HO=V#9u+5{1%KbRDfP7LPE&IuRx zO?0P?iD5$lOzSDSrJxcA7Q{MTutsc8Eku}-UzOPYHP6r`2p*0wWl;mk9y*3xNC&wP zYlw1?ZdN!k6p$6AiIxO0%nM;&46tHIl?7Fj=&gq#(Oi&KQ(F60EOLr4IgA~Z=kxhI zmk)5r9pXhrQFuY(C5a^n)+^drFR-@PQ1PHa&u~o#o5-epk9r1;;Rr*NmQ%2tWOCcF z?QIo`l#DOv4li;7Z&`j`CA5cA@Q;ig(O$afKt2UMH0BzlAK8WqnbdCgKt7PDQBS)j zX^K9gA!E#fHcn^}hWz1x3DmG`1QaowVVfn8VKag(vtbz+tOVpB$mrQH2!e{Ao%oU_ zH^($ZiA!-=6yr)%jK-s(cCoE3E(PLYp~6kr9@cFGR$`kZ_7*q1D_4!VP{+tkBQ#Q( zf}R}0$jc#zj>Y`0D|BPOX#=S}9Gf!8noTCOwshg$?OVNdSA?oq$A`J;{O0=m z<;C;o7FVkG-&tEo7Q0?6KU3>B-hxX@cORJG$>XVwvsH3&bs_p?`OIWBdiG-O)AyA} zgHLCfAC0{i>!*f)y*&6WI72sV&fgqtYUN%%ES?-asx5t8J$x@Wa~Wv&aowH+RQ2NV Us~_LY&-&}0h<9rX(F@mp1HjdA0{{R3 literal 0 HcmV?d00001 From 4f8411b56eef2967642e0ec8d5c8be8868ae08aa Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 29 Sep 2019 15:25:33 -0600 Subject: [PATCH 027/175] Removed draw calls on enable call to prevent artifacts on next screen While the deactivate callback clears the tft display, because of uui.c's way of changing screens, another call to enable(false) is called. Any draws in enable() will cause artifacts on the next screen. All draws should be done inside the tick callback instead. --- opendps/func_dpsmode.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index a1b8aa51..3b0558db 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -307,13 +307,8 @@ static void dpsmode_enable(bool enabled) /** Make sure we're displaying the settings and not the current * measurements when the power output is switched off */ dpsmode_voltage.value = saved_v; - dpsmode_voltage.ui.draw(&dpsmode_voltage.ui); - dpsmode_current.value = saved_i; - dpsmode_current.ui.draw(&dpsmode_current.ui); - dpsmode_power.value = saved_p; - dpsmode_power.ui.draw(&dpsmode_power.ui); } } @@ -361,7 +356,7 @@ static bool event(uui_t *ui, event_t event) { if (single_edit_mode) { single_edit_mode = false; - // toggle focus on anything that is in focus + // toggle focus on anything that is in focus (to unfocus) if (dpsmode_voltage.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_voltage); if (dpsmode_current.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_current); return true; @@ -565,6 +560,12 @@ static void dpsmode_tick(void) dpsmode_graphics &= ~CUR_GFX_PP; dpsmode_graphics &= ~CUR_GFX_OPP; } + + // No power. just redraw numbers + } else { + dpsmode_voltage.ui.draw(&dpsmode_voltage.ui); + dpsmode_current.ui.draw(&dpsmode_current.ui); + dpsmode_power.ui.draw(&dpsmode_power.ui); } // draw bars on right From a3bf6fceb6604826867f7fb7714071c840e3ee6b Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 29 Sep 2019 15:58:36 -0600 Subject: [PATCH 028/175] Added rot_left/right_m1/m2 events --- opendps/event.h | 32 ++++++++++++++++++-------------- opendps/hw.c | 8 ++++++++ opendps/uui.c | 7 +++++++ 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/opendps/event.h b/opendps/event.h index f65f2b60..1cc33d17 100644 --- a/opendps/event.h +++ b/opendps/event.h @@ -26,20 +26,24 @@ #define __EVENT_H__ typedef enum { - event_none = 0, - event_button_m1, - event_button_m2, - event_buttom_m1_and_m2, - event_button_sel, - event_button_enable, - event_rot_left, - event_rot_right, - event_rot_left_set, - event_rot_right_set, - event_rot_press, - event_uart_rx, - event_ocp, - event_ovp + event_none = 0, + event_button_m1, + event_button_m2, + event_buttom_m1_and_m2, + event_button_sel, + event_button_enable, + event_rot_left, + event_rot_right, + event_rot_left_set, + event_rot_right_set, + event_rot_left_m1, + event_rot_right_m1, + event_rot_left_m2, + event_rot_right_m2, + event_rot_press, + event_uart_rx, + event_ocp, + event_ovp } event_t; typedef enum { diff --git a/opendps/hw.c b/opendps/hw.c index 7c09421f..960889fa 100644 --- a/opendps/hw.c +++ b/opendps/hw.c @@ -967,6 +967,10 @@ void BUTTON_ROTARY_isr(void) set_skip = true; (void) longpress_end(); event_put(event_rot_left_set, press_short); + } else if (m1_pressed) { + event_put(event_rot_left_m1, press_short); + } else if (m2_pressed) { + event_put(event_rot_left_m2, press_short); } else { event_put(event_rot_left, press_short); } @@ -975,6 +979,10 @@ void BUTTON_ROTARY_isr(void) set_skip = true; (void) longpress_end(); event_put(event_rot_right_set, press_short); + } else if (m1_pressed) { + event_put(event_rot_right, press_short); + } else if (m2_pressed) { + event_put(event_rot_right, press_short); } else { event_put(event_rot_right, press_short); } diff --git a/opendps/uui.c b/opendps/uui.c index 05943b90..f7513670 100644 --- a/opendps/uui.c +++ b/opendps/uui.c @@ -174,6 +174,13 @@ void uui_handle_screen_event(uui_t *ui, event_t event) uui_next_screen(ui); break; + case event_rot_left_m1: + case event_rot_right_m1: + case event_rot_left_m2: + case event_rot_right_m2: + // do nothing + break; + case event_rot_left: case event_rot_right: case event_rot_press: From b68943c89d84960ba96ed6061b4aeb18c4765915 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 29 Sep 2019 17:58:45 -0600 Subject: [PATCH 029/175] Added time type fixed the rot m1/m2 event added 3rd row to display to test --- opendps/Makefile | 3 + opendps/func_dpsmode.c | 110 ++++++++++++--- opendps/hw.c | 6 +- opendps/opendps.c | 4 + opendps/uui.h | 2 + opendps/uui_number.c | 6 + opendps/uui_time.c | 308 +++++++++++++++++++++++++++++++++++++++++ opendps/uui_time.h | 55 ++++++++ 8 files changed, 473 insertions(+), 21 deletions(-) create mode 100644 opendps/uui_time.c create mode 100644 opendps/uui_time.h diff --git a/opendps/Makefile b/opendps/Makefile index f3956bff..1ba47608 100644 --- a/opendps/Makefile +++ b/opendps/Makefile @@ -81,6 +81,7 @@ OBJS = \ crc16.o \ uui.o \ uui_number.o \ + uui_time.o \ func_cv.o \ settings_calibration.o \ hw.o \ @@ -109,6 +110,8 @@ OBJS = \ gfx-oppbar.o \ gfx-padlock.o \ gfx-power.o \ + gfx-poweron.o \ + gfx-poweroff.o \ gfx-thermometer.o \ gfx-wifi.o \ opendps.o diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 3b0558db..c27f58d7 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -37,6 +37,7 @@ #include "func_dpsmode.h" #include "uui.h" #include "uui_number.h" +#include "uui_time.h" #include "dbg_printf.h" #include "mini-printf.h" #include "dps-model.h" @@ -55,6 +56,7 @@ static void dpsmode_enable(bool _enable); static void voltage_changed(ui_number_t *item); static void current_changed(ui_number_t *item); static void power_changed(ui_number_t *item); +static void timer_changed(ui_time_t *item); static void dpsmode_tick(void); static void activated(void); static void deactivated(void); @@ -77,6 +79,10 @@ static int32_t saved_v, saved_i, saved_p; static bool single_edit_mode; static bool select_mode; +// what is displayed on the 3rd row. +static int8_t third_row = 0; +ui_item_t *third_item; + enum { CUR_GFX_NOT_DRAWN = 0, CUR_GFX_CV = 1, @@ -146,6 +152,7 @@ ui_number_t dpsmode_current = { .changed = ¤t_changed, }; +// 3rd row items ui_number_t dpsmode_power = { { .type = ui_item_number, @@ -168,7 +175,46 @@ ui_number_t dpsmode_power = { .changed = &power_changed, }; +ui_number_t dpsmode_amphour = { + { + .type = ui_item_number, + .id = 13, + .x = XPOS_METER, + .y = YPOS_POWER, + .can_focus = false, + }, + .font_size = FONT_METER_LARGE, + .alignment = ui_text_right_aligned, + .pad_dot = false, + .color = WHITE, + .value = 0, + .min = 0, + .max = 0, + .si_prefix = si_milli, + .num_digits = 2, + .num_decimals = 2, + .unit = unit_amphour, + .changed = NULL, +}; +/* +ui_time_t dpsmode_timer = { + { + .type = ui_item_time, + .id = 14, + .x = XPOS_METER, + .y = YPOS_POWER, + .can_focus = false, + }, + .font_size = FONT_METER_LARGE, + .alignment = ui_text_right_aligned, + .pad_dot = false, + .color = WHITE, + .value = 0, + .changed = &timer_changed, +}; + +*/ /* This is the screen definition */ ui_screen_t dpsmode_screen = { @@ -187,7 +233,13 @@ ui_screen_t dpsmode_screen = { .tick = &dpsmode_tick, .set_parameter = &set_parameter, .get_parameter = &get_parameter, - .num_items = 3, + .num_items = 4, + .items = { + (ui_item_t*) &dpsmode_voltage, + (ui_item_t*) &dpsmode_current, + (ui_item_t*) &dpsmode_power, + (ui_item_t*) &dpsmode_amphour, + }, .parameters = { { .name = "voltage", @@ -202,16 +254,11 @@ ui_screen_t dpsmode_screen = { { .name = "power", .unit = unit_watt, - .prefix = si_milli + .prefix = si_milli // or micro? }, { .name = {'\0'} /** Terminator */ }, - }, - .items = { - (ui_item_t*) &dpsmode_voltage, - (ui_item_t*) &dpsmode_current, - (ui_item_t*) &dpsmode_power } }; @@ -346,11 +393,15 @@ static void power_changed(ui_number_t *item) } +static void timer_changed(ui_time_t *item) { + // do nothing yet... + // TODO: Implement a timer +} + + static bool event(uui_t *ui, event_t event) { switch(event) { - case event_button_m1: - case event_button_m2: case event_button_sel: if (single_edit_mode) { @@ -361,6 +412,24 @@ static bool event(uui_t *ui, event_t event) { if (dpsmode_current.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_current); return true; } + break; + + case event_button_m1: + case event_button_m2: + case event_rot_left_m1: + case event_rot_right_m1: + // change what's visible on the 3rd row + { + ui_screen_t *screen = ui->screens[ui->cur_screen]; + + // rotate around the 3rd row objects (skip the 1st two) + third_row = ++third_row % (screen->num_items - 2); + third_item = screen->items[third_row]; + + dpsmode_graphics |= CUR_GFX_PP; + + } + break; default: break; @@ -491,34 +560,28 @@ static void dpsmode_tick(void) // Voltage setting has focus, update with the desired value and not output value if (dpsmode_voltage.ui.has_focus && dpsmode_voltage.value != saved_v) { dpsmode_voltage.value = saved_v; - dpsmode_voltage.ui.draw(&dpsmode_voltage.ui); } // Voltage setting is not focused, update with actual output voltage if ( ! dpsmode_voltage.ui.has_focus && dpsmode_voltage.value != vout_actual) { dpsmode_voltage.value = vout_actual; - dpsmode_voltage.ui.draw(&dpsmode_voltage.ui); } // Same for amperage. update with desired value if focused if (dpsmode_current.ui.has_focus && dpsmode_current.value != saved_i) { dpsmode_current.value = saved_i; - dpsmode_current.ui.draw(&dpsmode_current.ui); } // Update with actual output voltage if not in focus if ( ! dpsmode_current.ui.has_focus && dpsmode_current.value != cout_actual) { dpsmode_current.value = cout_actual; - dpsmode_current.ui.draw(&dpsmode_current.ui); } // update the power with desired value if focused if (dpsmode_power.ui.has_focus && dpsmode_power.value != saved_i) { dpsmode_power.value = saved_p; - dpsmode_power.ui.draw(&dpsmode_power.ui); } // Update with actual output power if not in focus if ( ! dpsmode_power.ui.has_focus && dpsmode_power.value != power_actual) { dpsmode_power.value = power_actual; - dpsmode_power.ui.draw(&dpsmode_power.ui); } /** Determine if we are in CV or CC mode and display it */ @@ -561,11 +624,18 @@ static void dpsmode_tick(void) dpsmode_graphics &= ~CUR_GFX_OPP; } - // No power. just redraw numbers + } + + + // redraw + dpsmode_voltage.ui.draw(&dpsmode_voltage.ui); + dpsmode_current.ui.draw(&dpsmode_current.ui); + + // draw 3rd row item... + if ( third_item ) { + ((ui_number_t *)third_item)->ui.draw(& ((ui_number_t *)third_item)->ui); } else { - dpsmode_voltage.ui.draw(&dpsmode_voltage.ui); - dpsmode_current.ui.draw(&dpsmode_current.ui); - dpsmode_power.ui.draw(&dpsmode_power.ui); + // dpsmode_power.ui.draw(&dpsmode_power.ui); } // draw bars on right @@ -683,5 +753,7 @@ void func_dpsmode_init(uui_t *ui) number_init(&dpsmode_current); number_init(&dpsmode_power); + number_init(&dpsmode_amphour); + uui_add_screen(ui, &dpsmode_screen); } diff --git a/opendps/hw.c b/opendps/hw.c index 960889fa..9284565d 100644 --- a/opendps/hw.c +++ b/opendps/hw.c @@ -866,8 +866,10 @@ void BUTTON_M1_isr(void) if (falling) { if (is_bouncing()) return; m1_pressed = true; + if (m2_pressed) m1_and_m2_pressed = true; + exti_set_trigger(BUTTON_M1_EXTI, EXTI_TRIGGER_RISING); } else { m1_pressed = false; @@ -980,9 +982,9 @@ void BUTTON_ROTARY_isr(void) (void) longpress_end(); event_put(event_rot_right_set, press_short); } else if (m1_pressed) { - event_put(event_rot_right, press_short); + event_put(event_rot_right_m1, press_short); } else if (m2_pressed) { - event_put(event_rot_right, press_short); + event_put(event_rot_right_m2, press_short); } else { event_put(event_rot_right, press_short); } diff --git a/opendps/opendps.c b/opendps/opendps.c index 23ea9a7f..408f0db4 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -543,6 +543,10 @@ static void ui_handle_event(event_t event, uint8_t data) case event_rot_right: case event_rot_left_set: case event_rot_right_set: + case event_rot_left_m1: + case event_rot_right_m1: + case event_rot_left_m2: + case event_rot_right_m2: uui_handle_screen_event(current_ui, event); uui_refresh(current_ui, false); break; diff --git a/opendps/uui.h b/opendps/uui.h index 979dc939..d81280ac 100644 --- a/opendps/uui.h +++ b/opendps/uui.h @@ -64,6 +64,7 @@ typedef enum { unit_ampere, unit_volt, unit_watt, + unit_amphour, unit_second, unit_hertz, unit_furlong, @@ -91,6 +92,7 @@ typedef enum { typedef enum { ui_item_number, /** A control for setting a value (ui_number_t) */ ui_item_icon, /** A control for showing a icon (ui_icon_t) */ + ui_item_time, /** A control for showing time (ui_time_t) */ ui_item_last = 0xff } ui_item_type_t; diff --git a/opendps/uui_number.c b/opendps/uui_number.c index 5e0ad547..c6576135 100644 --- a/opendps/uui_number.c +++ b/opendps/uui_number.c @@ -166,6 +166,9 @@ static uint32_t number_draw_width(ui_item_t *_item) case unit_hertz: total_width += 2*FONT_FULL_SMALL_MAX_GLYPH_WIDTH; break; + case unit_amphour: + total_width += 3*FONT_FULL_SMALL_MAX_GLYPH_WIDTH; + break; default: assert(0); } @@ -308,6 +311,9 @@ static void number_draw(ui_item_t *_item) case unit_hertz: tft_puts(FONT_FULL_SMALL, "Hz", xpos, _item->y + h, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 2, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, color, false); break; + case unit_amphour: + tft_puts(FONT_FULL_SMALL, "mAh", xpos, _item->y + h, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 3, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, color, false); + break; case unit_watt: tft_putch(item->font_size, 'W', xpos, _item->y, max_w, h, color, false); break; diff --git a/opendps/uui_time.c b/opendps/uui_time.c new file mode 100644 index 00000000..522cb463 --- /dev/null +++ b/opendps/uui_time.c @@ -0,0 +1,308 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include "my_assert.h" +#include "uui_time.h" +#include "tft.h" +#include "ili9163c.h" +#include "font-full_small.h" +#include "font-meter_small.h" +#include "font-meter_medium.h" +#include "font-meter_large.h" + +// HH:MM:SS == 6 +#define DIGITS 6 + +// 99:59:59 == 359999 seconds +#define MAX_TIME 359999 + +#define MAX(a,b) (((a)>(b))?(a):(b)) + +static uint32_t digit_scale(ui_time_t *item, uint32_t i) { + if (item->cur_digit == 0 || item->cur_digit == 1) { + // seconds + return i; + } + if (item->cur_digit == 2 || item->cur_digit == 3) { + // minutes + return i * 60; + } + + // hours + return i * 3600; +} + +/** + * @brief Handle event and update our state and value accordingly + * + * @param _item The item + * @param[in] event The event + */ +static void number_got_event(ui_item_t *_item, event_t event) +{ + assert(_item); + + ui_time_t *item = (ui_time_t*) _item; + bool value_changed = false; + + switch(event) { + case event_rot_left: + item->value -= digit_scale(item, 1); + if (item->value < 0) item->value = 0; + + _item->needs_redraw = true; + value_changed = true; + + break; + + case event_rot_right: + item->value += digit_scale(item, 1); + if (item->value > MAX_TIME) item->value = MAX_TIME; + + _item->needs_redraw = true; + value_changed = true; + + break; + + case event_rot_press: + if (item->cur_digit == 0) { + item->cur_digit = 5; // item->num_digits + item->num_decimals - 1; + } else { + item->cur_digit--; + } + + _item->needs_redraw = true; + + break; + + default: + assert(0); + } + + if (value_changed && item->changed) { + item->changed(item); + } +} + +/** + * @brief Get the width of the number if it were to be drawn + * + * @param _item The item + * + * @return The width in pixels + */ +static uint32_t number_draw_width(ui_item_t *_item) +{ + ui_time_t *item = (ui_time_t*) _item; + uint32_t digit_w, dot_width, spacing; + uint32_t total_width = 0; + + switch (item->font_size) { + case FONT_FULL_SMALL: + digit_w = FONT_FULL_SMALL_MAX_DIGIT_WIDTH; + dot_width = item->pad_dot ? MAX(FONT_FULL_SMALL_MAX_DIGIT_WIDTH, FONT_FULL_SMALL_DOT_WIDTH) : FONT_FULL_SMALL_DOT_WIDTH; + spacing = FONT_FULL_SMALL_SPACING; + break; + case FONT_METER_SMALL: + digit_w = FONT_METER_SMALL_MAX_DIGIT_WIDTH; + dot_width = item->pad_dot ? MAX(FONT_METER_SMALL_MAX_DIGIT_WIDTH, FONT_METER_SMALL_DOT_WIDTH) : FONT_METER_SMALL_DOT_WIDTH; + spacing = FONT_METER_SMALL_SPACING; + break; + case FONT_METER_MEDIUM: + digit_w = FONT_METER_MEDIUM_MAX_DIGIT_WIDTH; + dot_width = item->pad_dot ? MAX(FONT_METER_MEDIUM_MAX_DIGIT_WIDTH, FONT_METER_MEDIUM_DOT_WIDTH) : FONT_METER_MEDIUM_DOT_WIDTH; + spacing = FONT_METER_MEDIUM_SPACING; + break; + case FONT_METER_LARGE: + digit_w = FONT_METER_LARGE_MAX_DIGIT_WIDTH; + dot_width = item->pad_dot ? MAX(FONT_METER_LARGE_MAX_DIGIT_WIDTH, FONT_METER_LARGE_DOT_WIDTH) : FONT_METER_LARGE_DOT_WIDTH; + spacing = FONT_METER_LARGE_SPACING; + break; + default: + /* Can't do anything if the wrong font size was supplied. */ + assert(0); + } + + /** Start printing from left to right */ + + // total digits HH:MM:SS = 6, plus spacing, plus 2 : + total_width += DIGITS * (digit_w + spacing); + total_width += 2 * (dot_width + spacing); + + return total_width; +} + +/** + * @brief Getter of our value + * + * @param _item The item + * + * @return value? + */ +static uint32_t number_get_value(ui_item_t *_item) +{ + assert(_item); + ui_time_t *item = (ui_time_t*) _item; + return item->value; +} + +static void number_draw(ui_item_t *_item) +{ + ui_time_t *item = (ui_time_t*) _item; + uint32_t digit_w, h, dot_width, spacing; + + switch (item->font_size) { + case FONT_FULL_SMALL: + digit_w = FONT_FULL_SMALL_MAX_DIGIT_WIDTH; + h = FONT_FULL_SMALL_MAX_GLYPH_HEIGHT; + dot_width = item->pad_dot ? MAX(FONT_FULL_SMALL_MAX_DIGIT_WIDTH, FONT_FULL_SMALL_DOT_WIDTH) : FONT_FULL_SMALL_DOT_WIDTH; + spacing = FONT_FULL_SMALL_SPACING; + break; + case FONT_METER_SMALL: + digit_w = FONT_METER_SMALL_MAX_DIGIT_WIDTH; + h = FONT_METER_SMALL_MAX_GLYPH_HEIGHT; + dot_width = item->pad_dot ? MAX(FONT_METER_SMALL_MAX_DIGIT_WIDTH, FONT_METER_SMALL_DOT_WIDTH) : FONT_METER_SMALL_DOT_WIDTH; + spacing = FONT_METER_SMALL_SPACING; + break; + case FONT_METER_MEDIUM: + digit_w = FONT_METER_MEDIUM_MAX_DIGIT_WIDTH; + h = FONT_METER_MEDIUM_MAX_GLYPH_HEIGHT; + dot_width = item->pad_dot ? MAX(FONT_METER_MEDIUM_MAX_DIGIT_WIDTH, FONT_METER_MEDIUM_DOT_WIDTH) : FONT_METER_MEDIUM_DOT_WIDTH; + spacing = FONT_METER_MEDIUM_SPACING; + break; + case FONT_METER_LARGE: + digit_w = FONT_METER_LARGE_MAX_DIGIT_WIDTH; + h = FONT_METER_LARGE_MAX_GLYPH_HEIGHT; + dot_width = item->pad_dot ? MAX(FONT_METER_LARGE_MAX_DIGIT_WIDTH, FONT_METER_LARGE_DOT_WIDTH) : FONT_METER_LARGE_DOT_WIDTH; + spacing = FONT_METER_LARGE_SPACING; + break; + default: + /* Can't do anything if the wrong font size was supplied. Drop out for safety. */ + return; + } + + uint32_t xpos = _item->x; + uint16_t color = item->color; + uint32_t cur_digit = DIGITS - 1; // Start at left most digit of HH:MM:SS + + /** Adjust drawing position if right aligned */ + if (item->alignment == ui_text_right_aligned) + xpos -= number_draw_width(_item); + + + uint8_t hours = item->value / 3600; + uint8_t minutes = (item->value / 60) % 60; + uint8_t seconds = item->value % 60; + uint8_t digit = 0; + bool highlight = false; + + // HH + digit = hours / 10; + highlight =_item->has_focus && item->cur_digit == DIGITS - 1; + + tft_putch(item->font_size, '0' + digit, + xpos, _item->y, + digit_w, h, + color, highlight); + cur_digit--; + xpos += digit_w + spacing; + + digit = hours % 10; + highlight =_item->has_focus && item->cur_digit == DIGITS - 2; + tft_putch(item->font_size, '0' + digit, + xpos, _item->y, + digit_w, h, + color, highlight); + cur_digit--; + xpos += digit_w + spacing; + + // : + tft_putch(item->font_size, '.', xpos, _item->y, dot_width, h, color, false); + xpos += dot_width + spacing; + + // MM + digit = minutes / 10; + highlight =_item->has_focus && item->cur_digit == DIGITS - 3; + tft_putch(item->font_size, '0' + digit, + xpos, _item->y, + digit_w, h, + color, highlight); + cur_digit--; + xpos += digit_w + spacing; + + digit = minutes % 10; + highlight =_item->has_focus && item->cur_digit == DIGITS - 4; + tft_putch(item->font_size, '0' + digit, + xpos, _item->y, + digit_w, h, + color, highlight); + cur_digit--; + xpos += digit_w + spacing; + + // : + tft_putch(item->font_size, '.', xpos, _item->y, dot_width, h, color, false); + xpos += dot_width + spacing; + + // SS + digit = seconds / 10; + highlight =_item->has_focus && item->cur_digit == DIGITS - 5; + tft_putch(item->font_size, '0' + digit, + xpos, _item->y, + digit_w, h, + color, highlight); + cur_digit--; + xpos += digit_w + spacing; + + digit = seconds % 10; + highlight =_item->has_focus && item->cur_digit == DIGITS - 6; + tft_putch(item->font_size, '0' + digit, + xpos, _item->y, + digit_w, h, + color, highlight); + cur_digit--; + xpos += digit_w + spacing; + + +} + +/** + * @brief Initialize time item + * + * @param item The item + */ +void time_init(ui_time_t *item) +{ + assert(item); + ui_item_init(&item->ui); + item->ui.got_event = &number_got_event; + item->ui.get_value = &number_get_value; + item->ui.draw = &number_draw; + item->cur_digit = DIGITS - 1; + item->ui.needs_redraw = true; +} + + + diff --git a/opendps/uui_time.h b/opendps/uui_time.h new file mode 100644 index 00000000..e70122e4 --- /dev/null +++ b/opendps/uui_time.h @@ -0,0 +1,55 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef __UUI_TIME_H__ +#define __UUI_TIME_H__ + +#include +#include +#include +#include "tft.h" +#include "uui.h" + +/** + * A UI item describing an editable time value formatted as HH:MM:SS + */ +typedef struct ui_time_t { + ui_item_t ui; + uint16_t color; + tft_font_size_t font_size; + ui_text_alignment_t alignment; + bool pad_dot; /** Make the '.' character the same width as the digits? */ + uint8_t cur_digit; + int32_t value; + void (*changed)(struct ui_time_t *item); +} ui_time_t; + +/** + * @brief Initialize number UI item + * + * @param item The item + */ +void time_init(ui_time_t *item); + +#endif // __UUI_NUMBER_H__ From a4c31608b7a71764be8362018db7282adf717534 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 29 Sep 2019 23:13:44 -0600 Subject: [PATCH 030/175] Implemented timer, watthour meter, accessible via third row and navigation --- opendps/Makefile | 1 + opendps/func_dpsmode.c | 254 ++++++++++++++++++++++++++++++++------ opendps/gfx-tmbar.c | 38 ++++++ opendps/gfx-tmbar.h | 13 ++ opendps/gfx/png/tmbar.png | Bin 0 -> 1077 bytes opendps/hw.c | 14 ++- opendps/opendps.c | 2 +- opendps/uui.h | 2 +- opendps/uui_number.c | 10 +- opendps/uui_time.c | 69 +++++++---- opendps/uui_time.h | 7 ++ 11 files changed, 338 insertions(+), 72 deletions(-) create mode 100644 opendps/gfx-tmbar.c create mode 100644 opendps/gfx-tmbar.h create mode 100644 opendps/gfx/png/tmbar.png diff --git a/opendps/Makefile b/opendps/Makefile index 1ba47608..c9772b62 100644 --- a/opendps/Makefile +++ b/opendps/Makefile @@ -108,6 +108,7 @@ OBJS = \ gfx-ccbar.o \ gfx-ppbar.o \ gfx-oppbar.o \ + gfx-tmbar.o \ gfx-padlock.o \ gfx-power.o \ gfx-poweron.o \ diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index c27f58d7..be5a0d30 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -32,6 +32,7 @@ #include "gfx-ccbar.h" #include "gfx-ppbar.h" #include "gfx-oppbar.h" +#include "gfx-tmbar.h" #include "font-meter_large.h" #include "hw.h" #include "func_dpsmode.h" @@ -56,6 +57,7 @@ static void dpsmode_enable(bool _enable); static void voltage_changed(ui_number_t *item); static void current_changed(ui_number_t *item); static void power_changed(ui_number_t *item); +static void watthour_changed(ui_number_t *item); static void timer_changed(ui_time_t *item); static void dpsmode_tick(void); static void activated(void); @@ -68,20 +70,26 @@ static set_param_status_t get_parameter(char *name, char *value, uint32_t value_ static void clear_bars(bool all); static void draw_bars(void); +static void determine_focused_item(uui_t *ui, bool search_ahead); +static void clear_third_region(void); /* We need to keep copies of the user settings as the value in the UI will * be replaced with measurements when output is active */ -static int32_t saved_v, saved_i, saved_p; +static int32_t saved_v, saved_i, saved_p, saved_t; // single edit mode, with M1/M2 buttons, not select. // pressing any other button when in this mode will exit the edit mode static bool single_edit_mode; static bool select_mode; +// timer +static int64_t tick_since_count; + // what is displayed on the 3rd row. static int8_t third_row = 0; ui_item_t *third_item; +static bool third_invalidate; enum { CUR_GFX_NOT_DRAWN = 0, @@ -89,12 +97,14 @@ enum { CUR_GFX_CC = 2, CUR_GFX_PP = 4, CUR_GFX_OPP = 8, + CUR_GFX_TM = 16, } dpsmode_graphics; #define SCREEN_ID (6) #define PAST_V (0) #define PAST_I (1) #define PAST_P (2) +#define PAST_T (3) #define XPOS_CCCV (25) #define XPOS_METER (117) @@ -175,38 +185,37 @@ ui_number_t dpsmode_power = { .changed = &power_changed, }; -ui_number_t dpsmode_amphour = { +ui_number_t dpsmode_watthour = { { .type = ui_item_number, .id = 13, .x = XPOS_METER, - .y = YPOS_POWER, - .can_focus = false, + .y = YPOS_POWER + 5, // +5 since we are using a smaller font + .can_focus = true, }, - .font_size = FONT_METER_LARGE, + .font_size = FONT_METER_MEDIUM, .alignment = ui_text_right_aligned, .pad_dot = false, .color = WHITE, .value = 0, .min = 0, - .max = 0, - .si_prefix = si_milli, - .num_digits = 2, - .num_decimals = 2, - .unit = unit_amphour, - .changed = NULL, + .max = 99999000, + .si_prefix = si_milli, // milli watt hours + .num_digits = 5, + .num_decimals = 1, + .unit = unit_watthour, + .changed = &watthour_changed, }; -/* ui_time_t dpsmode_timer = { { .type = ui_item_time, .id = 14, .x = XPOS_METER, - .y = YPOS_POWER, - .can_focus = false, + .y = YPOS_POWER + 5, // +5 since we are using smaller font + .can_focus = true, }, - .font_size = FONT_METER_LARGE, + .font_size = FONT_METER_MEDIUM, .alignment = ui_text_right_aligned, .pad_dot = false, .color = WHITE, @@ -214,7 +223,6 @@ ui_time_t dpsmode_timer = { .changed = &timer_changed, }; -*/ /* This is the screen definition */ ui_screen_t dpsmode_screen = { @@ -233,12 +241,13 @@ ui_screen_t dpsmode_screen = { .tick = &dpsmode_tick, .set_parameter = &set_parameter, .get_parameter = &get_parameter, - .num_items = 4, + .num_items = 5, .items = { (ui_item_t*) &dpsmode_voltage, (ui_item_t*) &dpsmode_current, (ui_item_t*) &dpsmode_power, - (ui_item_t*) &dpsmode_amphour, + (ui_item_t*) &dpsmode_watthour, + (ui_item_t*) &dpsmode_timer, }, .parameters = { { @@ -331,6 +340,7 @@ static void dpsmode_enable(bool enabled) saved_v = dpsmode_voltage.value; saved_i = dpsmode_current.value; saved_p = dpsmode_power.value; + saved_t = dpsmode_timer.value; (void) pwrctl_set_vout(dpsmode_voltage.value); (void) pwrctl_set_iout(dpsmode_current.value); @@ -340,6 +350,11 @@ static void dpsmode_enable(bool enabled) // clear all bars, including over power protection clear_bars(true); + // reset timer counter and start. + tick_since_count = get_ticks(); + if (saved_t > 0) + dpsmode_timer.value--; + } else { // already off, turning off again will reset any pp warnings if ( ! pwrctl_vout_enabled()) { @@ -356,6 +371,7 @@ static void dpsmode_enable(bool enabled) dpsmode_voltage.value = saved_v; dpsmode_current.value = saved_i; dpsmode_power.value = saved_p; + dpsmode_timer.value = saved_t; } } @@ -392,10 +408,18 @@ static void power_changed(ui_number_t *item) // (void) pwrctl_set_iout(item->value); } +/** + * @brief Callback for when value of the watthour item is changed + * + * @param item The current item + */ +static void watthour_changed(ui_number_t *item) { + // +} static void timer_changed(ui_time_t *item) { // do nothing yet... - // TODO: Implement a timer + saved_t = item->value; } @@ -403,6 +427,8 @@ static bool event(uui_t *ui, event_t event) { switch(event) { case event_button_sel: + case event_button_m1: + case event_button_m2: if (single_edit_mode) { single_edit_mode = false; @@ -414,8 +440,6 @@ static bool event(uui_t *ui, event_t event) { } break; - case event_button_m1: - case event_button_m2: case event_rot_left_m1: case event_rot_right_m1: // change what's visible on the 3rd row @@ -423,11 +447,15 @@ static bool event(uui_t *ui, event_t event) { ui_screen_t *screen = ui->screens[ui->cur_screen]; // rotate around the 3rd row objects (skip the 1st two) - third_row = ++third_row % (screen->num_items - 2); - third_item = screen->items[third_row]; - - dpsmode_graphics |= CUR_GFX_PP; - + if (event == event_rot_right_m1) { + third_row = (third_row + 1) % (screen->num_items - 2); + } else { + if (third_row == 0) third_row = screen->num_items - 3; + else third_row--; + } + + third_item = screen->items[2 + third_row]; + third_invalidate = true; } break; @@ -439,7 +467,12 @@ static bool event(uui_t *ui, event_t event) { switch(event) { case event_button_m1: // if in normal select mode, let parent handle it - if (select_mode) return false; + if (select_mode) { + // third item focused may have changed + determine_focused_item(ui, false); + + return false; + } // otherwise, enter single edit mode single_edit_mode = true; @@ -451,7 +484,11 @@ static bool event(uui_t *ui, event_t event) { return true; case event_button_m2: - if (select_mode) return false; + if (select_mode) { + determine_focused_item(ui, true); + return false; + } + single_edit_mode = true; if ( ! dpsmode_current.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_current); return true; @@ -460,6 +497,7 @@ static bool event(uui_t *ui, event_t event) { // toggle select mode, so parent can deal with other UI elements // keep track, so this screen will not do anything until we leave this mode select_mode = ! select_mode; + return false; default: @@ -474,8 +512,51 @@ static bool event(uui_t *ui, event_t event) { */ static void activated(void) { clear_bars(true); + clear_third_region(); + + // reset watthour value when we leave the screen. + dpsmode_watthour.value = 0; } +static void determine_focused_item(uui_t *ui, bool search_ahead) { + // determine what is now focused and change third to it. + ui_screen_t *screen = ui->screens[ui->cur_screen]; + + uint8_t focus_index = 0; + + for (uint8_t i = 0; i < screen->num_items; i++) { + if (((ui_number_t *)screen->items[i])->ui.has_focus) { + focus_index = i; + } + } + + if (search_ahead) { + // if searching ahead + for (focus_index++; focus_index < screen->num_items; focus_index++) { + if (((ui_number_t *)screen->items[focus_index])->ui.can_focus) { + break; + } + } + } else { + // if searching behind + for (; ; focus_index--) { + if (focus_index == 0) { + focus_index = screen->num_items; + } + + if (((ui_number_t *)screen->items[focus_index - 1])->ui.can_focus) { + focus_index--; + break; + } + } + } + + if (focus_index >= 2 && focus_index != screen->num_items) { + third_item = (ui_item_t *)screen->items[focus_index]; + third_invalidate = true; + clear_third_region(); + } +} /** * @brief Do any required clean up before changing away from this screen @@ -502,6 +583,9 @@ static void past_save(past_t *past) if (!past_write_unit(past, (SCREEN_ID << 24) | PAST_P, (void*) &saved_p, 4 /* sizeof(dpsmode_power.value) */ )) { /** @todo: handle past write failures */ } + if (!past_write_unit(past, (SCREEN_ID << 24) | PAST_T, (void*) &saved_t, 4 /* sizeof(dpsmode_power.value) */ )) { + /** @todo: handle past write failures */ + } } /** @@ -525,6 +609,10 @@ static void past_restore(past_t *past) saved_p = dpsmode_power.value = *p; (void) length; } + if (past_read_unit(past, (SCREEN_ID << 24) | PAST_T, (const void**) &p, &length)) { + saved_t = dpsmode_timer.value = *p; + (void) length; + } } /** @@ -606,6 +694,8 @@ static void dpsmode_tick(void) // show opp warning dpsmode_graphics |= CUR_GFX_OPP; dpsmode_graphics &= ~CUR_GFX_PP; + // disable timer graphic + dpsmode_graphics &= ~CUR_GFX_TM; // power off dpsmode_enable(false); @@ -624,6 +714,54 @@ static void dpsmode_tick(void) dpsmode_graphics &= ~CUR_GFX_OPP; } + // timer + int64_t diff = get_ticks() - tick_since_count; + int8_t secs = diff / 1000; + + // update every second + if (secs > 0) { + // update timer. If 0, use the timer as a clock. Otherwise, count down + if (saved_t > 0) { + dpsmode_timer.value -= secs; + dpsmode_graphics |= CUR_GFX_TM; + } else { + dpsmode_timer.value += secs; + + // overflow timer + if (dpsmode_timer.value > MAX_TIME) { + dpsmode_timer.value = MAX_TIME; + } + } + diff = diff % 1000; + + tick_since_count = get_ticks() - diff; + + // calculate amount of power delivered as milli watt hours + dpsmode_watthour.value += ((power_actual * 1000.0 / 3600.0f) * secs) / 1000; + + // 1000 == 1.0mWh + /* + if (dpsmode_watthour.value <= 1000000) { + dpsmode_watthour.num_decimals = 1; + } + if (dpsmode_watthour.value >= 1000000) { + dpsmode_watthour.num_decimals = 0; + } + */ + } + + // timer enabled, count down + if (saved_t > 0 && dpsmode_timer.value <= 0) { + // timer has counted down + // show the timer + third_item = &dpsmode_timer; + third_invalidate = true; + + // power off + dpsmode_enable(false); + opendps_update_power_status(false); + } + } @@ -633,7 +771,14 @@ static void dpsmode_tick(void) // draw 3rd row item... if ( third_item ) { + // blank out the whole 3rd row area + if (third_invalidate) { + third_invalidate = false; + clear_third_region(); + } + ((ui_number_t *)third_item)->ui.draw(& ((ui_number_t *)third_item)->ui); + } else { // dpsmode_power.ui.draw(&dpsmode_power.ui); } @@ -642,6 +787,12 @@ static void dpsmode_tick(void) draw_bars(); } +static void clear_third_region() { + tft_fill(0, YPOS_POWER, + TFT_WIDTH, FONT_METER_LARGE_MAX_GLYPH_HEIGHT, + BLACK); +} + /** * @brief draws bars on the right hand side of the screen. @@ -676,27 +827,48 @@ static void draw_bars() { } + // draw timer + if (dpsmode_graphics & CUR_GFX_TM) { + // blink the timer icon + if ((get_ticks() >> 9) & 1) + tft_blit((uint16_t*) gfx_tmbar, + GFX_TMBAR_WIDTH, GFX_TMBAR_HEIGHT, + TFT_WIDTH - GFX_TMBAR_WIDTH, + YPOS_POWER + FONT_METER_LARGE_MAX_GLYPH_HEIGHT - GFX_TMBAR_HEIGHT ); + else + tft_fill(TFT_WIDTH - GFX_TMBAR_WIDTH, YPOS_POWER + FONT_METER_LARGE_MAX_GLYPH_HEIGHT - GFX_TMBAR_HEIGHT, + GFX_TMBAR_WIDTH, GFX_TMBAR_HEIGHT, + BLACK); + } + + // draw opp if (dpsmode_graphics & CUR_GFX_OPP) { // blink the opp warning - if ((get_ticks() >> 10) & 1) + if (((get_ticks() >> 9) & 1) == 0) tft_blit((uint16_t*) gfx_oppbar, GFX_OPPBAR_WIDTH, GFX_OPPBAR_HEIGHT, TFT_WIDTH - GFX_OPPBAR_WIDTH, YPOS_POWER + FONT_METER_LARGE_MAX_GLYPH_HEIGHT - GFX_OPPBAR_HEIGHT ); - else - tft_fill(TFT_WIDTH - GFX_PPBAR_WIDTH, YPOS_POWER + FONT_METER_LARGE_MAX_GLYPH_HEIGHT - GFX_PPBAR_HEIGHT, - GFX_PPBAR_WIDTH, GFX_PPBAR_HEIGHT, + // no timer (or other icons), paint black over it. + else if ( (dpsmode_graphics & CUR_GFX_TM) != 1) + tft_fill(TFT_WIDTH - GFX_OPPBAR_WIDTH, YPOS_POWER + FONT_METER_LARGE_MAX_GLYPH_HEIGHT - GFX_OPPBAR_HEIGHT, + GFX_OPPBAR_WIDTH, GFX_OPPBAR_HEIGHT, BLACK); } // draw pp else if (dpsmode_graphics & CUR_GFX_PP) { - tft_blit((uint16_t*) gfx_ppbar, - GFX_PPBAR_WIDTH, GFX_PPBAR_HEIGHT, - TFT_WIDTH - GFX_PPBAR_WIDTH, - YPOS_POWER + FONT_METER_LARGE_MAX_GLYPH_HEIGHT - GFX_PPBAR_HEIGHT ); - // or clear - } else { + // if timer (or other icons), blink it so it is visible. + if (((get_ticks() >> 9) & 1) == 0) + tft_blit((uint16_t*) gfx_ppbar, + GFX_PPBAR_WIDTH, GFX_PPBAR_HEIGHT, + TFT_WIDTH - GFX_PPBAR_WIDTH, + YPOS_POWER + FONT_METER_LARGE_MAX_GLYPH_HEIGHT - GFX_PPBAR_HEIGHT ); + } + + + // no graphics at 3rd location, clear it. + if ( ! (dpsmode_graphics & CUR_GFX_OPP || dpsmode_graphics & CUR_GFX_PP || dpsmode_graphics & CUR_GFX_TM)) { tft_fill(TFT_WIDTH - GFX_PPBAR_WIDTH, YPOS_POWER + FONT_METER_LARGE_MAX_GLYPH_HEIGHT - GFX_PPBAR_HEIGHT, GFX_PPBAR_WIDTH, GFX_PPBAR_HEIGHT, BLACK); @@ -752,8 +924,12 @@ void func_dpsmode_init(uui_t *ui) number_init(&dpsmode_current); number_init(&dpsmode_power); + number_init(&dpsmode_watthour); + time_init(&dpsmode_timer); - number_init(&dpsmode_amphour); + // third item initialize + third_item = &dpsmode_power; + third_invalidate = true; uui_add_screen(ui, &dpsmode_screen); } diff --git a/opendps/gfx-tmbar.c b/opendps/gfx-tmbar.c new file mode 100644 index 00000000..58c318e5 --- /dev/null +++ b/opendps/gfx-tmbar.c @@ -0,0 +1,38 @@ +/** Gfx generated from gfx/png/tmbar.png */ + +#include "gfx-tmbar.h" + +const uint8_t gfx_tmbar[500] = { + 0x00, 0x00, 0x00, 0x00, 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, + 0xfd, 0x65, 0xfd, 0x65, 0x00, 0x00, 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, + 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, 0x00, 0x00, 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, + 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, 0x00, 0x00, 0xfd, 0x65, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x65, + 0x00, 0x00, 0xfd, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfd, 0x65, 0x00, 0x00, 0xfd, 0x65, 0xfd, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfd, 0x65, 0x00, 0x00, 0xfd, 0x65, 0xfd, 0x65, 0x00, 0x00, 0xfd, 0x65, 0xfd, 0x65, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfd, 0x65, 0x00, 0x00, 0xfd, 0x65, 0xfd, 0x65, 0x00, 0x00, 0xfd, 0x65, + 0xfd, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x65, 0xfd, 0x65, + 0x00, 0x00, 0xfd, 0x65, 0xfd, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfd, 0x65, 0xfd, 0x65, 0x00, 0x00, 0xfd, 0x65, 0xfd, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfd, 0x65, 0xfd, 0x65, 0x00, 0x00, 0xfd, 0x65, 0xfd, 0x65, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x65, 0xfd, 0x65, 0x00, 0x00, 0xfd, 0x65, + 0xfd, 0x65, 0xfd, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, + 0x00, 0x00, 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, 0x00, 0x00, 0xfd, 0x65, 0xfd, 0x65, + 0xfd, 0x65, 0xfd, 0x65, 0x00, 0x00, 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, 0x00, 0x00, 0xfd, 0x65, 0xfd, 0x65, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x65, 0xfd, 0x65, 0x00, 0x00, 0xfd, 0x65, + 0xfd, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x65, 0xfd, 0x65, + 0x00, 0x00, 0xfd, 0x65, 0xfd, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfd, 0x65, 0xfd, 0x65, 0x00, 0x00, 0xfd, 0x65, 0xfd, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfd, 0x65, 0xfd, 0x65, 0x00, 0x00, 0xfd, 0x65, 0xfd, 0x65, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x65, 0xfd, 0x65, 0x00, 0x00, 0xfd, 0x65, + 0xfd, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x65, 0xfd, 0x65, + 0x00, 0x00, 0xfd, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfd, 0x65, 0x00, 0x00, 0xfd, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x65, 0x00, 0x00, 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, + 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, 0x00, 0x00, 0xfd, 0x65, + 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, + 0x00, 0x00, 0x00, 0x00, 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, 0xfd, 0x65, + 0xfd, 0x65, 0xfd, 0x65 +}; \ No newline at end of file diff --git a/opendps/gfx-tmbar.h b/opendps/gfx-tmbar.h new file mode 100644 index 00000000..93ffe122 --- /dev/null +++ b/opendps/gfx-tmbar.h @@ -0,0 +1,13 @@ +/** Gfx generated from gfx/png/tmbar.png */ + +#ifndef __GFX_TMBAR_H__ +#define __GFX_TMBAR_H__ + +#include + +#define GFX_TMBAR_HEIGHT (25) +#define GFX_TMBAR_WIDTH (10) + +extern const uint8_t gfx_tmbar[500]; + +#endif // __GFX_TMBAR_H__ \ No newline at end of file diff --git a/opendps/gfx/png/tmbar.png b/opendps/gfx/png/tmbar.png new file mode 100644 index 0000000000000000000000000000000000000000..8351479884055d106bd1a2c360c7501171204035 GIT binary patch literal 1077 zcmbVL&1=(O7|%A4IhcqS*-lvsGRN|rek8QcHR)Vo-AY$kFAkHuZ`-gXZ%p2<>BNf& zLqrcAba>K>J1Oq$!HWk6dKg}YFcka)ym;3)?K(Y-A?A=g@0;K6d4A8={qo|q(UI{H zilRn~^G1byV|#3Pki54pOn!|IxKP8(sE*ra0I6AkEJzn!vjHp61f5%ZFiTNG8&0)` zYo!IvMlNT@7%p;s!ltO~OyryP8pN~(8;+M_e!P9h&<@BkE6I{j@^#pB<~IYlyt!Dl zH`i_AHjD3yg+wC^jmN^tO zcu`eVUXXZ6VhMr`J03P8)(aDT4+aeF!11wzJUaGhTBwC{3{l!k!Szd}W5-^2R47t1 zJ~Dk?Nt{cd1 zxzNK!Bgc?G9B_b^QEXWi>lT}qfW=yZqOchS*sKJUB(ThS1|&h>&xw55(DMa3S&*f? zC>GRADxc36(y6?hPN{l9?{kY@h)vIi{n$<%yT?^dB$wx1E?Kdj@#7B+JJ$x0l{2=T)JCl%{fWKKjq)!ga54`Pek$Yu>3VV{VOt& zv3a}-3y?|Ek6aAEt* z)r0eoGlw6(J)24Fayw6ym*4kWiQ8u%DDOWV+;}uS()he*|6DpZeQ$YcU}s|M;y5)d YP`e)|sMQzy+wme73ya3<{LQ<+0eOj2rvLx| literal 0 HcmV?d00001 diff --git a/opendps/hw.c b/opendps/hw.c index 9284565d..4ce6919a 100644 --- a/opendps/hw.c +++ b/opendps/hw.c @@ -92,6 +92,7 @@ static volatile bool set_skip = false; static volatile bool m1_pressed = false; static volatile bool m2_pressed = false; static volatile bool m1_and_m2_pressed = false; +static volatile bool rot_turned = false; #define DEBOUNCE_TIME_MS (30) @@ -867,6 +868,9 @@ void BUTTON_M1_isr(void) if (is_bouncing()) return; m1_pressed = true; + // do not fire button if rot rotated while down + rot_turned = false; + if (m2_pressed) m1_and_m2_pressed = true; @@ -879,7 +883,7 @@ void BUTTON_M1_isr(void) m1_and_m2_pressed = false; event_put(event_buttom_m1_and_m2, press_short); } else { - event_put(event_button_m1, press_short); + if ( ! rot_turned) event_put(event_button_m1, press_short); } } @@ -899,6 +903,10 @@ void BUTTON_M2_isr(void) if (falling) { if (is_bouncing()) return; m2_pressed = true; + + // do not fire button if rot rotated while down + rot_turned = false; + if (m1_pressed) m1_and_m2_pressed = true; exti_set_trigger(BUTTON_M2_EXTI, EXTI_TRIGGER_RISING); @@ -910,7 +918,7 @@ void BUTTON_M2_isr(void) m1_and_m2_pressed = false; event_put(event_buttom_m1_and_m2, press_short); } else { - event_put(event_button_m2, press_short); + if ( ! rot_turned) event_put(event_button_m2, press_short); } } @@ -964,6 +972,8 @@ void BUTTON_ROTARY_isr(void) exti_reset_request(BUTTON_ROT_A_EXTI); bool a = (((uint16_t) GPIO_IDR(BUTTON_ROT_A_PORT)) & BUTTON_ROT_A_PIN) ? 1 : 0; // Slightly faster than gpio_get(...) bool b = (((uint16_t) GPIO_IDR(BUTTON_ROT_B_PORT)) & BUTTON_ROT_B_PIN) ? 1 : 0; + rot_turned = true; + if (a == b) { if (set_pressed) { set_skip = true; diff --git a/opendps/opendps.c b/opendps/opendps.c index 408f0db4..8b421876 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -79,7 +79,7 @@ #endif // CONFIG_SPLASH_SCREEN /** How ofter we update the measurements in the UI (ms) */ -#define UI_UPDATE_INTERVAL_MS (250) +#define UI_UPDATE_INTERVAL_MS (100) /** Timeout for waiting for wifi connction (ms) */ #define WIFI_CONNECT_TIMEOUT (10000) diff --git a/opendps/uui.h b/opendps/uui.h index d81280ac..82c2932f 100644 --- a/opendps/uui.h +++ b/opendps/uui.h @@ -64,7 +64,7 @@ typedef enum { unit_ampere, unit_volt, unit_watt, - unit_amphour, + unit_watthour, unit_second, unit_hertz, unit_furlong, diff --git a/opendps/uui_number.c b/opendps/uui_number.c index c6576135..349f70df 100644 --- a/opendps/uui_number.c +++ b/opendps/uui_number.c @@ -166,7 +166,7 @@ static uint32_t number_draw_width(ui_item_t *_item) case unit_hertz: total_width += 2*FONT_FULL_SMALL_MAX_GLYPH_WIDTH; break; - case unit_amphour: + case unit_watthour: total_width += 3*FONT_FULL_SMALL_MAX_GLYPH_WIDTH; break; default: @@ -244,7 +244,7 @@ static void number_draw(ui_item_t *_item) bool highlight = _item->has_focus && item->cur_digit == cur_digit; uint8_t digit = item->value / my_pow(10, (item->si_prefix * -1) + i) % 10; - if (!digit /** If current digit is a 0 */ + if ( ! digit /** If current digit is a 0 */ && !_item->has_focus /** and its not in focus (selected) */ && cur_digit != item->num_decimals /** to prevent 0.123 becoming .123 */ && my_pow(10, cur_digit + (item->si_prefix * -1)) > (uint32_t) item->value) /** to prevent 4023 becoming 4 23 */ @@ -261,6 +261,7 @@ static void number_draw(ui_item_t *_item) } else { + if (spacing > 1) /** Dont frame tiny fonts */ { if (highlight) /** Draw an extra pixel wide border around the highlighted item */ @@ -311,8 +312,9 @@ static void number_draw(ui_item_t *_item) case unit_hertz: tft_puts(FONT_FULL_SMALL, "Hz", xpos, _item->y + h, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 2, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, color, false); break; - case unit_amphour: - tft_puts(FONT_FULL_SMALL, "mAh", xpos, _item->y + h, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 3, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, color, false); + case unit_watthour: + // units here are milliwatt hours + tft_puts(FONT_FULL_SMALL, "mWh", xpos, _item->y + h, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 3, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, color, false); break; case unit_watt: tft_putch(item->font_size, 'W', xpos, _item->y, max_w, h, color, false); diff --git a/opendps/uui_time.c b/opendps/uui_time.c index 522cb463..b5882bc0 100644 --- a/opendps/uui_time.c +++ b/opendps/uui_time.c @@ -33,26 +33,33 @@ #include "font-meter_medium.h" #include "font-meter_large.h" -// HH:MM:SS == 6 -#define DIGITS 6 - -// 99:59:59 == 359999 seconds -#define MAX_TIME 359999 - #define MAX(a,b) (((a)>(b))?(a):(b)) static uint32_t digit_scale(ui_time_t *item, uint32_t i) { - if (item->cur_digit == 0 || item->cur_digit == 1) { - // seconds - return i; - } - if (item->cur_digit == 2 || item->cur_digit == 3) { - // minutes - return i * 60; + switch (item->cur_digit) { + case 0: + // seconds + return i; + case 1: + // 10s of seconds + return 10 * i; + case 2: + // minutes + return 60 * i; + case 3: + // 10s of minutes + return 600 * i; + case 4: + // hours + return 3600 * i; + case 5: + // tens of hours + return 36000 * i; + case 6: + default: + // hundreds of hours + return 360000 * i; } - - // hours - return i * 3600; } /** @@ -148,7 +155,7 @@ static uint32_t number_draw_width(ui_item_t *_item) /** Start printing from left to right */ - // total digits HH:MM:SS = 6, plus spacing, plus 2 : + // total digits HHH:MM:SS = 7, plus spacing, plus 2 : total_width += DIGITS * (digit_w + spacing); total_width += 2 * (dot_width + spacing); @@ -213,14 +220,14 @@ static void number_draw(ui_item_t *_item) xpos -= number_draw_width(_item); - uint8_t hours = item->value / 3600; + uint16_t hours = item->value / 3600; uint8_t minutes = (item->value / 60) % 60; uint8_t seconds = item->value % 60; uint8_t digit = 0; bool highlight = false; - // HH - digit = hours / 10; + // HHH + digit = hours / 100; highlight =_item->has_focus && item->cur_digit == DIGITS - 1; tft_putch(item->font_size, '0' + digit, @@ -230,8 +237,18 @@ static void number_draw(ui_item_t *_item) cur_digit--; xpos += digit_w + spacing; - digit = hours % 10; + digit = (hours % 100) / 10; highlight =_item->has_focus && item->cur_digit == DIGITS - 2; + + tft_putch(item->font_size, '0' + digit, + xpos, _item->y, + digit_w, h, + color, highlight); + cur_digit--; + xpos += digit_w + spacing; + + digit = hours % 10; + highlight =_item->has_focus && item->cur_digit == DIGITS - 3; tft_putch(item->font_size, '0' + digit, xpos, _item->y, digit_w, h, @@ -241,11 +258,12 @@ static void number_draw(ui_item_t *_item) // : tft_putch(item->font_size, '.', xpos, _item->y, dot_width, h, color, false); + tft_putch(item->font_size, '.', xpos, _item->y - (h >> 1), dot_width, h, color, false); xpos += dot_width + spacing; // MM digit = minutes / 10; - highlight =_item->has_focus && item->cur_digit == DIGITS - 3; + highlight =_item->has_focus && item->cur_digit == DIGITS - 4; tft_putch(item->font_size, '0' + digit, xpos, _item->y, digit_w, h, @@ -254,7 +272,7 @@ static void number_draw(ui_item_t *_item) xpos += digit_w + spacing; digit = minutes % 10; - highlight =_item->has_focus && item->cur_digit == DIGITS - 4; + highlight =_item->has_focus && item->cur_digit == DIGITS - 5; tft_putch(item->font_size, '0' + digit, xpos, _item->y, digit_w, h, @@ -264,11 +282,12 @@ static void number_draw(ui_item_t *_item) // : tft_putch(item->font_size, '.', xpos, _item->y, dot_width, h, color, false); + tft_putch(item->font_size, '.', xpos, _item->y - (h >> 1), dot_width, h, color, false); xpos += dot_width + spacing; // SS digit = seconds / 10; - highlight =_item->has_focus && item->cur_digit == DIGITS - 5; + highlight =_item->has_focus && item->cur_digit == DIGITS - 6; tft_putch(item->font_size, '0' + digit, xpos, _item->y, digit_w, h, @@ -277,7 +296,7 @@ static void number_draw(ui_item_t *_item) xpos += digit_w + spacing; digit = seconds % 10; - highlight =_item->has_focus && item->cur_digit == DIGITS - 6; + highlight =_item->has_focus && item->cur_digit == DIGITS - 7; tft_putch(item->font_size, '0' + digit, xpos, _item->y, digit_w, h, diff --git a/opendps/uui_time.h b/opendps/uui_time.h index e70122e4..b209d18f 100644 --- a/opendps/uui_time.h +++ b/opendps/uui_time.h @@ -31,6 +31,13 @@ #include "tft.h" #include "uui.h" + +// HHH:MM:SS == 7 +#define DIGITS 7 + +// 999:59:59 == 3600000-1 seconds +#define MAX_TIME 3600000-1 + /** * A UI item describing an editable time value formatted as HH:MM:SS */ From 8b8ff69c631016d12263d665a4d4535fb16040d7 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 29 Sep 2019 23:16:05 -0600 Subject: [PATCH 031/175] Fixed makefile --- opendps/Makefile | 2 -- 1 file changed, 2 deletions(-) diff --git a/opendps/Makefile b/opendps/Makefile index c9772b62..f1c6aba2 100644 --- a/opendps/Makefile +++ b/opendps/Makefile @@ -111,8 +111,6 @@ OBJS = \ gfx-tmbar.o \ gfx-padlock.o \ gfx-power.o \ - gfx-poweron.o \ - gfx-poweroff.o \ gfx-thermometer.o \ gfx-wifi.o \ opendps.o From 576fc4d9dfba4cf5d9b1f1f4c1bfeed2b4514613 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 29 Sep 2019 23:37:44 -0600 Subject: [PATCH 032/175] Disable timer graphics when disabled --- opendps/func_dpsmode.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index be5a0d30..0bcf3908 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -372,6 +372,9 @@ static void dpsmode_enable(bool enabled) dpsmode_current.value = saved_i; dpsmode_power.value = saved_p; dpsmode_timer.value = saved_t; + + // disable timer graphic + dpsmode_graphics &= ~CUR_GFX_TM; } } From b2146f86969f60d18585237d1848ceec8a936962 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Mon, 30 Sep 2019 10:34:35 -0600 Subject: [PATCH 033/175] Minor bug fixes Third item will not change if in select mode Screen cannot change is locked if power is on to prevent inadvertant data/state loss Colon rendering should be less glitchy --- opendps/func_dpsmode.c | 15 ++++++++------- opendps/opendps.c | 16 ++++++++++++++-- opendps/uui_time.c | 8 ++++---- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 0bcf3908..39cdd9ea 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -446,7 +446,8 @@ static bool event(uui_t *ui, event_t event) { case event_rot_left_m1: case event_rot_right_m1: // change what's visible on the 3rd row - { + // only if not in select mode, as we may be editing fields + if ( ! select_mode) { ui_screen_t *screen = ui->screens[ui->cur_screen]; // rotate around the 3rd row objects (skip the 1st two) @@ -649,29 +650,29 @@ static void dpsmode_tick(void) // TODO: Issue where focus causes a brief frame where value is incorrect // Voltage setting has focus, update with the desired value and not output value - if (dpsmode_voltage.ui.has_focus && dpsmode_voltage.value != saved_v) { + if (dpsmode_voltage.ui.has_focus) { dpsmode_voltage.value = saved_v; } // Voltage setting is not focused, update with actual output voltage - if ( ! dpsmode_voltage.ui.has_focus && dpsmode_voltage.value != vout_actual) { + if ( ! dpsmode_voltage.ui.has_focus) { dpsmode_voltage.value = vout_actual; } // Same for amperage. update with desired value if focused - if (dpsmode_current.ui.has_focus && dpsmode_current.value != saved_i) { + if (dpsmode_current.ui.has_focus) { dpsmode_current.value = saved_i; } // Update with actual output voltage if not in focus - if ( ! dpsmode_current.ui.has_focus && dpsmode_current.value != cout_actual) { + if ( ! dpsmode_current.ui.has_focus) { dpsmode_current.value = cout_actual; } // update the power with desired value if focused - if (dpsmode_power.ui.has_focus && dpsmode_power.value != saved_i) { + if (dpsmode_power.ui.has_focus) { dpsmode_power.value = saved_p; } // Update with actual output power if not in focus - if ( ! dpsmode_power.ui.has_focus && dpsmode_power.value != power_actual) { + if ( ! dpsmode_power.ui.has_focus) { dpsmode_power.value = power_actual; } diff --git a/opendps/opendps.c b/opendps/opendps.c index 8b421876..29d05b82 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -541,8 +541,6 @@ static void ui_handle_event(event_t event, uint8_t data) case event_rot_press: case event_rot_left: case event_rot_right: - case event_rot_left_set: - case event_rot_right_set: case event_rot_left_m1: case event_rot_right_m1: case event_rot_left_m2: @@ -550,6 +548,20 @@ static void ui_handle_event(event_t event, uint8_t data) uui_handle_screen_event(current_ui, event); uui_refresh(current_ui, false); break; + + case event_rot_left_set: + case event_rot_right_set: + // lock out set+rotation when power is on + if (pwrctl_vout_enabled()) { + lock_flashing_period = LOCK_FLASHING_PERIOD; + lock_flash_counter = LOCK_FLASHING_COUNTER; + break; + } + + uui_handle_screen_event(current_ui, event); + uui_refresh(current_ui, false); + break; + default: break; } diff --git a/opendps/uui_time.c b/opendps/uui_time.c index b5882bc0..6dadee18 100644 --- a/opendps/uui_time.c +++ b/opendps/uui_time.c @@ -257,8 +257,8 @@ static void number_draw(ui_item_t *_item) xpos += digit_w + spacing; // : - tft_putch(item->font_size, '.', xpos, _item->y, dot_width, h, color, false); - tft_putch(item->font_size, '.', xpos, _item->y - (h >> 1), dot_width, h, color, false); + tft_putch(item->font_size, '.', xpos, _item->y, dot_width, h >> 4, color, false); + tft_putch(item->font_size, '.', xpos, _item->y - (h >> 1), dot_width, h >> 4, color, false); xpos += dot_width + spacing; // MM @@ -281,8 +281,8 @@ static void number_draw(ui_item_t *_item) xpos += digit_w + spacing; // : - tft_putch(item->font_size, '.', xpos, _item->y, dot_width, h, color, false); - tft_putch(item->font_size, '.', xpos, _item->y - (h >> 1), dot_width, h, color, false); + tft_putch(item->font_size, '.', xpos, _item->y, dot_width, h >> 4, color, false); + tft_putch(item->font_size, '.', xpos, _item->y - (h >> 1), dot_width, h >> 4, color, false); xpos += dot_width + spacing; // SS From c68f0a1932ea11d4312e689d1f9156ae4d953f3a Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Mon, 30 Sep 2019 10:46:24 -0600 Subject: [PATCH 034/175] Minor tweaks to constants --- opendps/dps-model.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/opendps/dps-model.h b/opendps/dps-model.h index e4e33ffc..665361e7 100644 --- a/opendps/dps-model.h +++ b/opendps/dps-model.h @@ -75,10 +75,10 @@ #define ADC_CHA_IOUT_GOLDEN_VALUE (0x45) #define A_DAC_K (float)0.6402f #define A_DAC_C (float)299.5518f - #define A_ADC_K (float)1.74096f - #define A_ADC_C (float)-121.3943805f - #define V_DAC_K (float)0.07544f - #define V_DAC_C (float)2.1563f + #define A_ADC_K (float)1.724797241f + #define A_ADC_C (float)-122.2488093f + #define V_DAC_K (float)0.075289421f + #define V_DAC_C (float)3.948403194f #define V_ADC_K (float)13.253f #define V_ADC_C (float)-103.105f #elif defined(DPS3005) From f46ef5e179662e670aae4e69b3b7d8ee8de5da9a Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Mon, 30 Sep 2019 11:19:59 -0600 Subject: [PATCH 035/175] Minor tweaks to constants --- opendps/dps-model.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/opendps/dps-model.h b/opendps/dps-model.h index 665361e7..79e7c162 100644 --- a/opendps/dps-model.h +++ b/opendps/dps-model.h @@ -73,14 +73,14 @@ #define CONFIG_DPS_MAX_CURRENT (5000) #endif #define ADC_CHA_IOUT_GOLDEN_VALUE (0x45) - #define A_DAC_K (float)0.6402f - #define A_DAC_C (float)299.5518f + #define A_DAC_K (float)0.64126878130217f + #define A_DAC_C (float)302.806477462437f #define A_ADC_K (float)1.724797241f #define A_ADC_C (float)-122.2488093f #define V_DAC_K (float)0.075289421f #define V_DAC_C (float)3.948403194f - #define V_ADC_K (float)13.253f - #define V_ADC_C (float)-103.105f + #define V_ADC_K (float)13.2973244147157f + #define V_ADC_C (float)-108.801003344482f #elif defined(DPS3005) #ifndef CONFIG_DPS_MAX_CURRENT #define CONFIG_DPS_MAX_CURRENT (5000) From bb53ae2c1c3960b1d282450469bb6a8cff84e64a Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Mon, 30 Sep 2019 11:52:52 -0600 Subject: [PATCH 036/175] Calibrated values and they are now spot on --- opendps/dps-model.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/opendps/dps-model.h b/opendps/dps-model.h index 79e7c162..70dd4326 100644 --- a/opendps/dps-model.h +++ b/opendps/dps-model.h @@ -73,14 +73,14 @@ #define CONFIG_DPS_MAX_CURRENT (5000) #endif #define ADC_CHA_IOUT_GOLDEN_VALUE (0x45) - #define A_DAC_K (float)0.64126878130217f - #define A_DAC_C (float)302.806477462437f + #define A_DAC_K (float)0.642339346880304f + #define A_DAC_C (float)300.056571748685f #define A_ADC_K (float)1.724797241f #define A_ADC_C (float)-122.2488093f - #define V_DAC_K (float)0.075289421f - #define V_DAC_C (float)3.948403194f - #define V_ADC_K (float)13.2973244147157f - #define V_ADC_C (float)-108.801003344482f + #define V_DAC_K (float)0.075587636839016f + #define V_DAC_C (float)0.578377373449399f + #define V_ADC_K (float)13.2451913879205f + #define V_ADC_C (float)-111.852853739113f #elif defined(DPS3005) #ifndef CONFIG_DPS_MAX_CURRENT #define CONFIG_DPS_MAX_CURRENT (5000) From e2f33e6d784db38edc806b20f81c3ea67ee20de9 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Mon, 30 Sep 2019 11:53:55 -0600 Subject: [PATCH 037/175] Colons render a bit better --- opendps/uui_time.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/opendps/uui_time.c b/opendps/uui_time.c index 6dadee18..5628907e 100644 --- a/opendps/uui_time.c +++ b/opendps/uui_time.c @@ -257,8 +257,8 @@ static void number_draw(ui_item_t *_item) xpos += digit_w + spacing; // : - tft_putch(item->font_size, '.', xpos, _item->y, dot_width, h >> 4, color, false); - tft_putch(item->font_size, '.', xpos, _item->y - (h >> 1), dot_width, h >> 4, color, false); + tft_putch(item->font_size, '.', xpos, _item->y - (h>>2) + (h >> 1), dot_width, h >> 2, color, false); + tft_putch(item->font_size, '.', xpos, _item->y - (h>>2) , dot_width, h >> 2, color, false); xpos += dot_width + spacing; // MM @@ -281,8 +281,8 @@ static void number_draw(ui_item_t *_item) xpos += digit_w + spacing; // : - tft_putch(item->font_size, '.', xpos, _item->y, dot_width, h >> 4, color, false); - tft_putch(item->font_size, '.', xpos, _item->y - (h >> 1), dot_width, h >> 4, color, false); + tft_putch(item->font_size, '.', xpos, _item->y - (h>>2) + (h >> 1), dot_width, h >> 2, color, false); + tft_putch(item->font_size, '.', xpos, _item->y - (h>>2) , dot_width, h >> 2, color, false); xpos += dot_width + spacing; // SS From 20a1aef377558f7b042cff588b68d34adbc5a47f Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Mon, 30 Sep 2019 11:55:03 -0600 Subject: [PATCH 038/175] Entering select mode will focus on item being edited --- opendps/func_dpsmode.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 39cdd9ea..640a09a0 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -502,6 +502,11 @@ static bool event(uui_t *ui, event_t event) { // keep track, so this screen will not do anything until we leave this mode select_mode = ! select_mode; + if (select_mode) { + determine_focused_item(ui, true); + return false; + } + return false; default: From 3301371d633c32babd0ba755c5d7235bba592501 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Mon, 30 Sep 2019 12:00:00 -0600 Subject: [PATCH 039/175] Focus on proper item when entering select mode --- opendps/func_dpsmode.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 640a09a0..9f830e2c 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -70,7 +70,7 @@ static set_param_status_t get_parameter(char *name, char *value, uint32_t value_ static void clear_bars(bool all); static void draw_bars(void); -static void determine_focused_item(uui_t *ui, bool search_ahead); +static void determine_focused_item(uui_t *ui, int8_t direction); static void clear_third_region(void); /* We need to keep copies of the user settings as the value in the UI will @@ -473,7 +473,7 @@ static bool event(uui_t *ui, event_t event) { // if in normal select mode, let parent handle it if (select_mode) { // third item focused may have changed - determine_focused_item(ui, false); + determine_focused_item(ui, -1); return false; } @@ -489,7 +489,7 @@ static bool event(uui_t *ui, event_t event) { case event_button_m2: if (select_mode) { - determine_focused_item(ui, true); + determine_focused_item(ui, 1); return false; } @@ -503,7 +503,7 @@ static bool event(uui_t *ui, event_t event) { select_mode = ! select_mode; if (select_mode) { - determine_focused_item(ui, true); + determine_focused_item(ui, 0); return false; } @@ -527,7 +527,7 @@ static void activated(void) { dpsmode_watthour.value = 0; } -static void determine_focused_item(uui_t *ui, bool search_ahead) { +static void determine_focused_item(uui_t *ui, int8_t direction) { // determine what is now focused and change third to it. ui_screen_t *screen = ui->screens[ui->cur_screen]; @@ -539,14 +539,14 @@ static void determine_focused_item(uui_t *ui, bool search_ahead) { } } - if (search_ahead) { + if (direction > 0) { // if searching ahead for (focus_index++; focus_index < screen->num_items; focus_index++) { if (((ui_number_t *)screen->items[focus_index])->ui.can_focus) { break; } } - } else { + } else if (direction < 0) { // if searching behind for (; ; focus_index--) { if (focus_index == 0) { From 62a80785eaab44803b5a2d4b2e079f4c5e1cee80 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Mon, 30 Sep 2019 12:03:09 -0600 Subject: [PATCH 040/175] Using the current screen item to focus when entering select mode --- opendps/func_dpsmode.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 9f830e2c..c7cd6e8e 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -558,8 +558,14 @@ static void determine_focused_item(uui_t *ui, int8_t direction) { break; } } + + // the current item on focus by the screen + } else { + // this item may not be a third item. The check below should catch it. + focus_index = screen->cur_item; } + if (focus_index >= 2 && focus_index != screen->num_items) { third_item = (ui_item_t *)screen->items[focus_index]; third_invalidate = true; From 5fded774a564d3c766ff2d1235ec7d52f5004068 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Mon, 30 Sep 2019 12:06:21 -0600 Subject: [PATCH 041/175] Keep track of third row item index --- opendps/func_dpsmode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index c7cd6e8e..0a116d8c 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -568,6 +568,7 @@ static void determine_focused_item(uui_t *ui, int8_t direction) { if (focus_index >= 2 && focus_index != screen->num_items) { third_item = (ui_item_t *)screen->items[focus_index]; + third_row = focus_index - 2; third_invalidate = true; clear_third_region(); } From 7638ce91f3ee6b825967e4f75c210924003a04b7 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Mon, 30 Sep 2019 12:11:35 -0600 Subject: [PATCH 042/175] Changed the default digits to the first least significant number --- opendps/uui_number.c | 2 +- opendps/uui_time.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/opendps/uui_number.c b/opendps/uui_number.c index 349f70df..138fad15 100644 --- a/opendps/uui_number.c +++ b/opendps/uui_number.c @@ -336,6 +336,6 @@ void number_init(ui_number_t *item) item->ui.got_event = &number_got_event; item->ui.get_value = &number_get_value; item->ui.draw = &number_draw; - item->cur_digit = item->num_digits + item->num_decimals - 1; /** Most signinficant digit */ + item->cur_digit = item->num_decimals; // edit least significant digit first item->ui.needs_redraw = true; } diff --git a/opendps/uui_time.c b/opendps/uui_time.c index 5628907e..038b87dd 100644 --- a/opendps/uui_time.c +++ b/opendps/uui_time.c @@ -319,7 +319,7 @@ void time_init(ui_time_t *item) item->ui.got_event = &number_got_event; item->ui.get_value = &number_get_value; item->ui.draw = &number_draw; - item->cur_digit = DIGITS - 1; + item->cur_digit = DIGITS - 3; // hour first item->ui.needs_redraw = true; } From ba117e82328bcb60b0681e08b867d3e1b0e845ac Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Mon, 30 Sep 2019 12:26:35 -0600 Subject: [PATCH 043/175] Fixed slightly off current ADC values --- opendps/dps-model.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opendps/dps-model.h b/opendps/dps-model.h index 70dd4326..b4f6a21e 100644 --- a/opendps/dps-model.h +++ b/opendps/dps-model.h @@ -75,8 +75,8 @@ #define ADC_CHA_IOUT_GOLDEN_VALUE (0x45) #define A_DAC_K (float)0.642339346880304f #define A_DAC_C (float)300.056571748685f - #define A_ADC_K (float)1.724797241f - #define A_ADC_C (float)-122.2488093f + #define A_ADC_K (float)1.719076520466f + #define A_ADC_C (float)-119.687453381924f #define V_DAC_K (float)0.075587636839016f #define V_DAC_C (float)0.578377373449399f #define V_ADC_K (float)13.2451913879205f From 5f16d52594bf325993d07bceb6466062f79cad8c Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Mon, 30 Sep 2019 12:37:19 -0600 Subject: [PATCH 044/175] Readjusted lower end amperage ADC to prevent noisy 0 --- opendps/dps-model.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opendps/dps-model.h b/opendps/dps-model.h index b4f6a21e..8577b2a3 100644 --- a/opendps/dps-model.h +++ b/opendps/dps-model.h @@ -75,8 +75,8 @@ #define ADC_CHA_IOUT_GOLDEN_VALUE (0x45) #define A_DAC_K (float)0.642339346880304f #define A_DAC_C (float)300.056571748685f - #define A_ADC_K (float)1.719076520466f - #define A_ADC_C (float)-119.687453381924f + #define A_ADC_K (float)1.72894209590626f + #define A_ADC_C (float)-122.667008351117f #define V_DAC_K (float)0.075587636839016f #define V_DAC_C (float)0.578377373449399f #define V_ADC_K (float)13.2451913879205f From 23bd2eb8b3cfa806301ae3e4dc8fa90102fb15aa Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Mon, 30 Sep 2019 21:42:39 -0600 Subject: [PATCH 045/175] Refined values for DPS5005 --- opendps/dps-model.h | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/opendps/dps-model.h b/opendps/dps-model.h index 1d10d7da..2ae4e3f6 100644 --- a/opendps/dps-model.h +++ b/opendps/dps-model.h @@ -60,14 +60,17 @@ #define CONFIG_DPS_MAX_CURRENT (5000) #endif #define ADC_CHA_IOUT_GOLDEN_VALUE (0x45) - #define A_ADC_K (float)1.713f - #define A_ADC_C (float)-118.51f - #define A_DAC_K (float)0.652f - #define A_DAC_C (float)288.611f - #define V_DAC_K (float)0.072f - #define V_DAC_C (float)1.85f - #define V_ADC_K (float)13.164f - #define V_ADC_C (float)-100.751f + #define A_ADC_K (float) 1.71083908618961f + #define A_ADC_C (float) -120.124411804613f + + #define A_DAC_K (float) 0.647948164146868f + #define A_DAC_C (float) 278.025917926566f + + #define V_DAC_K (float) 0.076447899114725f + #define V_DAC_C (float) 3.22404026358549f + + #define V_ADC_K (float) 13.0935331433421f + #define V_ADC_C (float) -105.218043662758f #elif defined(DPS3005) #ifndef CONFIG_DPS_MAX_CURRENT #define CONFIG_DPS_MAX_CURRENT (5000) From cdc1c8097157cd24ceabfc346dff3384a27feb65 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Mon, 30 Sep 2019 21:48:37 -0600 Subject: [PATCH 046/175] Refined v ADC values --- opendps/dps-model.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opendps/dps-model.h b/opendps/dps-model.h index 2ae4e3f6..c4315713 100644 --- a/opendps/dps-model.h +++ b/opendps/dps-model.h @@ -69,8 +69,8 @@ #define V_DAC_K (float) 0.076447899114725f #define V_DAC_C (float) 3.22404026358549f - #define V_ADC_K (float) 13.0935331433421f - #define V_ADC_C (float) -105.218043662758f + #define V_ADC_K (float) 13.0802536979635f + #define V_ADC_C (float) -108.032224145859f #elif defined(DPS3005) #ifndef CONFIG_DPS_MAX_CURRENT #define CONFIG_DPS_MAX_CURRENT (5000) From 57d1facb00819f8129c6a0d170d5e801fc15404f Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Tue, 1 Oct 2019 20:23:10 -0600 Subject: [PATCH 047/175] Added recall code and M1/M2 key combination --- opendps/event.h | 8 +++-- opendps/func_dpsmode.c | 56 ++++++++++++++++++++++++++++- opendps/hw.c | 80 +++++++++++++++++++++++------------------- opendps/opendps.c | 10 +++--- opendps/uui.c | 2 +- opendps/uui.h | 2 +- 6 files changed, 113 insertions(+), 45 deletions(-) diff --git a/opendps/event.h b/opendps/event.h index 1cc33d17..961b2503 100644 --- a/opendps/event.h +++ b/opendps/event.h @@ -31,6 +31,10 @@ typedef enum { event_button_m2, event_buttom_m1_and_m2, event_button_sel, + + event_button_sel_m1, + event_button_sel_m2, + event_button_enable, event_rot_left, event_rot_right, @@ -47,8 +51,8 @@ typedef enum { } event_t; typedef enum { - press_short = 0, - press_long, + press_short = 0, + press_long, } button_press_t; diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 0a116d8c..00742abe 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -36,6 +36,7 @@ #include "font-meter_large.h" #include "hw.h" #include "func_dpsmode.h" +#include "event.h" #include "uui.h" #include "uui_number.h" #include "uui_time.h" @@ -86,6 +87,9 @@ static bool select_mode; // timer static int64_t tick_since_count; +// time for a note to appear in frames drawn +static int32_t note_timeout = 0; + // what is displayed on the 3rd row. static int8_t third_row = 0; ui_item_t *third_item; @@ -98,6 +102,12 @@ enum { CUR_GFX_PP = 4, CUR_GFX_OPP = 8, CUR_GFX_TM = 16, + + // not real graphics, but notices that overlay the screen temporarily + CUR_NOTE_M1_SAVED = 1024, + CUR_NOTE_M1_RECALL = 2048, + CUR_NOTE_M1_SAVED = 4096, + CUR_NOTE_M1_RECALL = 8192, } dpsmode_graphics; #define SCREEN_ID (6) @@ -426,13 +436,14 @@ static void timer_changed(ui_time_t *item) { } -static bool event(uui_t *ui, event_t event) { +static bool event(uui_t *ui, event_t event, uint8_t data) { switch(event) { case event_button_sel: case event_button_m1: case event_button_m2: + // leave single edit mode on any button press if (single_edit_mode) { single_edit_mode = false; @@ -441,6 +452,22 @@ static bool event(uui_t *ui, event_t event) { if (dpsmode_current.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_current); return true; } + + // do recall on press_long event_button_m1 or event_button_m2 + if (event == event_button_m1 && data = press_long) { + // TODO: recall M1 values. + saved_v = 510; + saved_i = 200; + saved_p = 0; + saved_t = 0; + + // show the M1 recall note + dpsmode_graphics |= CUR_NOTE_M1_RECALL; + + dpsmode_enable(false); + } + + break; case event_rot_left_m1: @@ -891,6 +918,33 @@ static void draw_bars() { } + // draw any notes + if (dpsmode_graphics & CUR_NOTE_M1_RECALL) { + note_timeout--; + // expired + if (note_timeout == 0) { + dpsmode_graphics &= ~CUR_NOTE_M1_RECALL; + + } else { + + // border + tft_fill( 10, 50, + TFT_WIDTH - 20, 50 + 40, + WHITE ); + // inside + tft_fill( 11, 51, + TFT_WIDTH - 22, 51 + 38, + BLACK ); + + // message + tft_puts(FONT_FULL_SMALL, "M1 Recalled", + 15, 60, + TFT_WIDTH, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, + WHITE, false); + } + + } + } /* diff --git a/opendps/hw.c b/opendps/hw.c index 4ce6919a..ae0bfe64 100644 --- a/opendps/hw.c +++ b/opendps/hw.c @@ -88,11 +88,10 @@ static volatile uint64_t longpress_start; static volatile bool longpress_detected; /** Used to filter SET press from SET + ROT */ static volatile bool set_pressed = false; -static volatile bool set_skip = false; static volatile bool m1_pressed = false; static volatile bool m2_pressed = false; static volatile bool m1_and_m2_pressed = false; -static volatile bool rot_turned = false; +static volatile bool key_combo = false; #define DEBOUNCE_TIME_MS (30) @@ -837,20 +836,30 @@ void BUTTON_SEL_isr(void) { static bool falling = true; exti_reset_request(BUTTON_SEL_EXTI); + if (falling) { if (is_bouncing()) return; set_pressed = true; - set_skip = false; + key_combo = false; + longpress_begin(event_button_sel); exti_set_trigger(BUTTON_SEL_EXTI, EXTI_TRIGGER_RISING); } else { set_pressed = false; - if (!set_skip) { - if (!longpress_end()) { - // Not a long press, send short press - event_put(event_button_sel, press_short); - } + + if ( ! key_combo && m1_pressed ) { + key_combo = true; + event_put(event_buttom_sel_m1, press_short); + return; } + + if ( ! key_combo && m2_pressed ) { + key_combo = true; + event_put(event_buttom_sel_m1, press_short); + } + + if ( ! longpress_end() && ! key_combo) event_put(event_button_set, press_short); + exti_set_trigger(BUTTON_SEL_EXTI, EXTI_TRIGGER_FALLING); } falling = !falling; @@ -866,27 +875,28 @@ void BUTTON_M1_isr(void) exti_reset_request(BUTTON_M1_EXTI); if (falling) { if (is_bouncing()) return; - m1_pressed = true; - - // do not fire button if rot rotated while down - rot_turned = false; - if (m2_pressed) - m1_and_m2_pressed = true; + m1_pressed = true; + key_combo = false; + longpress_begin(event_button_m1); exti_set_trigger(BUTTON_M1_EXTI, EXTI_TRIGGER_RISING); } else { m1_pressed = false; - if (!m2_pressed) { - if (m1_and_m2_pressed) { - m1_and_m2_pressed = false; - event_put(event_buttom_m1_and_m2, press_short); - } else { - if ( ! rot_turned) event_put(event_button_m1, press_short); - } + if ( ! key_combo && set_pressed ) { + key_combo = true; + event_put(event_buttom_sel_m1, press_short); + return; + } + + if ( ! key_combo && m2_pressed ) { + key_combo = true; + event_put(event_buttom_m1_and_m2, press_short); } + if ( ! longpress_end() && ! key_combo) event_put(event_button_m1, press_short); + exti_set_trigger(BUTTON_M1_EXTI, EXTI_TRIGGER_FALLING); } falling = !falling; @@ -905,23 +915,25 @@ void BUTTON_M2_isr(void) m2_pressed = true; // do not fire button if rot rotated while down - rot_turned = false; + key_combo = false; - if (m1_pressed) - m1_and_m2_pressed = true; exti_set_trigger(BUTTON_M2_EXTI, EXTI_TRIGGER_RISING); } else { m2_pressed = false; - if (!m1_pressed) { - if (m1_and_m2_pressed) { - m1_and_m2_pressed = false; - event_put(event_buttom_m1_and_m2, press_short); - } else { - if ( ! rot_turned) event_put(event_button_m2, press_short); - } + if ( ! key_combo && set_pressed ) { + key_combo = true; + event_put(event_buttom_sel_m2, press_short); + return; } + if ( ! key_combo && m1_pressed ) { + key_combo = true; + event_put(event_buttom_m1_and_m2, press_short); + } + + if ( ! key_combo) event_put(event_button_m2, press_short); + exti_set_trigger(BUTTON_M2_EXTI, EXTI_TRIGGER_FALLING); } falling = !falling; @@ -972,12 +984,10 @@ void BUTTON_ROTARY_isr(void) exti_reset_request(BUTTON_ROT_A_EXTI); bool a = (((uint16_t) GPIO_IDR(BUTTON_ROT_A_PORT)) & BUTTON_ROT_A_PIN) ? 1 : 0; // Slightly faster than gpio_get(...) bool b = (((uint16_t) GPIO_IDR(BUTTON_ROT_B_PORT)) & BUTTON_ROT_B_PIN) ? 1 : 0; - rot_turned = true; + key_combo = true; if (a == b) { if (set_pressed) { - set_skip = true; - (void) longpress_end(); event_put(event_rot_left_set, press_short); } else if (m1_pressed) { event_put(event_rot_left_m1, press_short); @@ -988,8 +998,6 @@ void BUTTON_ROTARY_isr(void) } } else { if (set_pressed) { - set_skip = true; - (void) longpress_end(); event_put(event_rot_right_set, press_short); } else if (m1_pressed) { event_put(event_rot_right_m1, press_short); diff --git a/opendps/opendps.c b/opendps/opendps.c index 29d05b82..25ba7f02 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -509,7 +509,7 @@ static void ui_handle_event(event_t event, uint8_t data) #endif // CONFIG_OCP_DEBUGGING ui_flash(); /** @todo When OCP kicks in, show last I_out on screen */ opendps_update_power_status(false); - uui_handle_screen_event(current_ui, event); + uui_handle_screen_event(current_ui, event, data); } break; case event_ovp: @@ -524,7 +524,7 @@ static void ui_handle_event(event_t event, uint8_t data) #endif // CONFIG_OVP_DEBUGGING ui_flash(); /** @todo When OVP kicks in, show last V_out on screen */ opendps_update_power_status(false); - uui_handle_screen_event(current_ui, event); + uui_handle_screen_event(current_ui, event, data); } break; case event_buttom_m1_and_m2: ; @@ -538,6 +538,8 @@ static void ui_handle_event(event_t event, uint8_t data) case event_button_m1: case event_button_m2: case event_button_sel: + case event_button_sel_m1: + case event_button_sel_m2: case event_rot_press: case event_rot_left: case event_rot_right: @@ -545,7 +547,7 @@ static void ui_handle_event(event_t event, uint8_t data) case event_rot_right_m1: case event_rot_left_m2: case event_rot_right_m2: - uui_handle_screen_event(current_ui, event); + uui_handle_screen_event(current_ui, event, data); uui_refresh(current_ui, false); break; @@ -558,7 +560,7 @@ static void ui_handle_event(event_t event, uint8_t data) break; } - uui_handle_screen_event(current_ui, event); + uui_handle_screen_event(current_ui, event, data); uui_refresh(current_ui, false); break; diff --git a/opendps/uui.c b/opendps/uui.c index f7513670..1da5d9e7 100644 --- a/opendps/uui.c +++ b/opendps/uui.c @@ -149,7 +149,7 @@ void uui_focus(uui_t *ui, ui_item_t *item) { } -void uui_handle_screen_event(uui_t *ui, event_t event) +void uui_handle_screen_event(uui_t *ui, event_t event, uint8_t data) { assert(ui); ui_screen_t *screen = ui->screens[ui->cur_screen]; diff --git a/opendps/uui.h b/opendps/uui.h index 82c2932f..6e5c918e 100644 --- a/opendps/uui.h +++ b/opendps/uui.h @@ -224,7 +224,7 @@ void uui_add_screen(uui_t *ui, ui_screen_t *screen); * @param ui The user interface * @param[in] event The event */ -void uui_handle_screen_event(uui_t *ui, event_t event); +void uui_handle_screen_event(uui_t *ui, event_t event, uint8_t data); /** * @brief Switch to next screen From 0e88aab5fe94795086f1fa3707f00712af0a870a Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Tue, 1 Oct 2019 20:27:16 -0600 Subject: [PATCH 048/175] Fixed broken code --- opendps/func_dpsmode.c | 5 +++-- opendps/hw.c | 14 +++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 00742abe..144b16b0 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -34,6 +34,7 @@ #include "gfx-oppbar.h" #include "gfx-tmbar.h" #include "font-meter_large.h" +#include "font-full_small.h" #include "hw.h" #include "func_dpsmode.h" #include "event.h" @@ -63,7 +64,7 @@ static void timer_changed(ui_time_t *item); static void dpsmode_tick(void); static void activated(void); static void deactivated(void); -static bool event(uui_t *ui, event_t event); +static bool event(uui_t *ui, event_t event, uint8_t data); static void past_save(past_t *past); static void past_restore(past_t *past); static set_param_status_t set_parameter(char *name, char *value); @@ -454,7 +455,7 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { } // do recall on press_long event_button_m1 or event_button_m2 - if (event == event_button_m1 && data = press_long) { + if (event == event_button_m1 && data == press_long) { // TODO: recall M1 values. saved_v = 510; saved_i = 200; diff --git a/opendps/hw.c b/opendps/hw.c index ae0bfe64..c70b3506 100644 --- a/opendps/hw.c +++ b/opendps/hw.c @@ -849,16 +849,16 @@ void BUTTON_SEL_isr(void) if ( ! key_combo && m1_pressed ) { key_combo = true; - event_put(event_buttom_sel_m1, press_short); + event_put(event_button_sel_m1, press_short); return; } if ( ! key_combo && m2_pressed ) { key_combo = true; - event_put(event_buttom_sel_m1, press_short); + event_put(event_button_sel_m1, press_short); } - if ( ! longpress_end() && ! key_combo) event_put(event_button_set, press_short); + if ( ! longpress_end() && ! key_combo) event_put(event_button_sel, press_short); exti_set_trigger(BUTTON_SEL_EXTI, EXTI_TRIGGER_FALLING); } @@ -886,13 +886,13 @@ void BUTTON_M1_isr(void) if ( ! key_combo && set_pressed ) { key_combo = true; - event_put(event_buttom_sel_m1, press_short); + event_put(event_button_sel_m1, press_short); return; } if ( ! key_combo && m2_pressed ) { key_combo = true; - event_put(event_buttom_m1_and_m2, press_short); + event_put(event_button_m1_and_m2, press_short); } if ( ! longpress_end() && ! key_combo) event_put(event_button_m1, press_short); @@ -923,13 +923,13 @@ void BUTTON_M2_isr(void) if ( ! key_combo && set_pressed ) { key_combo = true; - event_put(event_buttom_sel_m2, press_short); + event_put(event_button_sel_m2, press_short); return; } if ( ! key_combo && m1_pressed ) { key_combo = true; - event_put(event_buttom_m1_and_m2, press_short); + event_put(event_button_m1_and_m2, press_short); } if ( ! key_combo) event_put(event_button_m2, press_short); From 685707c8e462c5110898ae5ea4fca44b7ce23391 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Tue, 1 Oct 2019 20:28:18 -0600 Subject: [PATCH 049/175] Fixed bad code --- opendps/event.h | 2 +- opendps/func_dpsmode.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/opendps/event.h b/opendps/event.h index 961b2503..7d4f7046 100644 --- a/opendps/event.h +++ b/opendps/event.h @@ -29,7 +29,7 @@ typedef enum { event_none = 0, event_button_m1, event_button_m2, - event_buttom_m1_and_m2, + event_button_m1_and_m2, event_button_sel, event_button_sel_m1, diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 144b16b0..e764eea2 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -107,8 +107,8 @@ enum { // not real graphics, but notices that overlay the screen temporarily CUR_NOTE_M1_SAVED = 1024, CUR_NOTE_M1_RECALL = 2048, - CUR_NOTE_M1_SAVED = 4096, - CUR_NOTE_M1_RECALL = 8192, + CUR_NOTE_M2_SAVED = 4096, + CUR_NOTE_M2_RECALL = 8192, } dpsmode_graphics; #define SCREEN_ID (6) From baa540f702d3eebf4cb7f001bf7e72076101a946 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Tue, 1 Oct 2019 20:29:02 -0600 Subject: [PATCH 050/175] buttom is button --- opendps/opendps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opendps/opendps.c b/opendps/opendps.c index 25ba7f02..6abf1887 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -527,7 +527,7 @@ static void ui_handle_event(event_t event, uint8_t data) uui_handle_screen_event(current_ui, event, data); } break; - case event_buttom_m1_and_m2: ; + case event_button_m1_and_m2: ; uint8_t target_screen_id = current_ui == &func_ui ? SETTINGS_UI_ID : FUNC_UI_ID; /** Change between the settings and functional screen */ opendps_change_screen(target_screen_id); break; From e5c7ddf0df6e95878795a62e1f69ed59eea72143 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Tue, 1 Oct 2019 20:35:07 -0600 Subject: [PATCH 051/175] Handled the new events --- opendps/func_dpsmode.c | 1 + opendps/uui.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index e764eea2..88dbb70d 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -463,6 +463,7 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { saved_t = 0; // show the M1 recall note + note_timeout = 50; dpsmode_graphics |= CUR_NOTE_M1_RECALL; dpsmode_enable(false); diff --git a/opendps/uui.c b/opendps/uui.c index 1da5d9e7..8758263c 100644 --- a/opendps/uui.c +++ b/opendps/uui.c @@ -178,6 +178,8 @@ void uui_handle_screen_event(uui_t *ui, event_t event, uint8_t data) case event_rot_right_m1: case event_rot_left_m2: case event_rot_right_m2: + case event_button_sel_m1: + case event_button_sel_m2: // do nothing break; From 5b983a019aa2159bc1452f0c9d3371c4f8ea95db Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Tue, 1 Oct 2019 20:38:20 -0600 Subject: [PATCH 052/175] Drawing note over everything --- opendps/func_dpsmode.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 88dbb70d..50dae39e 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -457,13 +457,13 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { // do recall on press_long event_button_m1 or event_button_m2 if (event == event_button_m1 && data == press_long) { // TODO: recall M1 values. - saved_v = 510; + saved_v = 5100; saved_i = 200; saved_p = 0; saved_t = 0; // show the M1 recall note - note_timeout = 50; + note_timeout = 500; dpsmode_graphics |= CUR_NOTE_M1_RECALL; dpsmode_enable(false); @@ -924,7 +924,7 @@ static void draw_bars() { if (dpsmode_graphics & CUR_NOTE_M1_RECALL) { note_timeout--; // expired - if (note_timeout == 0) { + if (note_timeout <= 0) { dpsmode_graphics &= ~CUR_NOTE_M1_RECALL; } else { @@ -947,6 +947,23 @@ static void draw_bars() { } + + // border + tft_fill( 10, 50, + TFT_WIDTH - 20, 50 + 40, + WHITE ); + // inside + tft_fill( 11, 51, + TFT_WIDTH - 22, 51 + 38, + BLACK ); + + // message + tft_puts(FONT_FULL_SMALL, "M1 Recalled", + 15, 60, + TFT_WIDTH, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, + WHITE, false); + + } /* From 1c45ec28c6461fc9e669608b9f34ef25f342d078 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Tue, 1 Oct 2019 21:12:47 -0600 Subject: [PATCH 053/175] Added M1 graphics instead of drawing something manually --- opendps/func_dpsmode.c | 60 +++++++------------------------------- opendps/gfx-m1bar.c | 38 ++++++++++++++++++++++++ opendps/gfx-m1bar.h | 13 +++++++++ opendps/gfx/png/m1bar.png | Bin 0 -> 993 bytes 4 files changed, 62 insertions(+), 49 deletions(-) create mode 100644 opendps/gfx-m1bar.c create mode 100644 opendps/gfx-m1bar.h create mode 100644 opendps/gfx/png/m1bar.png diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 50dae39e..7ac3b762 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -33,6 +33,7 @@ #include "gfx-ppbar.h" #include "gfx-oppbar.h" #include "gfx-tmbar.h" +#include "gfx-m1bar.h" #include "font-meter_large.h" #include "font-full_small.h" #include "hw.h" @@ -88,9 +89,6 @@ static bool select_mode; // timer static int64_t tick_since_count; -// time for a note to appear in frames drawn -static int32_t note_timeout = 0; - // what is displayed on the 3rd row. static int8_t third_row = 0; ui_item_t *third_item; @@ -104,11 +102,8 @@ enum { CUR_GFX_OPP = 8, CUR_GFX_TM = 16, - // not real graphics, but notices that overlay the screen temporarily - CUR_NOTE_M1_SAVED = 1024, - CUR_NOTE_M1_RECALL = 2048, - CUR_NOTE_M2_SAVED = 4096, - CUR_NOTE_M2_RECALL = 8192, + CUR_GFX_M1_RECALL = 1024, + CUR_GFX_M2_RECALL = 2048, } dpsmode_graphics; #define SCREEN_ID (6) @@ -396,6 +391,7 @@ static void dpsmode_enable(bool enabled) */ static void voltage_changed(ui_number_t *item) { + dpsmode_graphics &= ~CUR_GFX_M1_RECALL & ~CUR_GFX_M2_RECALL; saved_v = item->value; (void) pwrctl_set_vout(item->value); } @@ -407,6 +403,7 @@ static void voltage_changed(ui_number_t *item) */ static void current_changed(ui_number_t *item) { + dpsmode_graphics &= ~CUR_GFX_M1_RECALL & ~CUR_GFX_M2_RECALL; saved_i = item->value; (void) pwrctl_set_iout(item->value); } @@ -418,6 +415,7 @@ static void current_changed(ui_number_t *item) */ static void power_changed(ui_number_t *item) { + dpsmode_graphics &= ~CUR_GFX_M1_RECALL & ~CUR_GFX_M2_RECALL; saved_p = item->value; // (void) pwrctl_set_iout(item->value); } @@ -463,8 +461,7 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { saved_t = 0; // show the M1 recall note - note_timeout = 500; - dpsmode_graphics |= CUR_NOTE_M1_RECALL; + dpsmode_graphics |= CUR_GFX_M1_RECALL; dpsmode_enable(false); } @@ -921,49 +918,14 @@ static void draw_bars() { // draw any notes - if (dpsmode_graphics & CUR_NOTE_M1_RECALL) { - note_timeout--; - // expired - if (note_timeout <= 0) { - dpsmode_graphics &= ~CUR_NOTE_M1_RECALL; - - } else { - - // border - tft_fill( 10, 50, - TFT_WIDTH - 20, 50 + 40, - WHITE ); - // inside - tft_fill( 11, 51, - TFT_WIDTH - 22, 51 + 38, - BLACK ); - - // message - tft_puts(FONT_FULL_SMALL, "M1 Recalled", - 15, 60, - TFT_WIDTH, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, - WHITE, false); + if (dpsmode_graphics & CUR_GFX_M1_RECALL) { + tft_fill(5, 0, + GFX_M1BAR_WIDTH, GFX_M1BAR_HEIGHT, + BLACK); } - } - // border - tft_fill( 10, 50, - TFT_WIDTH - 20, 50 + 40, - WHITE ); - // inside - tft_fill( 11, 51, - TFT_WIDTH - 22, 51 + 38, - BLACK ); - - // message - tft_puts(FONT_FULL_SMALL, "M1 Recalled", - 15, 60, - TFT_WIDTH, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, - WHITE, false); - - } /* diff --git a/opendps/gfx-m1bar.c b/opendps/gfx-m1bar.c new file mode 100644 index 00000000..8e7b6d37 --- /dev/null +++ b/opendps/gfx-m1bar.c @@ -0,0 +1,38 @@ +/** Gfx generated from gfx/png/m1bar.png */ + +#include "gfx-m1bar.h" + +const uint8_t gfx_m1bar[500] = { + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0xfe, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, + 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, + 0xfe, 0xc0, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0x00, 0x00 +}; \ No newline at end of file diff --git a/opendps/gfx-m1bar.h b/opendps/gfx-m1bar.h new file mode 100644 index 00000000..2ae318c2 --- /dev/null +++ b/opendps/gfx-m1bar.h @@ -0,0 +1,13 @@ +/** Gfx generated from gfx/png/m1bar.png */ + +#ifndef __GFX_M1BAR_H__ +#define __GFX_M1BAR_H__ + +#include + +#define GFX_M1BAR_HEIGHT (10) +#define GFX_M1BAR_WIDTH (25) + +extern const uint8_t gfx_m1bar[500]; + +#endif // __GFX_M1BAR_H__ \ No newline at end of file diff --git a/opendps/gfx/png/m1bar.png b/opendps/gfx/png/m1bar.png new file mode 100644 index 0000000000000000000000000000000000000000..405f49bd4a09a14bb627607f7b1990950f9045d9 GIT binary patch literal 993 zcmaJ=J#5oJ7%Kmu$h6SFhvMV{0H$x4zy!o97E$>t; zXJ_4!U3T_5m`M~$;3Hy##NP;FB~jT9uR_nM8M2_`Le^FGD5;vc2s9iakmK?hN04&h zs>})btR%}&J4CRGV!RbOba0KyG*qZ)5wZ!6EQ~jLU0iHo zg5wqrfu^Nhlfm?g7r3|`U+!Q`Qz-{Au>%K{b(N(ooaecUR?v;SqzMLHf?&u6qbTY| zK@%k@TNHA0J*hjov!;y`RF2S22dbrgAbkz0ze4?1Nl-oRXnrGb21tUEXt zejpaoWMDenzlPm2Q3a*PzI5rOFMbqI#Ya@yrCYy#(`T_%*5|C`bKTwl`DAEfS}0D0 zn+vD+!L!>_qayQ#SO@xzk*E0!qr2a^S8JEn&c3`OJuaMLKdpYG9`1Yc* gcW>7kPliu`1LobgGw;tYz34o;vQg2W7uW9p0p%Ptd;kCd literal 0 HcmV?d00001 From 2975408b7edd1ac756f4cb8800fbd1ad08a0c469 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Tue, 1 Oct 2019 21:13:48 -0600 Subject: [PATCH 054/175] Extra bracket --- opendps/func_dpsmode.c | 1 - 1 file changed, 1 deletion(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 7ac3b762..99ba8904 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -922,7 +922,6 @@ static void draw_bars() { tft_fill(5, 0, GFX_M1BAR_WIDTH, GFX_M1BAR_HEIGHT, BLACK); - } } From 7e5b4569162088c991436c9e7109550b5ac18c40 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Tue, 1 Oct 2019 21:15:23 -0600 Subject: [PATCH 055/175] Handle long press m1 --- opendps/func_dpsmode.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 99ba8904..406e51d9 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -442,16 +442,6 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { case event_button_m1: case event_button_m2: - // leave single edit mode on any button press - if (single_edit_mode) { - single_edit_mode = false; - - // toggle focus on anything that is in focus (to unfocus) - if (dpsmode_voltage.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_voltage); - if (dpsmode_current.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_current); - return true; - } - // do recall on press_long event_button_m1 or event_button_m2 if (event == event_button_m1 && data == press_long) { // TODO: recall M1 values. @@ -464,6 +454,19 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { dpsmode_graphics |= CUR_GFX_M1_RECALL; dpsmode_enable(false); + + return true; + } + + + // leave single edit mode on any button press + if (single_edit_mode) { + single_edit_mode = false; + + // toggle focus on anything that is in focus (to unfocus) + if (dpsmode_voltage.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_voltage); + if (dpsmode_current.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_current); + return true; } From 5540a2cff9e8df7b678946b182bd64ea1c323e76 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Tue, 1 Oct 2019 21:31:54 -0600 Subject: [PATCH 056/175] Added recall code --- opendps/Makefile | 2 + opendps/func_dpsmode.c | 100 +++++++++++++++++++++++++++++--------- opendps/gfx-m2bar.c | 38 +++++++++++++++ opendps/gfx-m2bar.h | 13 +++++ opendps/gfx/png/m2bar.png | Bin 0 -> 1011 bytes 5 files changed, 129 insertions(+), 24 deletions(-) create mode 100644 opendps/gfx-m2bar.c create mode 100644 opendps/gfx-m2bar.h create mode 100644 opendps/gfx/png/m2bar.png diff --git a/opendps/Makefile b/opendps/Makefile index f1c6aba2..7e93ba09 100644 --- a/opendps/Makefile +++ b/opendps/Makefile @@ -109,6 +109,8 @@ OBJS = \ gfx-ppbar.o \ gfx-oppbar.o \ gfx-tmbar.o \ + gfx-m1bar.o \ + gfx-m2bar.o \ gfx-padlock.o \ gfx-power.o \ gfx-thermometer.o \ diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 406e51d9..68488e5e 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -34,6 +34,7 @@ #include "gfx-oppbar.h" #include "gfx-tmbar.h" #include "gfx-m1bar.h" +#include "gfx-m2bar.h" #include "font-meter_large.h" #include "font-full_small.h" #include "hw.h" @@ -80,6 +81,8 @@ static void clear_third_region(void); * be replaced with measurements when output is active */ static int32_t saved_v, saved_i, saved_p, saved_t; +// the M1, M2 recall values +static int32_t[2] recall_v, recall_i, recall_p, recall_t = {0, 0}; // single edit mode, with M1/M2 buttons, not select. // pressing any other button when in this mode will exit the edit mode @@ -444,17 +447,29 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { // do recall on press_long event_button_m1 or event_button_m2 if (event == event_button_m1 && data == press_long) { - // TODO: recall M1 values. - saved_v = 5100; - saved_i = 200; - saved_p = 0; - saved_t = 0; + saved_v = recall_v[0]; + saved_i = recall_i[0]; + saved_p = recall_p[0]; + saved_t = recall_t[0]; - // show the M1 recall note + // Turn off power + dpsmode_enable(false); + + // show the M1 recall graphics dpsmode_graphics |= CUR_GFX_M1_RECALL; + return true; + } + if (event == event_button_m2 && data == press_long) { + saved_v = recall_v[1]; + saved_i = recall_i[1]; + saved_p = recall_p[1]; + saved_t = recall_t[1]; + // Turn off power dpsmode_enable(false); + // show the M2 recall graphics + dpsmode_graphics |= CUR_GFX_M2_RECALL; return true; } @@ -618,18 +633,27 @@ static void deactivated(void) */ static void past_save(past_t *past) { - /** @todo: past bug causes corruption for units smaller than 4 bytes (#27) */ - if (!past_write_unit(past, (SCREEN_ID << 24) | PAST_V, (void*) &saved_v, 4 /* sizeof(dpsmode_voltage.value) */ )) { - /** @todo: handle past write failures */ - } - if (!past_write_unit(past, (SCREEN_ID << 24) | PAST_I, (void*) &saved_i, 4 /* sizeof(dpsmode_current.value) */ )) { - /** @todo: handle past write failures */ + if ( past_write_unit(past, (SCREEN_ID << 24) | PAST_V, (void*) &saved_v, 4) + && past_write_unit(past, (SCREEN_ID << 24) | PAST_I, (void*) &saved_i, 4) + && past_write_unit(past, (SCREEN_ID << 24) | PAST_P, (void*) &saved_p, 4) + && past_write_unit(past, (SCREEN_ID << 24) | PAST_T, (void*) &saved_t, 4)) { + // write successful } - if (!past_write_unit(past, (SCREEN_ID << 24) | PAST_P, (void*) &saved_p, 4 /* sizeof(dpsmode_power.value) */ )) { - /** @todo: handle past write failures */ + + // recall m1 + if ( past_write_unit(past, (SCREEN_ID << 24) | (PAST_V << 2), (void*) &recall_v[0], 4) + && past_write_unit(past, (SCREEN_ID << 24) | (PAST_I << 2), (void*) &recall_i[0], 4) + && past_write_unit(past, (SCREEN_ID << 24) | (PAST_P << 2), (void*) &recall_p[0], 4) + && past_write_unit(past, (SCREEN_ID << 24) | (PAST_T << 2), (void*) &recall_t[0], 4)) { + // write successful } - if (!past_write_unit(past, (SCREEN_ID << 24) | PAST_T, (void*) &saved_t, 4 /* sizeof(dpsmode_power.value) */ )) { - /** @todo: handle past write failures */ + + // recall m2 + if ( past_write_unit(past, (SCREEN_ID << 24) | (PAST_V << 4), (void*) &recall_v[1], 4) + && past_write_unit(past, (SCREEN_ID << 24) | (PAST_I << 4), (void*) &recall_i[1], 4) + && past_write_unit(past, (SCREEN_ID << 24) | (PAST_P << 4), (void*) &recall_p[1], 4) + && past_write_unit(past, (SCREEN_ID << 24) | (PAST_T << 4), (void*) &recall_t[1], 4)) { + // write successful } } @@ -642,22 +666,46 @@ static void past_restore(past_t *past) { uint32_t length; uint32_t *p = 0; + if (past_read_unit(past, (SCREEN_ID << 24) | PAST_V, (const void**) &p, &length)) { saved_v = dpsmode_voltage.value = *p; - (void) length; } if (past_read_unit(past, (SCREEN_ID << 24) | PAST_I, (const void**) &p, &length)) { saved_i = dpsmode_current.value = *p; - (void) length; } if (past_read_unit(past, (SCREEN_ID << 24) | PAST_P, (const void**) &p, &length)) { saved_p = dpsmode_power.value = *p; - (void) length; } if (past_read_unit(past, (SCREEN_ID << 24) | PAST_T, (const void**) &p, &length)) { saved_t = dpsmode_timer.value = *p; - (void) length; } + + if (past_read_unit(past, (SCREEN_ID << 24) | (PAST_V << 2), (const void**) &p, &length)) { + recall_v[0] = *p; + } + if (past_read_unit(past, (SCREEN_ID << 24) | (PAST_I << 2), (const void**) &p, &length)) { + recall_i[0] = *p; + } + if (past_read_unit(past, (SCREEN_ID << 24) | (PAST_P << 2), (const void**) &p, &length)) { + recall_p[0] = *p; + } + if (past_read_unit(past, (SCREEN_ID << 24) | (PAST_T << 2), (const void**) &p, &length)) { + recall_t[0] = *p; + } + + if (past_read_unit(past, (SCREEN_ID << 24) | (PAST_V << 4), (const void**) &p, &length)) { + recall_v[1] = *p; + } + if (past_read_unit(past, (SCREEN_ID << 24) | (PAST_I << 4), (const void**) &p, &length)) { + recall_i[1] = *p; + } + if (past_read_unit(past, (SCREEN_ID << 24) | (PAST_P << 4), (const void**) &p, &length)) { + recall_p[1] = *p; + } + if (past_read_unit(past, (SCREEN_ID << 24) | (PAST_T << 4), (const void**) &p, &length)) { + recall_t[1] = *p; + } + } /** @@ -920,11 +968,15 @@ static void draw_bars() { } - // draw any notes + // draw any recall icons if (dpsmode_graphics & CUR_GFX_M1_RECALL) { - tft_fill(5, 0, - GFX_M1BAR_WIDTH, GFX_M1BAR_HEIGHT, - BLACK); + tft_blit((uint16_t*) gfx_m1bar, + GFX_M1BAR_WIDTH, GFX_M1BAR_HEIGHT, + 5, 0); + } else if (dpsmode_graphics & CUR_GFX_M2_RECALL) { + tft_blit((uint16_t*) gfx_m2bar, + GFX_M2BAR_WIDTH, GFX_M2BAR_HEIGHT, + 5, 0); } diff --git a/opendps/gfx-m2bar.c b/opendps/gfx-m2bar.c new file mode 100644 index 00000000..2a937702 --- /dev/null +++ b/opendps/gfx-m2bar.c @@ -0,0 +1,38 @@ +/** Gfx generated from gfx/png/m2bar.png */ + +#include "gfx-m2bar.h" + +const uint8_t gfx_m2bar[500] = { + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0xfe, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, + 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, + 0xfe, 0xc0, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0x00, 0x00 +}; \ No newline at end of file diff --git a/opendps/gfx-m2bar.h b/opendps/gfx-m2bar.h new file mode 100644 index 00000000..9263e559 --- /dev/null +++ b/opendps/gfx-m2bar.h @@ -0,0 +1,13 @@ +/** Gfx generated from gfx/png/m2bar.png */ + +#ifndef __GFX_M2BAR_H__ +#define __GFX_M2BAR_H__ + +#include + +#define GFX_M2BAR_HEIGHT (10) +#define GFX_M2BAR_WIDTH (25) + +extern const uint8_t gfx_m2bar[500]; + +#endif // __GFX_M2BAR_H__ \ No newline at end of file diff --git a/opendps/gfx/png/m2bar.png b/opendps/gfx/png/m2bar.png new file mode 100644 index 0000000000000000000000000000000000000000..7da0936610c6d23a26e800f25bb5a70a8811d6b7 GIT binary patch literal 1011 zcmaJ=&ui0A9M4vfu`$>{oO1}zRCL0cUrpO3ERL?pT)~Xc71rIBCa-JQl9wf~HX9yf zHxI)80(VkG`~m7g^k5lYb`cMrynFGWx9ueO(zTrjYaq#ckMHO6{d~XQ&wF4j-yR*l zJWNs4XmLp`k^dxlhld8q_w!M8AU?oa1+SnQZkhq4@;0hMP;|`=Sc0a#vwZ~TC@OK? zDOYeszav}7Wz0B+iCmwcDQa#$@=a?KVo-$}j;GMSK76EsV=MG(M(1?D0PD`uZU9$y zm&?}frX|_*{4FpS$%Md#*aVTg<%M#j&~09stm9*r2JH~MsnDmQD!Ks*D1actWK$L| zW590{T{6scG^T5 z#zv;k@(dT3)D6`2|A)G6FFM2}c&7KC#9?{IhinOks1aCXaJ6Kd%9jfPG%*Uw2yJz{ zXw(r#VIBFPP>8!Gf$3Gpvr#j=*~aL)T=YV0dKN6I3QbrT$FXIe&*Vf^6E(4r;dxD3 z$mb+Aoz?PuF0E>U*u|>IYPitDU95eE&Gf~_c5r=?S%raf7ut&fazVRn+3BxE=*!o^ z+Wobp`(jxlhK+~&*RZ=s#6j`0XI--CnIC$@@d2^++ZSJdlWSoW)qFYnR<+-q91KiO z^9z&ywm3dJu{L^%j^8*iC;>5w)SmWul@h9tvYwt(cmU;2@_sW&QlbOdq4{Kvr z-+UPyd6mELDVc5UtxOpSjlepGr_hIr)5wsT%P$ENaW@%Z2s5Kl*<; AQUCw| literal 0 HcmV?d00001 From 85bac08fb23f88acf820e9efbaf677c361bf7117 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Tue, 1 Oct 2019 21:37:21 -0600 Subject: [PATCH 057/175] Recall values should be saved --- opendps/func_dpsmode.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 68488e5e..a55d212c 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -82,7 +82,7 @@ static void clear_third_region(void); */ static int32_t saved_v, saved_i, saved_p, saved_t; // the M1, M2 recall values -static int32_t[2] recall_v, recall_i, recall_p, recall_t = {0, 0}; +static int32_t recall_v[2], recall_i[2], recall_p[2], recall_t[2] = {0, 0}; // single edit mode, with M1/M2 buttons, not select. // pressing any other button when in this mode will exit the edit mode @@ -394,7 +394,9 @@ static void dpsmode_enable(bool enabled) */ static void voltage_changed(ui_number_t *item) { - dpsmode_graphics &= ~CUR_GFX_M1_RECALL & ~CUR_GFX_M2_RECALL; + dpsmode_graphics &= ~CUR_GFX_M1_RECALL; + dpsmode_graphics &= ~CUR_GFX_M2_RECALL; + saved_v = item->value; (void) pwrctl_set_vout(item->value); } @@ -406,7 +408,9 @@ static void voltage_changed(ui_number_t *item) */ static void current_changed(ui_number_t *item) { - dpsmode_graphics &= ~CUR_GFX_M1_RECALL & ~CUR_GFX_M2_RECALL; + dpsmode_graphics &= ~CUR_GFX_M1_RECALL; + dpsmode_graphics &= ~CUR_GFX_M2_RECALL; + saved_i = item->value; (void) pwrctl_set_iout(item->value); } @@ -418,7 +422,9 @@ static void current_changed(ui_number_t *item) */ static void power_changed(ui_number_t *item) { - dpsmode_graphics &= ~CUR_GFX_M1_RECALL & ~CUR_GFX_M2_RECALL; + dpsmode_graphics &= ~CUR_GFX_M1_RECALL; + dpsmode_graphics &= ~CUR_GFX_M2_RECALL; + saved_p = item->value; // (void) pwrctl_set_iout(item->value); } @@ -433,6 +439,9 @@ static void watthour_changed(ui_number_t *item) { } static void timer_changed(ui_time_t *item) { + dpsmode_graphics &= ~CUR_GFX_M1_RECALL; + dpsmode_graphics &= ~CUR_GFX_M2_RECALL; + // do nothing yet... saved_t = item->value; } @@ -441,6 +450,23 @@ static void timer_changed(ui_time_t *item) { static bool event(uui_t *ui, event_t event, uint8_t data) { switch(event) { + case event_button_sel_m1: + case event_button_sel_m2: + // save values to recall + if (event == event_button_sel_m1) { + recall_v[0] = saved_v; + recall_i[0] = saved_i; + recall_p[0] = saved_p; + recall_t[0] = saved_t; + } else { + recall_v[1] = saved_v; + recall_i[1] = saved_i; + recall_p[1] = saved_p; + recall_t[1] = saved_t; + } + + return true; + case event_button_sel: case event_button_m1: case event_button_m2: From 2f3493b52b19a21f8a854f98bfb77dad400030f5 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Tue, 1 Oct 2019 21:38:55 -0600 Subject: [PATCH 058/175] Removed thermometer to save space --- opendps/Makefile | 1 - opendps/opendps.c | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/opendps/Makefile b/opendps/Makefile index 7e93ba09..c05aeaf9 100644 --- a/opendps/Makefile +++ b/opendps/Makefile @@ -113,7 +113,6 @@ OBJS = \ gfx-m2bar.o \ gfx-padlock.o \ gfx-power.o \ - gfx-thermometer.o \ gfx-wifi.o \ opendps.o diff --git a/opendps/opendps.c b/opendps/opendps.c index 6abf1887..f0533d61 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -41,7 +41,7 @@ #include "serialhandler.h" #include "ili9163c.h" #include "gfx-padlock.h" -#include "gfx-thermometer.h" +// #include "gfx-thermometer.h" #include "gfx-power.h" #include "gfx-wifi.h" #include "font-full_small.h" @@ -605,7 +605,7 @@ void opendps_temperature_lock(bool lock) tft_clear(); uui_show(current_ui, false); uui_show(&main_ui, false); - tft_blit((uint16_t*) gfx_thermometer, GFX_THERMOMETER_WIDTH, GFX_THERMOMETER_HEIGHT, 1+(ui_width-GFX_THERMOMETER_WIDTH)/2, 30); + // tft_blit((uint16_t*) gfx_thermometer, GFX_THERMOMETER_WIDTH, GFX_THERMOMETER_HEIGHT, 1+(ui_width-GFX_THERMOMETER_WIDTH)/2, 30); } else { emu_printf("DPS enabled due to temperature\n"); tft_clear(); From 19834d44459fb40817982f300688bdfcb0d849b5 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Tue, 1 Oct 2019 21:44:54 -0600 Subject: [PATCH 059/175] M2 button should now work --- opendps/func_dpsmode.c | 6 ++++++ opendps/hw.c | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index a55d212c..ebbb1d40 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -482,6 +482,7 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { dpsmode_enable(false); // show the M1 recall graphics + dpsmode_graphics &= ~CUR_GFX_M2_RECALL; dpsmode_graphics |= CUR_GFX_M1_RECALL; return true; } @@ -495,6 +496,7 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { dpsmode_enable(false); // show the M2 recall graphics + dpsmode_graphics &= ~CUR_GFX_M1_RECALL; dpsmode_graphics |= CUR_GFX_M2_RECALL; return true; } @@ -1003,6 +1005,10 @@ static void draw_bars() { tft_blit((uint16_t*) gfx_m2bar, GFX_M2BAR_WIDTH, GFX_M2BAR_HEIGHT, 5, 0); + } else { + tft_fill(5, 0 + GFX_M2BAR_WIDTH, GFX_M2BAR_HEIGHT, + BLACK); } diff --git a/opendps/hw.c b/opendps/hw.c index c70b3506..c8e89a87 100644 --- a/opendps/hw.c +++ b/opendps/hw.c @@ -917,6 +917,7 @@ void BUTTON_M2_isr(void) // do not fire button if rot rotated while down key_combo = false; + longpress_begin(event_button_m1); exti_set_trigger(BUTTON_M2_EXTI, EXTI_TRIGGER_RISING); } else { m2_pressed = false; @@ -932,7 +933,7 @@ void BUTTON_M2_isr(void) event_put(event_button_m1_and_m2, press_short); } - if ( ! key_combo) event_put(event_button_m2, press_short); + if ( ! longpress_end() && ! key_combo) event_put(event_button_m2, press_short); exti_set_trigger(BUTTON_M2_EXTI, EXTI_TRIGGER_FALLING); } From cccde95fa164e55a5e4b8b92778e5ca5373ded99 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Tue, 1 Oct 2019 21:45:37 -0600 Subject: [PATCH 060/175] Fixed bad fill --- opendps/func_dpsmode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index ebbb1d40..c1740a3b 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -1006,7 +1006,7 @@ static void draw_bars() { GFX_M2BAR_WIDTH, GFX_M2BAR_HEIGHT, 5, 0); } else { - tft_fill(5, 0 + tft_fill(5, 0, GFX_M2BAR_WIDTH, GFX_M2BAR_HEIGHT, BLACK); } From 1997bbdee49671d00aacf7e2706d04c2c9ab9ca3 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Tue, 1 Oct 2019 21:47:19 -0600 Subject: [PATCH 061/175] M2 button should trigger --- opendps/func_dpsmode.c | 4 ++-- opendps/hw.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index c1740a3b..7c05ee66 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -117,8 +117,8 @@ enum { #define XPOS_CCCV (25) #define XPOS_METER (117) -#define YPOS_VOLTAGE (10) -#define YPOS_CURRENT (45) +#define YPOS_VOLTAGE (11) +#define YPOS_CURRENT (46) #define YPOS_POWER (80) /* Overriding white color */ diff --git a/opendps/hw.c b/opendps/hw.c index c8e89a87..a3d5895b 100644 --- a/opendps/hw.c +++ b/opendps/hw.c @@ -917,7 +917,7 @@ void BUTTON_M2_isr(void) // do not fire button if rot rotated while down key_combo = false; - longpress_begin(event_button_m1); + longpress_begin(event_button_m2); exti_set_trigger(BUTTON_M2_EXTI, EXTI_TRIGGER_RISING); } else { m2_pressed = false; From d62c0fb65cf9e1b29caa1ee5c81fd144ba26097a Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Tue, 1 Oct 2019 21:51:31 -0600 Subject: [PATCH 062/175] Show m1/m2 when saving --- opendps/func_dpsmode.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 7c05ee66..80d210a9 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -454,15 +454,21 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { case event_button_sel_m2: // save values to recall if (event == event_button_sel_m1) { + // save values to m1, show m1 graphics recall_v[0] = saved_v; recall_i[0] = saved_i; recall_p[0] = saved_p; recall_t[0] = saved_t; + dpsmode_graphics &= ~CUR_GFX_M2_RECALL; + dpsmode_graphics |= CUR_GFX_M1_RECALL; } else { + // save values to m2, show m2 graphics recall_v[1] = saved_v; recall_i[1] = saved_i; recall_p[1] = saved_p; recall_t[1] = saved_t; + dpsmode_graphics &= ~CUR_GFX_M1_RECALL; + dpsmode_graphics |= CUR_GFX_M2_RECALL; } return true; @@ -1000,11 +1006,11 @@ static void draw_bars() { if (dpsmode_graphics & CUR_GFX_M1_RECALL) { tft_blit((uint16_t*) gfx_m1bar, GFX_M1BAR_WIDTH, GFX_M1BAR_HEIGHT, - 5, 0); + TFT_WIDTH - GFXM1BAR_WIDTH - 5, 0); } else if (dpsmode_graphics & CUR_GFX_M2_RECALL) { tft_blit((uint16_t*) gfx_m2bar, GFX_M2BAR_WIDTH, GFX_M2BAR_HEIGHT, - 5, 0); + TFT_WIDTH - GFXM2BAR_WIDTH - 5, 0); } else { tft_fill(5, 0, GFX_M2BAR_WIDTH, GFX_M2BAR_HEIGHT, From ea34e92dc825a77012f56418eba4eff02a55b905 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Tue, 1 Oct 2019 21:52:07 -0600 Subject: [PATCH 063/175] Fixed bad gfx name --- opendps/func_dpsmode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 80d210a9..b4eb3d53 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -1006,11 +1006,11 @@ static void draw_bars() { if (dpsmode_graphics & CUR_GFX_M1_RECALL) { tft_blit((uint16_t*) gfx_m1bar, GFX_M1BAR_WIDTH, GFX_M1BAR_HEIGHT, - TFT_WIDTH - GFXM1BAR_WIDTH - 5, 0); + TFT_WIDTH - GFX_M1BAR_WIDTH - 5, 0); } else if (dpsmode_graphics & CUR_GFX_M2_RECALL) { tft_blit((uint16_t*) gfx_m2bar, GFX_M2BAR_WIDTH, GFX_M2BAR_HEIGHT, - TFT_WIDTH - GFXM2BAR_WIDTH - 5, 0); + TFT_WIDTH - GFX_M2BAR_WIDTH - 5, 0); } else { tft_fill(5, 0, GFX_M2BAR_WIDTH, GFX_M2BAR_HEIGHT, From 776c0898d696d65adebcf1d3b644867f5b6c3fd3 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Tue, 1 Oct 2019 21:53:13 -0600 Subject: [PATCH 064/175] Clear m1/m2 bar properly --- opendps/func_dpsmode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index b4eb3d53..0cddaed8 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -1012,7 +1012,7 @@ static void draw_bars() { GFX_M2BAR_WIDTH, GFX_M2BAR_HEIGHT, TFT_WIDTH - GFX_M2BAR_WIDTH - 5, 0); } else { - tft_fill(5, 0, + tft_fill(TFT_WIDTH - GFX_M1BAR_WIDTH - 5, 0, GFX_M2BAR_WIDTH, GFX_M2BAR_HEIGHT, BLACK); } From d7640b5124090238fe237755da09dffc93c66095 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Tue, 1 Oct 2019 21:56:26 -0600 Subject: [PATCH 065/175] Clear all does not clear m1/m2 --- opendps/func_dpsmode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 0cddaed8..00a8a84c 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -1028,7 +1028,7 @@ static void draw_bars() { static void clear_bars(bool all) { if (all) { // clears opp as well as the others - dpsmode_graphics = CUR_GFX_NOT_DRAWN; + dpsmode_graphics &= ~0x3ff; // exclude m1/m2, so not CUR_GFX_NOT_DRAWN; return; } From 1908b69e845b14ebe7ed2b1f1d3d2f11c5cb9616 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Tue, 1 Oct 2019 21:59:23 -0600 Subject: [PATCH 066/175] Power off also updates status --- opendps/func_dpsmode.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 00a8a84c..82c5911c 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -486,6 +486,7 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { // Turn off power dpsmode_enable(false); + opendps_update_power_status(false); // show the M1 recall graphics dpsmode_graphics &= ~CUR_GFX_M2_RECALL; @@ -500,6 +501,7 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { // Turn off power dpsmode_enable(false); + opendps_update_power_status(false); // show the M2 recall graphics dpsmode_graphics &= ~CUR_GFX_M1_RECALL; @@ -1006,13 +1008,13 @@ static void draw_bars() { if (dpsmode_graphics & CUR_GFX_M1_RECALL) { tft_blit((uint16_t*) gfx_m1bar, GFX_M1BAR_WIDTH, GFX_M1BAR_HEIGHT, - TFT_WIDTH - GFX_M1BAR_WIDTH - 5, 0); + TFT_WIDTH - GFX_M1BAR_WIDTH - 10, 0); } else if (dpsmode_graphics & CUR_GFX_M2_RECALL) { tft_blit((uint16_t*) gfx_m2bar, GFX_M2BAR_WIDTH, GFX_M2BAR_HEIGHT, - TFT_WIDTH - GFX_M2BAR_WIDTH - 5, 0); + TFT_WIDTH - GFX_M2BAR_WIDTH - 10, 0); } else { - tft_fill(TFT_WIDTH - GFX_M1BAR_WIDTH - 5, 0, + tft_fill(TFT_WIDTH - GFX_M1BAR_WIDTH - 10, 0, GFX_M2BAR_WIDTH, GFX_M2BAR_HEIGHT, BLACK); } From 482a160209b3170e38fad6d2cfbc9e7699796e36 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Tue, 1 Oct 2019 22:09:40 -0600 Subject: [PATCH 067/175] Using rot turn+down key combo to change third item --- opendps/event.h | 2 ++ opendps/func_dpsmode.c | 6 +++--- opendps/hw.c | 14 +++++++++----- opendps/opendps.c | 2 ++ opendps/uui.c | 2 ++ 5 files changed, 18 insertions(+), 8 deletions(-) diff --git a/opendps/event.h b/opendps/event.h index 7d4f7046..13c2ca54 100644 --- a/opendps/event.h +++ b/opendps/event.h @@ -44,6 +44,8 @@ typedef enum { event_rot_right_m1, event_rot_left_m2, event_rot_right_m2, + event_rot_left_down, + event_rot_right_down, event_rot_press, event_uart_rx, event_ocp, diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 82c5911c..25be5e43 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -523,15 +523,15 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { break; - case event_rot_left_m1: - case event_rot_right_m1: + case event_rot_left_down: + case event_rot_right_down: // change what's visible on the 3rd row // only if not in select mode, as we may be editing fields if ( ! select_mode) { ui_screen_t *screen = ui->screens[ui->cur_screen]; // rotate around the 3rd row objects (skip the 1st two) - if (event == event_rot_right_m1) { + if (event == event_rot_right_down) { third_row = (third_row + 1) % (screen->num_items - 2); } else { if (third_row == 0) third_row = screen->num_items - 3; diff --git a/opendps/hw.c b/opendps/hw.c index a3d5895b..835adc6a 100644 --- a/opendps/hw.c +++ b/opendps/hw.c @@ -90,7 +90,7 @@ static volatile bool longpress_detected; static volatile bool set_pressed = false; static volatile bool m1_pressed = false; static volatile bool m2_pressed = false; -static volatile bool m1_and_m2_pressed = false; +static volatile bool rot_pressed = false; static volatile bool key_combo = false; #define DEBOUNCE_TIME_MS (30) @@ -969,13 +969,13 @@ void BUTTON_ROTARY_isr(void) static bool falling = true; if (falling) { if (is_bouncing()) return; + rot_pressed = true; + key_combo = false; longpress_begin(event_rot_press); exti_set_trigger(BUTTON_ROT_PRESS_EXTI, EXTI_TRIGGER_RISING); } else { - if (!longpress_end()) { - // Not a long press, send short press - event_put(event_rot_press, press_short); - } + rot_pressed = false; + if ( ! longpress_end() && ! key_combo) event_put(event_rot_press, press_short); exti_set_trigger(BUTTON_ROT_PRESS_EXTI, EXTI_TRIGGER_FALLING); } falling = !falling; @@ -994,6 +994,8 @@ void BUTTON_ROTARY_isr(void) event_put(event_rot_left_m1, press_short); } else if (m2_pressed) { event_put(event_rot_left_m2, press_short); + } else if (rot_pressed) { + event_put(event_rot_left_down, press_short); } else { event_put(event_rot_left, press_short); } @@ -1004,6 +1006,8 @@ void BUTTON_ROTARY_isr(void) event_put(event_rot_right_m1, press_short); } else if (m2_pressed) { event_put(event_rot_right_m2, press_short); + } else if (rot_pressed) { + event_put(event_rot_right_down, press_short); } else { event_put(event_rot_right, press_short); } diff --git a/opendps/opendps.c b/opendps/opendps.c index f0533d61..5b745864 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -547,6 +547,8 @@ static void ui_handle_event(event_t event, uint8_t data) case event_rot_right_m1: case event_rot_left_m2: case event_rot_right_m2: + case event_rot_left_down: + case event_rot_right_down: uui_handle_screen_event(current_ui, event, data); uui_refresh(current_ui, false); break; diff --git a/opendps/uui.c b/opendps/uui.c index 8758263c..2c214a36 100644 --- a/opendps/uui.c +++ b/opendps/uui.c @@ -178,6 +178,8 @@ void uui_handle_screen_event(uui_t *ui, event_t event, uint8_t data) case event_rot_right_m1: case event_rot_left_m2: case event_rot_right_m2: + case event_rot_left_down: + case event_rot_right_down: case event_button_sel_m1: case event_button_sel_m2: // do nothing From ea7457b62e7d95f70db0c6ccbfc3fd0bedfd2123 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Tue, 1 Oct 2019 22:14:41 -0600 Subject: [PATCH 068/175] No long press as part of key combos --- opendps/hw.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/opendps/hw.c b/opendps/hw.c index 835adc6a..51c7b40e 100644 --- a/opendps/hw.c +++ b/opendps/hw.c @@ -255,7 +255,8 @@ uint16_t hw_get_vtrig_mv(void) */ void hw_longpress_check(void) { - if (longpress_event != event_none) { + // skip long presses that are part of a key combination + if ( ! key_combo && longpress_event != event_none) { if (get_ticks() - longpress_start > LONGPRESS_TIME_MS) { event_put(longpress_event, press_long); longpress_detected = true; @@ -985,31 +986,38 @@ void BUTTON_ROTARY_isr(void) exti_reset_request(BUTTON_ROT_A_EXTI); bool a = (((uint16_t) GPIO_IDR(BUTTON_ROT_A_PORT)) & BUTTON_ROT_A_PIN) ? 1 : 0; // Slightly faster than gpio_get(...) bool b = (((uint16_t) GPIO_IDR(BUTTON_ROT_B_PORT)) & BUTTON_ROT_B_PIN) ? 1 : 0; - key_combo = true; if (a == b) { if (set_pressed) { + key_combo = true; event_put(event_rot_left_set, press_short); } else if (m1_pressed) { + key_combo = true; event_put(event_rot_left_m1, press_short); } else if (m2_pressed) { + key_combo = true; event_put(event_rot_left_m2, press_short); } else if (rot_pressed) { + key_combo = true; event_put(event_rot_left_down, press_short); } else { - event_put(event_rot_left, press_short); + if ( ! key_combo) event_put(event_rot_left, press_short); } } else { if (set_pressed) { + key_combo = true; event_put(event_rot_right_set, press_short); } else if (m1_pressed) { + key_combo = true; event_put(event_rot_right_m1, press_short); } else if (m2_pressed) { + key_combo = true; event_put(event_rot_right_m2, press_short); } else if (rot_pressed) { + key_combo = true; event_put(event_rot_right_down, press_short); } else { - event_put(event_rot_right, press_short); + if ( ! key_combo) event_put(event_rot_right, press_short); } } } From 016a6d85762fa3157fd46f4602df857517363455 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Tue, 1 Oct 2019 22:25:21 -0600 Subject: [PATCH 069/175] Added brightness --- opendps/func_dpsmode.c | 30 ++++++++++++++++++++++++++++++ opendps/uui.h | 1 + opendps/uui_number.c | 6 ++++++ 3 files changed, 37 insertions(+) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 25be5e43..a845baa3 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -62,6 +62,7 @@ static void voltage_changed(ui_number_t *item); static void current_changed(ui_number_t *item); static void power_changed(ui_number_t *item); static void watthour_changed(ui_number_t *item); +static void brightness_changed(ui_number_t *item); static void timer_changed(ui_time_t *item); static void dpsmode_tick(void); static void activated(void); @@ -232,6 +233,28 @@ ui_time_t dpsmode_timer = { .changed = &timer_changed, }; +ui_number_t dpsmode_brightness = { + { + .type = ui_item_number, + .id = 15, + .x = XPOS_METER, + .y = YPOS_POWER + 5, // +5 since we are using a smaller font + .can_focus = true, + }, + .font_size = FONT_METER_MEDIUM, + .alignment = ui_text_right_aligned, + .pad_dot = false, + .color = WHITE, + .value = 0, + .min = 0, + .max = 100, + .si_prefix = si_milli, // milli watt hours + .num_digits = 3, + .num_decimals = 0, + .unit = unit_percent, + .changed = &brightness_changed, +}; + /* This is the screen definition */ ui_screen_t dpsmode_screen = { @@ -446,6 +469,10 @@ static void timer_changed(ui_time_t *item) { saved_t = item->value; } +static void brightness_changed(ui_number_t *item) { + // update brightness + hw_set_backlight(item->value); +} static bool event(uui_t *ui, event_t event, uint8_t data) { @@ -1071,10 +1098,13 @@ void func_dpsmode_init(uui_t *ui) number_init(&dpsmode_power); number_init(&dpsmode_watthour); time_init(&dpsmode_timer); + number_init(&dpsmode_brightness); // third item initialize third_item = &dpsmode_power; third_invalidate = true; + dpsmode_brightness->value = hw_get_backlight(); + uui_add_screen(ui, &dpsmode_screen); } diff --git a/opendps/uui.h b/opendps/uui.h index 6e5c918e..e67ebede 100644 --- a/opendps/uui.h +++ b/opendps/uui.h @@ -67,6 +67,7 @@ typedef enum { unit_watthour, unit_second, unit_hertz, + unit_percent, unit_furlong, unit_last = 0xff } unit_t; diff --git a/opendps/uui_number.c b/opendps/uui_number.c index 138fad15..68a2a566 100644 --- a/opendps/uui_number.c +++ b/opendps/uui_number.c @@ -163,6 +163,9 @@ static uint32_t number_draw_width(ui_item_t *_item) case unit_watt: total_width += max_w; break; + case unit_percent: + total_width += FONT_FULL_SMALL_MAX_GLYPH_WIDTH; + break; case unit_hertz: total_width += 2*FONT_FULL_SMALL_MAX_GLYPH_WIDTH; break; @@ -319,6 +322,9 @@ static void number_draw(ui_item_t *_item) case unit_watt: tft_putch(item->font_size, 'W', xpos, _item->y, max_w, h, color, false); break; + case unit_percent: + tft_puts(FONT_FULL_SMALL, "%", xpos, _item->y + h, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 2, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, color, false); + break; default: assert(0); } From 77a7cbf79e2be5f521757c00d21de67d7857743d Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Tue, 1 Oct 2019 22:26:00 -0600 Subject: [PATCH 070/175] Fixed getting brightness properly --- opendps/func_dpsmode.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index a845baa3..8b76ebc8 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -1100,11 +1100,13 @@ void func_dpsmode_init(uui_t *ui) time_init(&dpsmode_timer); number_init(&dpsmode_brightness); + // get brightness + dpsmode_brightness.value = hw_get_backlight(); + // third item initialize third_item = &dpsmode_power; third_invalidate = true; - dpsmode_brightness->value = hw_get_backlight(); uui_add_screen(ui, &dpsmode_screen); } From 360b2a3028cba2470720a5fe1044a5474586f92b Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Tue, 1 Oct 2019 22:26:53 -0600 Subject: [PATCH 071/175] Added brightness to third item list --- opendps/func_dpsmode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 8b76ebc8..ac8444f9 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -273,13 +273,14 @@ ui_screen_t dpsmode_screen = { .tick = &dpsmode_tick, .set_parameter = &set_parameter, .get_parameter = &get_parameter, - .num_items = 5, + .num_items = 6, .items = { (ui_item_t*) &dpsmode_voltage, (ui_item_t*) &dpsmode_current, (ui_item_t*) &dpsmode_power, (ui_item_t*) &dpsmode_watthour, (ui_item_t*) &dpsmode_timer, + (ui_item_t*) &dpsmode_brightness, }, .parameters = { { From 604c1721fbcb40d039343c41f49b07844456ff81 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Tue, 1 Oct 2019 22:28:16 -0600 Subject: [PATCH 072/175] Percentage is no si prefix --- opendps/func_dpsmode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index ac8444f9..aa934884 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -248,7 +248,7 @@ ui_number_t dpsmode_brightness = { .value = 0, .min = 0, .max = 100, - .si_prefix = si_milli, // milli watt hours + .si_prefix = si_none, // percentage, so 0-100 .num_digits = 3, .num_decimals = 0, .unit = unit_percent, From cc0135f92a659dc881c1cad79ddb96aaec82eea2 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Tue, 1 Oct 2019 22:36:35 -0600 Subject: [PATCH 073/175] Set brightness from 0 - 120% --- opendps/func_dpsmode.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index aa934884..55b28fbc 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -245,9 +245,9 @@ ui_number_t dpsmode_brightness = { .alignment = ui_text_right_aligned, .pad_dot = false, .color = WHITE, - .value = 0, + .value = 70, .min = 0, - .max = 100, + .max = 120, .si_prefix = si_none, // percentage, so 0-100 .num_digits = 3, .num_decimals = 0, @@ -472,7 +472,7 @@ static void timer_changed(ui_time_t *item) { static void brightness_changed(ui_number_t *item) { // update brightness - hw_set_backlight(item->value); + hw_set_backlight(item->value << 1); } static bool event(uui_t *ui, event_t event, uint8_t data) { From 334fc2517cf40d412977183c79efc25b1c2dff64 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Tue, 1 Oct 2019 22:38:26 -0600 Subject: [PATCH 074/175] Get brightness on activation --- opendps/func_dpsmode.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 55b28fbc..dc698a59 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -472,7 +472,7 @@ static void timer_changed(ui_time_t *item) { static void brightness_changed(ui_number_t *item) { // update brightness - hw_set_backlight(item->value << 1); + hw_set_backlight(item->value); } static bool event(uui_t *ui, event_t event, uint8_t data) { @@ -633,6 +633,9 @@ static void activated(void) { // reset watthour value when we leave the screen. dpsmode_watthour.value = 0; + + // get brightness + dpsmode_brightness.value = hw_get_backlight(); } static void determine_focused_item(uui_t *ui, int8_t direction) { @@ -1101,9 +1104,6 @@ void func_dpsmode_init(uui_t *ui) time_init(&dpsmode_timer); number_init(&dpsmode_brightness); - // get brightness - dpsmode_brightness.value = hw_get_backlight(); - // third item initialize third_item = &dpsmode_power; third_invalidate = true; From 179546e16c48043b176bc719dccf30b0f59bf048 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Tue, 1 Oct 2019 22:43:55 -0600 Subject: [PATCH 075/175] Rot events occur when no other buttons are pressed --- opendps/hw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opendps/hw.c b/opendps/hw.c index 51c7b40e..96ebaf1a 100644 --- a/opendps/hw.c +++ b/opendps/hw.c @@ -1001,7 +1001,7 @@ void BUTTON_ROTARY_isr(void) key_combo = true; event_put(event_rot_left_down, press_short); } else { - if ( ! key_combo) event_put(event_rot_left, press_short); + event_put(event_rot_left, press_short); } } else { if (set_pressed) { @@ -1017,7 +1017,7 @@ void BUTTON_ROTARY_isr(void) key_combo = true; event_put(event_rot_right_down, press_short); } else { - if ( ! key_combo) event_put(event_rot_right, press_short); + put(event_rot_right, press_short); } } } From 78b461a838ded4e0c6c4a0609c61a5d7aab98038 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Tue, 1 Oct 2019 22:44:27 -0600 Subject: [PATCH 076/175] Fixed last commit --- opendps/hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opendps/hw.c b/opendps/hw.c index 96ebaf1a..500c5adc 100644 --- a/opendps/hw.c +++ b/opendps/hw.c @@ -1017,7 +1017,7 @@ void BUTTON_ROTARY_isr(void) key_combo = true; event_put(event_rot_right_down, press_short); } else { - put(event_rot_right, press_short); + event_put(event_rot_right, press_short); } } } From b9d5785c006158b5e86d567b9b66ea7daee11bca Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Tue, 1 Oct 2019 20:23:10 -0600 Subject: [PATCH 077/175] Added recall code and M1/M2 key combination Added brightness adjustment Using rot turn+down key combo to change third item --- opendps/Makefile | 3 +- opendps/event.h | 12 ++- opendps/func_dpsmode.c | 208 +++++++++++++++++++++++++++++++++----- opendps/gfx-m1bar.c | 38 +++++++ opendps/gfx-m1bar.h | 13 +++ opendps/gfx-m2bar.c | 38 +++++++ opendps/gfx-m2bar.h | 13 +++ opendps/gfx/png/m1bar.png | Bin 0 -> 993 bytes opendps/gfx/png/m2bar.png | Bin 0 -> 1011 bytes opendps/hw.c | 105 +++++++++++-------- opendps/opendps.c | 18 ++-- opendps/uui.c | 6 +- opendps/uui.h | 3 +- opendps/uui_number.c | 6 ++ 14 files changed, 385 insertions(+), 78 deletions(-) create mode 100644 opendps/gfx-m1bar.c create mode 100644 opendps/gfx-m1bar.h create mode 100644 opendps/gfx-m2bar.c create mode 100644 opendps/gfx-m2bar.h create mode 100644 opendps/gfx/png/m1bar.png create mode 100644 opendps/gfx/png/m2bar.png diff --git a/opendps/Makefile b/opendps/Makefile index f1c6aba2..c05aeaf9 100644 --- a/opendps/Makefile +++ b/opendps/Makefile @@ -109,9 +109,10 @@ OBJS = \ gfx-ppbar.o \ gfx-oppbar.o \ gfx-tmbar.o \ + gfx-m1bar.o \ + gfx-m2bar.o \ gfx-padlock.o \ gfx-power.o \ - gfx-thermometer.o \ gfx-wifi.o \ opendps.o diff --git a/opendps/event.h b/opendps/event.h index 1cc33d17..13c2ca54 100644 --- a/opendps/event.h +++ b/opendps/event.h @@ -29,8 +29,12 @@ typedef enum { event_none = 0, event_button_m1, event_button_m2, - event_buttom_m1_and_m2, + event_button_m1_and_m2, event_button_sel, + + event_button_sel_m1, + event_button_sel_m2, + event_button_enable, event_rot_left, event_rot_right, @@ -40,6 +44,8 @@ typedef enum { event_rot_right_m1, event_rot_left_m2, event_rot_right_m2, + event_rot_left_down, + event_rot_right_down, event_rot_press, event_uart_rx, event_ocp, @@ -47,8 +53,8 @@ typedef enum { } event_t; typedef enum { - press_short = 0, - press_long, + press_short = 0, + press_long, } button_press_t; diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 0a116d8c..dc698a59 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -33,9 +33,13 @@ #include "gfx-ppbar.h" #include "gfx-oppbar.h" #include "gfx-tmbar.h" +#include "gfx-m1bar.h" +#include "gfx-m2bar.h" #include "font-meter_large.h" +#include "font-full_small.h" #include "hw.h" #include "func_dpsmode.h" +#include "event.h" #include "uui.h" #include "uui_number.h" #include "uui_time.h" @@ -58,11 +62,12 @@ static void voltage_changed(ui_number_t *item); static void current_changed(ui_number_t *item); static void power_changed(ui_number_t *item); static void watthour_changed(ui_number_t *item); +static void brightness_changed(ui_number_t *item); static void timer_changed(ui_time_t *item); static void dpsmode_tick(void); static void activated(void); static void deactivated(void); -static bool event(uui_t *ui, event_t event); +static bool event(uui_t *ui, event_t event, uint8_t data); static void past_save(past_t *past); static void past_restore(past_t *past); static set_param_status_t set_parameter(char *name, char *value); @@ -77,6 +82,8 @@ static void clear_third_region(void); * be replaced with measurements when output is active */ static int32_t saved_v, saved_i, saved_p, saved_t; +// the M1, M2 recall values +static int32_t recall_v[2], recall_i[2], recall_p[2], recall_t[2] = {0, 0}; // single edit mode, with M1/M2 buttons, not select. // pressing any other button when in this mode will exit the edit mode @@ -98,6 +105,9 @@ enum { CUR_GFX_PP = 4, CUR_GFX_OPP = 8, CUR_GFX_TM = 16, + + CUR_GFX_M1_RECALL = 1024, + CUR_GFX_M2_RECALL = 2048, } dpsmode_graphics; #define SCREEN_ID (6) @@ -108,8 +118,8 @@ enum { #define XPOS_CCCV (25) #define XPOS_METER (117) -#define YPOS_VOLTAGE (10) -#define YPOS_CURRENT (45) +#define YPOS_VOLTAGE (11) +#define YPOS_CURRENT (46) #define YPOS_POWER (80) /* Overriding white color */ @@ -223,6 +233,28 @@ ui_time_t dpsmode_timer = { .changed = &timer_changed, }; +ui_number_t dpsmode_brightness = { + { + .type = ui_item_number, + .id = 15, + .x = XPOS_METER, + .y = YPOS_POWER + 5, // +5 since we are using a smaller font + .can_focus = true, + }, + .font_size = FONT_METER_MEDIUM, + .alignment = ui_text_right_aligned, + .pad_dot = false, + .color = WHITE, + .value = 70, + .min = 0, + .max = 120, + .si_prefix = si_none, // percentage, so 0-100 + .num_digits = 3, + .num_decimals = 0, + .unit = unit_percent, + .changed = &brightness_changed, +}; + /* This is the screen definition */ ui_screen_t dpsmode_screen = { @@ -241,13 +273,14 @@ ui_screen_t dpsmode_screen = { .tick = &dpsmode_tick, .set_parameter = &set_parameter, .get_parameter = &get_parameter, - .num_items = 5, + .num_items = 6, .items = { (ui_item_t*) &dpsmode_voltage, (ui_item_t*) &dpsmode_current, (ui_item_t*) &dpsmode_power, (ui_item_t*) &dpsmode_watthour, (ui_item_t*) &dpsmode_timer, + (ui_item_t*) &dpsmode_brightness, }, .parameters = { { @@ -385,6 +418,9 @@ static void dpsmode_enable(bool enabled) */ static void voltage_changed(ui_number_t *item) { + dpsmode_graphics &= ~CUR_GFX_M1_RECALL; + dpsmode_graphics &= ~CUR_GFX_M2_RECALL; + saved_v = item->value; (void) pwrctl_set_vout(item->value); } @@ -396,6 +432,9 @@ static void voltage_changed(ui_number_t *item) */ static void current_changed(ui_number_t *item) { + dpsmode_graphics &= ~CUR_GFX_M1_RECALL; + dpsmode_graphics &= ~CUR_GFX_M2_RECALL; + saved_i = item->value; (void) pwrctl_set_iout(item->value); } @@ -407,6 +446,9 @@ static void current_changed(ui_number_t *item) */ static void power_changed(ui_number_t *item) { + dpsmode_graphics &= ~CUR_GFX_M1_RECALL; + dpsmode_graphics &= ~CUR_GFX_M2_RECALL; + saved_p = item->value; // (void) pwrctl_set_iout(item->value); } @@ -421,18 +463,82 @@ static void watthour_changed(ui_number_t *item) { } static void timer_changed(ui_time_t *item) { + dpsmode_graphics &= ~CUR_GFX_M1_RECALL; + dpsmode_graphics &= ~CUR_GFX_M2_RECALL; + // do nothing yet... saved_t = item->value; } +static void brightness_changed(ui_number_t *item) { + // update brightness + hw_set_backlight(item->value); +} -static bool event(uui_t *ui, event_t event) { +static bool event(uui_t *ui, event_t event, uint8_t data) { switch(event) { + case event_button_sel_m1: + case event_button_sel_m2: + // save values to recall + if (event == event_button_sel_m1) { + // save values to m1, show m1 graphics + recall_v[0] = saved_v; + recall_i[0] = saved_i; + recall_p[0] = saved_p; + recall_t[0] = saved_t; + dpsmode_graphics &= ~CUR_GFX_M2_RECALL; + dpsmode_graphics |= CUR_GFX_M1_RECALL; + } else { + // save values to m2, show m2 graphics + recall_v[1] = saved_v; + recall_i[1] = saved_i; + recall_p[1] = saved_p; + recall_t[1] = saved_t; + dpsmode_graphics &= ~CUR_GFX_M1_RECALL; + dpsmode_graphics |= CUR_GFX_M2_RECALL; + } + + return true; + case event_button_sel: case event_button_m1: case event_button_m2: + // do recall on press_long event_button_m1 or event_button_m2 + if (event == event_button_m1 && data == press_long) { + saved_v = recall_v[0]; + saved_i = recall_i[0]; + saved_p = recall_p[0]; + saved_t = recall_t[0]; + + // Turn off power + dpsmode_enable(false); + opendps_update_power_status(false); + + // show the M1 recall graphics + dpsmode_graphics &= ~CUR_GFX_M2_RECALL; + dpsmode_graphics |= CUR_GFX_M1_RECALL; + return true; + } + if (event == event_button_m2 && data == press_long) { + saved_v = recall_v[1]; + saved_i = recall_i[1]; + saved_p = recall_p[1]; + saved_t = recall_t[1]; + + // Turn off power + dpsmode_enable(false); + opendps_update_power_status(false); + + // show the M2 recall graphics + dpsmode_graphics &= ~CUR_GFX_M1_RECALL; + dpsmode_graphics |= CUR_GFX_M2_RECALL; + return true; + } + + + // leave single edit mode on any button press if (single_edit_mode) { single_edit_mode = false; @@ -441,17 +547,19 @@ static bool event(uui_t *ui, event_t event) { if (dpsmode_current.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_current); return true; } + + break; - case event_rot_left_m1: - case event_rot_right_m1: + case event_rot_left_down: + case event_rot_right_down: // change what's visible on the 3rd row // only if not in select mode, as we may be editing fields if ( ! select_mode) { ui_screen_t *screen = ui->screens[ui->cur_screen]; // rotate around the 3rd row objects (skip the 1st two) - if (event == event_rot_right_m1) { + if (event == event_rot_right_down) { third_row = (third_row + 1) % (screen->num_items - 2); } else { if (third_row == 0) third_row = screen->num_items - 3; @@ -525,6 +633,9 @@ static void activated(void) { // reset watthour value when we leave the screen. dpsmode_watthour.value = 0; + + // get brightness + dpsmode_brightness.value = hw_get_backlight(); } static void determine_focused_item(uui_t *ui, int8_t direction) { @@ -589,18 +700,27 @@ static void deactivated(void) */ static void past_save(past_t *past) { - /** @todo: past bug causes corruption for units smaller than 4 bytes (#27) */ - if (!past_write_unit(past, (SCREEN_ID << 24) | PAST_V, (void*) &saved_v, 4 /* sizeof(dpsmode_voltage.value) */ )) { - /** @todo: handle past write failures */ - } - if (!past_write_unit(past, (SCREEN_ID << 24) | PAST_I, (void*) &saved_i, 4 /* sizeof(dpsmode_current.value) */ )) { - /** @todo: handle past write failures */ + if ( past_write_unit(past, (SCREEN_ID << 24) | PAST_V, (void*) &saved_v, 4) + && past_write_unit(past, (SCREEN_ID << 24) | PAST_I, (void*) &saved_i, 4) + && past_write_unit(past, (SCREEN_ID << 24) | PAST_P, (void*) &saved_p, 4) + && past_write_unit(past, (SCREEN_ID << 24) | PAST_T, (void*) &saved_t, 4)) { + // write successful } - if (!past_write_unit(past, (SCREEN_ID << 24) | PAST_P, (void*) &saved_p, 4 /* sizeof(dpsmode_power.value) */ )) { - /** @todo: handle past write failures */ + + // recall m1 + if ( past_write_unit(past, (SCREEN_ID << 24) | (PAST_V << 2), (void*) &recall_v[0], 4) + && past_write_unit(past, (SCREEN_ID << 24) | (PAST_I << 2), (void*) &recall_i[0], 4) + && past_write_unit(past, (SCREEN_ID << 24) | (PAST_P << 2), (void*) &recall_p[0], 4) + && past_write_unit(past, (SCREEN_ID << 24) | (PAST_T << 2), (void*) &recall_t[0], 4)) { + // write successful } - if (!past_write_unit(past, (SCREEN_ID << 24) | PAST_T, (void*) &saved_t, 4 /* sizeof(dpsmode_power.value) */ )) { - /** @todo: handle past write failures */ + + // recall m2 + if ( past_write_unit(past, (SCREEN_ID << 24) | (PAST_V << 4), (void*) &recall_v[1], 4) + && past_write_unit(past, (SCREEN_ID << 24) | (PAST_I << 4), (void*) &recall_i[1], 4) + && past_write_unit(past, (SCREEN_ID << 24) | (PAST_P << 4), (void*) &recall_p[1], 4) + && past_write_unit(past, (SCREEN_ID << 24) | (PAST_T << 4), (void*) &recall_t[1], 4)) { + // write successful } } @@ -613,22 +733,46 @@ static void past_restore(past_t *past) { uint32_t length; uint32_t *p = 0; + if (past_read_unit(past, (SCREEN_ID << 24) | PAST_V, (const void**) &p, &length)) { saved_v = dpsmode_voltage.value = *p; - (void) length; } if (past_read_unit(past, (SCREEN_ID << 24) | PAST_I, (const void**) &p, &length)) { saved_i = dpsmode_current.value = *p; - (void) length; } if (past_read_unit(past, (SCREEN_ID << 24) | PAST_P, (const void**) &p, &length)) { saved_p = dpsmode_power.value = *p; - (void) length; } if (past_read_unit(past, (SCREEN_ID << 24) | PAST_T, (const void**) &p, &length)) { saved_t = dpsmode_timer.value = *p; - (void) length; } + + if (past_read_unit(past, (SCREEN_ID << 24) | (PAST_V << 2), (const void**) &p, &length)) { + recall_v[0] = *p; + } + if (past_read_unit(past, (SCREEN_ID << 24) | (PAST_I << 2), (const void**) &p, &length)) { + recall_i[0] = *p; + } + if (past_read_unit(past, (SCREEN_ID << 24) | (PAST_P << 2), (const void**) &p, &length)) { + recall_p[0] = *p; + } + if (past_read_unit(past, (SCREEN_ID << 24) | (PAST_T << 2), (const void**) &p, &length)) { + recall_t[0] = *p; + } + + if (past_read_unit(past, (SCREEN_ID << 24) | (PAST_V << 4), (const void**) &p, &length)) { + recall_v[1] = *p; + } + if (past_read_unit(past, (SCREEN_ID << 24) | (PAST_I << 4), (const void**) &p, &length)) { + recall_i[1] = *p; + } + if (past_read_unit(past, (SCREEN_ID << 24) | (PAST_P << 4), (const void**) &p, &length)) { + recall_p[1] = *p; + } + if (past_read_unit(past, (SCREEN_ID << 24) | (PAST_T << 4), (const void**) &p, &length)) { + recall_t[1] = *p; + } + } /** @@ -891,6 +1035,22 @@ static void draw_bars() { } + // draw any recall icons + if (dpsmode_graphics & CUR_GFX_M1_RECALL) { + tft_blit((uint16_t*) gfx_m1bar, + GFX_M1BAR_WIDTH, GFX_M1BAR_HEIGHT, + TFT_WIDTH - GFX_M1BAR_WIDTH - 10, 0); + } else if (dpsmode_graphics & CUR_GFX_M2_RECALL) { + tft_blit((uint16_t*) gfx_m2bar, + GFX_M2BAR_WIDTH, GFX_M2BAR_HEIGHT, + TFT_WIDTH - GFX_M2BAR_WIDTH - 10, 0); + } else { + tft_fill(TFT_WIDTH - GFX_M1BAR_WIDTH - 10, 0, + GFX_M2BAR_WIDTH, GFX_M2BAR_HEIGHT, + BLACK); + } + + } /* @@ -901,7 +1061,7 @@ static void draw_bars() { static void clear_bars(bool all) { if (all) { // clears opp as well as the others - dpsmode_graphics = CUR_GFX_NOT_DRAWN; + dpsmode_graphics &= ~0x3ff; // exclude m1/m2, so not CUR_GFX_NOT_DRAWN; return; } @@ -942,10 +1102,12 @@ void func_dpsmode_init(uui_t *ui) number_init(&dpsmode_power); number_init(&dpsmode_watthour); time_init(&dpsmode_timer); + number_init(&dpsmode_brightness); // third item initialize third_item = &dpsmode_power; third_invalidate = true; + uui_add_screen(ui, &dpsmode_screen); } diff --git a/opendps/gfx-m1bar.c b/opendps/gfx-m1bar.c new file mode 100644 index 00000000..8e7b6d37 --- /dev/null +++ b/opendps/gfx-m1bar.c @@ -0,0 +1,38 @@ +/** Gfx generated from gfx/png/m1bar.png */ + +#include "gfx-m1bar.h" + +const uint8_t gfx_m1bar[500] = { + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0xfe, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, + 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, + 0xfe, 0xc0, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0x00, 0x00 +}; \ No newline at end of file diff --git a/opendps/gfx-m1bar.h b/opendps/gfx-m1bar.h new file mode 100644 index 00000000..2ae318c2 --- /dev/null +++ b/opendps/gfx-m1bar.h @@ -0,0 +1,13 @@ +/** Gfx generated from gfx/png/m1bar.png */ + +#ifndef __GFX_M1BAR_H__ +#define __GFX_M1BAR_H__ + +#include + +#define GFX_M1BAR_HEIGHT (10) +#define GFX_M1BAR_WIDTH (25) + +extern const uint8_t gfx_m1bar[500]; + +#endif // __GFX_M1BAR_H__ \ No newline at end of file diff --git a/opendps/gfx-m2bar.c b/opendps/gfx-m2bar.c new file mode 100644 index 00000000..2a937702 --- /dev/null +++ b/opendps/gfx-m2bar.c @@ -0,0 +1,38 @@ +/** Gfx generated from gfx/png/m2bar.png */ + +#include "gfx-m2bar.h" + +const uint8_t gfx_m2bar[500] = { + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0xfe, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, + 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, + 0xfe, 0xc0, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0x00, 0x00, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, 0xfe, 0xc0, + 0xfe, 0xc0, 0x00, 0x00 +}; \ No newline at end of file diff --git a/opendps/gfx-m2bar.h b/opendps/gfx-m2bar.h new file mode 100644 index 00000000..9263e559 --- /dev/null +++ b/opendps/gfx-m2bar.h @@ -0,0 +1,13 @@ +/** Gfx generated from gfx/png/m2bar.png */ + +#ifndef __GFX_M2BAR_H__ +#define __GFX_M2BAR_H__ + +#include + +#define GFX_M2BAR_HEIGHT (10) +#define GFX_M2BAR_WIDTH (25) + +extern const uint8_t gfx_m2bar[500]; + +#endif // __GFX_M2BAR_H__ \ No newline at end of file diff --git a/opendps/gfx/png/m1bar.png b/opendps/gfx/png/m1bar.png new file mode 100644 index 0000000000000000000000000000000000000000..405f49bd4a09a14bb627607f7b1990950f9045d9 GIT binary patch literal 993 zcmaJ=J#5oJ7%Kmu$h6SFhvMV{0H$x4zy!o97E$>t; zXJ_4!U3T_5m`M~$;3Hy##NP;FB~jT9uR_nM8M2_`Le^FGD5;vc2s9iakmK?hN04&h zs>})btR%}&J4CRGV!RbOba0KyG*qZ)5wZ!6EQ~jLU0iHo zg5wqrfu^Nhlfm?g7r3|`U+!Q`Qz-{Au>%K{b(N(ooaecUR?v;SqzMLHf?&u6qbTY| zK@%k@TNHA0J*hjov!;y`RF2S22dbrgAbkz0ze4?1Nl-oRXnrGb21tUEXt zejpaoWMDenzlPm2Q3a*PzI5rOFMbqI#Ya@yrCYy#(`T_%*5|C`bKTwl`DAEfS}0D0 zn+vD+!L!>_qayQ#SO@xzk*E0!qr2a^S8JEn&c3`OJuaMLKdpYG9`1Yc* gcW>7kPliu`1LobgGw;tYz34o;vQg2W7uW9p0p%Ptd;kCd literal 0 HcmV?d00001 diff --git a/opendps/gfx/png/m2bar.png b/opendps/gfx/png/m2bar.png new file mode 100644 index 0000000000000000000000000000000000000000..7da0936610c6d23a26e800f25bb5a70a8811d6b7 GIT binary patch literal 1011 zcmaJ=&ui0A9M4vfu`$>{oO1}zRCL0cUrpO3ERL?pT)~Xc71rIBCa-JQl9wf~HX9yf zHxI)80(VkG`~m7g^k5lYb`cMrynFGWx9ueO(zTrjYaq#ckMHO6{d~XQ&wF4j-yR*l zJWNs4XmLp`k^dxlhld8q_w!M8AU?oa1+SnQZkhq4@;0hMP;|`=Sc0a#vwZ~TC@OK? zDOYeszav}7Wz0B+iCmwcDQa#$@=a?KVo-$}j;GMSK76EsV=MG(M(1?D0PD`uZU9$y zm&?}frX|_*{4FpS$%Md#*aVTg<%M#j&~09stm9*r2JH~MsnDmQD!Ks*D1actWK$L| zW590{T{6scG^T5 z#zv;k@(dT3)D6`2|A)G6FFM2}c&7KC#9?{IhinOks1aCXaJ6Kd%9jfPG%*Uw2yJz{ zXw(r#VIBFPP>8!Gf$3Gpvr#j=*~aL)T=YV0dKN6I3QbrT$FXIe&*Vf^6E(4r;dxD3 z$mb+Aoz?PuF0E>U*u|>IYPitDU95eE&Gf~_c5r=?S%raf7ut&fazVRn+3BxE=*!o^ z+Wobp`(jxlhK+~&*RZ=s#6j`0XI--CnIC$@@d2^++ZSJdlWSoW)qFYnR<+-q91KiO z^9z&ywm3dJu{L^%j^8*iC;>5w)SmWul@h9tvYwt(cmU;2@_sW&QlbOdq4{Kvr z-+UPyd6mELDVc5UtxOpSjlepGr_hIr)5wsT%P$ENaW@%Z2s5Kl*<; AQUCw| literal 0 HcmV?d00001 diff --git a/opendps/hw.c b/opendps/hw.c index 4ce6919a..500c5adc 100644 --- a/opendps/hw.c +++ b/opendps/hw.c @@ -88,11 +88,10 @@ static volatile uint64_t longpress_start; static volatile bool longpress_detected; /** Used to filter SET press from SET + ROT */ static volatile bool set_pressed = false; -static volatile bool set_skip = false; static volatile bool m1_pressed = false; static volatile bool m2_pressed = false; -static volatile bool m1_and_m2_pressed = false; -static volatile bool rot_turned = false; +static volatile bool rot_pressed = false; +static volatile bool key_combo = false; #define DEBOUNCE_TIME_MS (30) @@ -256,7 +255,8 @@ uint16_t hw_get_vtrig_mv(void) */ void hw_longpress_check(void) { - if (longpress_event != event_none) { + // skip long presses that are part of a key combination + if ( ! key_combo && longpress_event != event_none) { if (get_ticks() - longpress_start > LONGPRESS_TIME_MS) { event_put(longpress_event, press_long); longpress_detected = true; @@ -837,20 +837,30 @@ void BUTTON_SEL_isr(void) { static bool falling = true; exti_reset_request(BUTTON_SEL_EXTI); + if (falling) { if (is_bouncing()) return; set_pressed = true; - set_skip = false; + key_combo = false; + longpress_begin(event_button_sel); exti_set_trigger(BUTTON_SEL_EXTI, EXTI_TRIGGER_RISING); } else { set_pressed = false; - if (!set_skip) { - if (!longpress_end()) { - // Not a long press, send short press - event_put(event_button_sel, press_short); - } + + if ( ! key_combo && m1_pressed ) { + key_combo = true; + event_put(event_button_sel_m1, press_short); + return; + } + + if ( ! key_combo && m2_pressed ) { + key_combo = true; + event_put(event_button_sel_m1, press_short); } + + if ( ! longpress_end() && ! key_combo) event_put(event_button_sel, press_short); + exti_set_trigger(BUTTON_SEL_EXTI, EXTI_TRIGGER_FALLING); } falling = !falling; @@ -866,27 +876,28 @@ void BUTTON_M1_isr(void) exti_reset_request(BUTTON_M1_EXTI); if (falling) { if (is_bouncing()) return; - m1_pressed = true; - // do not fire button if rot rotated while down - rot_turned = false; - - if (m2_pressed) - m1_and_m2_pressed = true; + m1_pressed = true; + key_combo = false; + longpress_begin(event_button_m1); exti_set_trigger(BUTTON_M1_EXTI, EXTI_TRIGGER_RISING); } else { m1_pressed = false; - if (!m2_pressed) { - if (m1_and_m2_pressed) { - m1_and_m2_pressed = false; - event_put(event_buttom_m1_and_m2, press_short); - } else { - if ( ! rot_turned) event_put(event_button_m1, press_short); - } + if ( ! key_combo && set_pressed ) { + key_combo = true; + event_put(event_button_sel_m1, press_short); + return; + } + + if ( ! key_combo && m2_pressed ) { + key_combo = true; + event_put(event_button_m1_and_m2, press_short); } + if ( ! longpress_end() && ! key_combo) event_put(event_button_m1, press_short); + exti_set_trigger(BUTTON_M1_EXTI, EXTI_TRIGGER_FALLING); } falling = !falling; @@ -905,23 +916,26 @@ void BUTTON_M2_isr(void) m2_pressed = true; // do not fire button if rot rotated while down - rot_turned = false; + key_combo = false; - if (m1_pressed) - m1_and_m2_pressed = true; + longpress_begin(event_button_m2); exti_set_trigger(BUTTON_M2_EXTI, EXTI_TRIGGER_RISING); } else { m2_pressed = false; - if (!m1_pressed) { - if (m1_and_m2_pressed) { - m1_and_m2_pressed = false; - event_put(event_buttom_m1_and_m2, press_short); - } else { - if ( ! rot_turned) event_put(event_button_m2, press_short); - } + if ( ! key_combo && set_pressed ) { + key_combo = true; + event_put(event_button_sel_m2, press_short); + return; + } + + if ( ! key_combo && m1_pressed ) { + key_combo = true; + event_put(event_button_m1_and_m2, press_short); } + if ( ! longpress_end() && ! key_combo) event_put(event_button_m2, press_short); + exti_set_trigger(BUTTON_M2_EXTI, EXTI_TRIGGER_FALLING); } falling = !falling; @@ -956,13 +970,13 @@ void BUTTON_ROTARY_isr(void) static bool falling = true; if (falling) { if (is_bouncing()) return; + rot_pressed = true; + key_combo = false; longpress_begin(event_rot_press); exti_set_trigger(BUTTON_ROT_PRESS_EXTI, EXTI_TRIGGER_RISING); } else { - if (!longpress_end()) { - // Not a long press, send short press - event_put(event_rot_press, press_short); - } + rot_pressed = false; + if ( ! longpress_end() && ! key_combo) event_put(event_rot_press, press_short); exti_set_trigger(BUTTON_ROT_PRESS_EXTI, EXTI_TRIGGER_FALLING); } falling = !falling; @@ -972,29 +986,36 @@ void BUTTON_ROTARY_isr(void) exti_reset_request(BUTTON_ROT_A_EXTI); bool a = (((uint16_t) GPIO_IDR(BUTTON_ROT_A_PORT)) & BUTTON_ROT_A_PIN) ? 1 : 0; // Slightly faster than gpio_get(...) bool b = (((uint16_t) GPIO_IDR(BUTTON_ROT_B_PORT)) & BUTTON_ROT_B_PIN) ? 1 : 0; - rot_turned = true; if (a == b) { if (set_pressed) { - set_skip = true; - (void) longpress_end(); + key_combo = true; event_put(event_rot_left_set, press_short); } else if (m1_pressed) { + key_combo = true; event_put(event_rot_left_m1, press_short); } else if (m2_pressed) { + key_combo = true; event_put(event_rot_left_m2, press_short); + } else if (rot_pressed) { + key_combo = true; + event_put(event_rot_left_down, press_short); } else { event_put(event_rot_left, press_short); } } else { if (set_pressed) { - set_skip = true; - (void) longpress_end(); + key_combo = true; event_put(event_rot_right_set, press_short); } else if (m1_pressed) { + key_combo = true; event_put(event_rot_right_m1, press_short); } else if (m2_pressed) { + key_combo = true; event_put(event_rot_right_m2, press_short); + } else if (rot_pressed) { + key_combo = true; + event_put(event_rot_right_down, press_short); } else { event_put(event_rot_right, press_short); } diff --git a/opendps/opendps.c b/opendps/opendps.c index 29d05b82..5b745864 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -41,7 +41,7 @@ #include "serialhandler.h" #include "ili9163c.h" #include "gfx-padlock.h" -#include "gfx-thermometer.h" +// #include "gfx-thermometer.h" #include "gfx-power.h" #include "gfx-wifi.h" #include "font-full_small.h" @@ -509,7 +509,7 @@ static void ui_handle_event(event_t event, uint8_t data) #endif // CONFIG_OCP_DEBUGGING ui_flash(); /** @todo When OCP kicks in, show last I_out on screen */ opendps_update_power_status(false); - uui_handle_screen_event(current_ui, event); + uui_handle_screen_event(current_ui, event, data); } break; case event_ovp: @@ -524,10 +524,10 @@ static void ui_handle_event(event_t event, uint8_t data) #endif // CONFIG_OVP_DEBUGGING ui_flash(); /** @todo When OVP kicks in, show last V_out on screen */ opendps_update_power_status(false); - uui_handle_screen_event(current_ui, event); + uui_handle_screen_event(current_ui, event, data); } break; - case event_buttom_m1_and_m2: ; + case event_button_m1_and_m2: ; uint8_t target_screen_id = current_ui == &func_ui ? SETTINGS_UI_ID : FUNC_UI_ID; /** Change between the settings and functional screen */ opendps_change_screen(target_screen_id); break; @@ -538,6 +538,8 @@ static void ui_handle_event(event_t event, uint8_t data) case event_button_m1: case event_button_m2: case event_button_sel: + case event_button_sel_m1: + case event_button_sel_m2: case event_rot_press: case event_rot_left: case event_rot_right: @@ -545,7 +547,9 @@ static void ui_handle_event(event_t event, uint8_t data) case event_rot_right_m1: case event_rot_left_m2: case event_rot_right_m2: - uui_handle_screen_event(current_ui, event); + case event_rot_left_down: + case event_rot_right_down: + uui_handle_screen_event(current_ui, event, data); uui_refresh(current_ui, false); break; @@ -558,7 +562,7 @@ static void ui_handle_event(event_t event, uint8_t data) break; } - uui_handle_screen_event(current_ui, event); + uui_handle_screen_event(current_ui, event, data); uui_refresh(current_ui, false); break; @@ -603,7 +607,7 @@ void opendps_temperature_lock(bool lock) tft_clear(); uui_show(current_ui, false); uui_show(&main_ui, false); - tft_blit((uint16_t*) gfx_thermometer, GFX_THERMOMETER_WIDTH, GFX_THERMOMETER_HEIGHT, 1+(ui_width-GFX_THERMOMETER_WIDTH)/2, 30); + // tft_blit((uint16_t*) gfx_thermometer, GFX_THERMOMETER_WIDTH, GFX_THERMOMETER_HEIGHT, 1+(ui_width-GFX_THERMOMETER_WIDTH)/2, 30); } else { emu_printf("DPS enabled due to temperature\n"); tft_clear(); diff --git a/opendps/uui.c b/opendps/uui.c index f7513670..2c214a36 100644 --- a/opendps/uui.c +++ b/opendps/uui.c @@ -149,7 +149,7 @@ void uui_focus(uui_t *ui, ui_item_t *item) { } -void uui_handle_screen_event(uui_t *ui, event_t event) +void uui_handle_screen_event(uui_t *ui, event_t event, uint8_t data) { assert(ui); ui_screen_t *screen = ui->screens[ui->cur_screen]; @@ -178,6 +178,10 @@ void uui_handle_screen_event(uui_t *ui, event_t event) case event_rot_right_m1: case event_rot_left_m2: case event_rot_right_m2: + case event_rot_left_down: + case event_rot_right_down: + case event_button_sel_m1: + case event_button_sel_m2: // do nothing break; diff --git a/opendps/uui.h b/opendps/uui.h index 82c2932f..e67ebede 100644 --- a/opendps/uui.h +++ b/opendps/uui.h @@ -67,6 +67,7 @@ typedef enum { unit_watthour, unit_second, unit_hertz, + unit_percent, unit_furlong, unit_last = 0xff } unit_t; @@ -224,7 +225,7 @@ void uui_add_screen(uui_t *ui, ui_screen_t *screen); * @param ui The user interface * @param[in] event The event */ -void uui_handle_screen_event(uui_t *ui, event_t event); +void uui_handle_screen_event(uui_t *ui, event_t event, uint8_t data); /** * @brief Switch to next screen diff --git a/opendps/uui_number.c b/opendps/uui_number.c index 138fad15..68a2a566 100644 --- a/opendps/uui_number.c +++ b/opendps/uui_number.c @@ -163,6 +163,9 @@ static uint32_t number_draw_width(ui_item_t *_item) case unit_watt: total_width += max_w; break; + case unit_percent: + total_width += FONT_FULL_SMALL_MAX_GLYPH_WIDTH; + break; case unit_hertz: total_width += 2*FONT_FULL_SMALL_MAX_GLYPH_WIDTH; break; @@ -319,6 +322,9 @@ static void number_draw(ui_item_t *_item) case unit_watt: tft_putch(item->font_size, 'W', xpos, _item->y, max_w, h, color, false); break; + case unit_percent: + tft_puts(FONT_FULL_SMALL, "%", xpos, _item->y + h, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 2, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, color, false); + break; default: assert(0); } From 96e84e2c46eaa35a652d410b81ffedfd4be44378 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Thu, 3 Oct 2019 20:07:59 -0600 Subject: [PATCH 078/175] Fixed glitchy 3rd item on start Brightness value should now be set even when screen is the first screen to start up --- opendps/func_dpsmode.c | 31 +++++++++---------------------- opendps/uui_time.c | 8 ++++---- 2 files changed, 13 insertions(+), 26 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index dc698a59..d302d593 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -245,9 +245,9 @@ ui_number_t dpsmode_brightness = { .alignment = ui_text_right_aligned, .pad_dot = false, .color = WHITE, - .value = 70, + .value = 0, .min = 0, - .max = 120, + .max = 100, .si_prefix = si_none, // percentage, so 0-100 .num_digits = 3, .num_decimals = 0, @@ -472,7 +472,7 @@ static void timer_changed(ui_time_t *item) { static void brightness_changed(ui_number_t *item) { // update brightness - hw_set_backlight(item->value); + hw_set_backlight(item->value * 1.28f); } static bool event(uui_t *ui, event_t event, uint8_t data) { @@ -633,9 +633,6 @@ static void activated(void) { // reset watthour value when we leave the screen. dpsmode_watthour.value = 0; - - // get brightness - dpsmode_brightness.value = hw_get_backlight(); } static void determine_focused_item(uui_t *ui, int8_t direction) { @@ -796,6 +793,10 @@ static void dpsmode_tick(void) // set the maximum power based on max voltage and max amps dpsmode_power.max = dpsmode_voltage.max * CONFIG_DPS_MAX_CURRENT; + // update brightness if 0 (because it's most likely not set) + if (dpsmode_brightness.value == 0) + dpsmode_brightness.value = hw_get_backlight(); + // power enabled if (pwrctl_vout_enabled()) { // get the actual voltage and current being supplied @@ -897,17 +898,8 @@ static void dpsmode_tick(void) tick_since_count = get_ticks() - diff; // calculate amount of power delivered as milli watt hours - dpsmode_watthour.value += ((power_actual * 1000.0 / 3600.0f) * secs) / 1000; - // 1000 == 1.0mWh - /* - if (dpsmode_watthour.value <= 1000000) { - dpsmode_watthour.num_decimals = 1; - } - if (dpsmode_watthour.value >= 1000000) { - dpsmode_watthour.num_decimals = 0; - } - */ + dpsmode_watthour.value += ((power_actual * 1000.0 / 3600.0f) * secs) / 1000; } // timer enabled, count down @@ -940,7 +932,7 @@ static void dpsmode_tick(void) ((ui_number_t *)third_item)->ui.draw(& ((ui_number_t *)third_item)->ui); } else { - // dpsmode_power.ui.draw(&dpsmode_power.ui); + dpsmode_power.ui.draw(&dpsmode_power.ui); } // draw bars on right @@ -1104,10 +1096,5 @@ void func_dpsmode_init(uui_t *ui) time_init(&dpsmode_timer); number_init(&dpsmode_brightness); - // third item initialize - third_item = &dpsmode_power; - third_invalidate = true; - - uui_add_screen(ui, &dpsmode_screen); } diff --git a/opendps/uui_time.c b/opendps/uui_time.c index 038b87dd..93ffc1b1 100644 --- a/opendps/uui_time.c +++ b/opendps/uui_time.c @@ -257,8 +257,8 @@ static void number_draw(ui_item_t *_item) xpos += digit_w + spacing; // : - tft_putch(item->font_size, '.', xpos, _item->y - (h>>2) + (h >> 1), dot_width, h >> 2, color, false); - tft_putch(item->font_size, '.', xpos, _item->y - (h>>2) , dot_width, h >> 2, color, false); + tft_putch(item->font_size, '.', xpos, _item->y - (h>>2) + (h >> 1), dot_width, h >> 4, color, false); + tft_putch(item->font_size, '.', xpos, _item->y - (h>>2) , dot_width, h >> 4, color, false); xpos += dot_width + spacing; // MM @@ -281,8 +281,8 @@ static void number_draw(ui_item_t *_item) xpos += digit_w + spacing; // : - tft_putch(item->font_size, '.', xpos, _item->y - (h>>2) + (h >> 1), dot_width, h >> 2, color, false); - tft_putch(item->font_size, '.', xpos, _item->y - (h>>2) , dot_width, h >> 2, color, false); + tft_putch(item->font_size, '.', xpos, _item->y - (h>>2) + (h >> 1), dot_width, h >> 3, color, false); + tft_putch(item->font_size, '.', xpos, _item->y - (h>>2) , dot_width, h >> 3, color, false); xpos += dot_width + spacing; // SS From 1304d94e979df0d1949030ad52a6ab8373a42061 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Thu, 3 Oct 2019 20:10:40 -0600 Subject: [PATCH 079/175] No longer forcing a uui refresh when events occur to prevent glitchy draws --- opendps/opendps.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opendps/opendps.c b/opendps/opendps.c index 5b745864..1c919f85 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -550,7 +550,7 @@ static void ui_handle_event(event_t event, uint8_t data) case event_rot_left_down: case event_rot_right_down: uui_handle_screen_event(current_ui, event, data); - uui_refresh(current_ui, false); + //uui_refresh(current_ui, false); break; case event_rot_left_set: @@ -563,7 +563,7 @@ static void ui_handle_event(event_t event, uint8_t data) } uui_handle_screen_event(current_ui, event, data); - uui_refresh(current_ui, false); + //uui_refresh(current_ui, false); break; default: From 6ba050dfa8401a55bcc3436a209b4316c20cd87c Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Thu, 3 Oct 2019 20:23:02 -0600 Subject: [PATCH 080/175] No longer redrawing screens on activation becauase it is triggered by an event and event handlers should be super fast. Defer to next UI tick instead --- opendps/opendps.c | 28 +++++++++++++++++++--------- opendps/uui.c | 10 ++++++++-- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/opendps/opendps.c b/opendps/opendps.c index 1c919f85..a443edb7 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -512,6 +512,7 @@ static void ui_handle_event(event_t event, uint8_t data) uui_handle_screen_event(current_ui, event, data); } break; + case event_ovp: { #ifdef CONFIG_OVP_DEBUGGING @@ -527,10 +528,12 @@ static void ui_handle_event(event_t event, uint8_t data) uui_handle_screen_event(current_ui, event, data); } break; + case event_button_m1_and_m2: ; uint8_t target_screen_id = current_ui == &func_ui ? SETTINGS_UI_ID : FUNC_UI_ID; /** Change between the settings and functional screen */ opendps_change_screen(target_screen_id); break; + case event_button_enable: #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" write_past_settings(); @@ -629,13 +632,6 @@ static void ui_tick(void) static uint64_t last_tft_flash = 0; static uint64_t last_lock_flash = 0; - static uint64_t last = 0; - /** Update on the first call and every UI_UPDATE_INTERVAL_MS ms */ - if (last > 0 && get_ticks() - last < UI_UPDATE_INTERVAL_MS) { - return; - } - - last = get_ticks(); uui_tick(current_ui); uui_tick(&main_ui); @@ -932,12 +928,22 @@ static void check_master_reset(void) */ static void event_handler(void) { + static uint64_t last = 0; + while(1) { event_t event; uint8_t data = 0; - if (!event_get(&event, &data)) { + + if ( ! event_get(&event, &data)) { hw_longpress_check(); - ui_tick(); + + /** Update on the first call and every UI_UPDATE_INTERVAL_MS ms */ + if (last <= 0 || get_ticks() - last >= UI_UPDATE_INTERVAL_MS) { + ui_tick(); + } + + last = get_ticks(); + } else { if (event) { emu_printf(" Event %d 0x%02x\n", event, data); @@ -954,7 +960,11 @@ static void event_handler(void) default: break; } + ui_handle_event(event, data); + + // call ui_tick immediately because event could have caused UI changes + ui_tick(); } } } diff --git a/opendps/uui.c b/opendps/uui.c index 2c214a36..1bc9050d 100644 --- a/opendps/uui.c +++ b/opendps/uui.c @@ -102,6 +102,7 @@ void uui_activate(uui_t *ui) { assert(ui); assert(ui->num_screens); + if (ui->num_screens > 0) { ui_screen_t *screen = ui->screens[ui->cur_screen]; /** Find the first focusable item */ @@ -111,9 +112,13 @@ void uui_activate(uui_t *ui) break; } } + /** @todo: add activation callback for each screen allowing for updating of U/I settings */ - uui_refresh(ui, true); - tft_blit((uint16_t*) screen->icon_data, screen->icon_width, screen->icon_height, XPOS_ICON, 128-screen->icon_height); + + // do not immediately redraw the screen. The next ui tick should do this. + // uui_refresh(ui, true); + // tft_blit((uint16_t*) screen->icon_data, screen->icon_width, screen->icon_height, XPOS_ICON, 128-screen->icon_height); + if (screen->activated) { screen->activated(); } @@ -274,6 +279,7 @@ void uui_set_screen(uui_t *ui, uint32_t screen_idx) ui->cur_screen = screen_idx; ui_screen_t *new_screen = ui->screens[ui->cur_screen]; assert(new_screen); + if (new_screen != cur_screen) { // cur_screen->enable(false); /** Alway disable current function when switching */ opendps_update_power_status(false); /** @todo: move */ From 6d2a2a6006d58b89a33b0c9aefcea8326830639b Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Thu, 3 Oct 2019 20:44:55 -0600 Subject: [PATCH 081/175] Clear third item region when focus is changed to avoid select artifact --- opendps/func_dpsmode.c | 7 +++---- opendps/func_gen.c | 4 +++- opendps/uui.c | 10 ++-------- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index d302d593..f55df210 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -674,11 +674,10 @@ static void determine_focused_item(uui_t *ui, int8_t direction) { } - if (focus_index >= 2 && focus_index != screen->num_items) { + if (focus_index >= 2 && focus_index < screen->num_items) { third_item = (ui_item_t *)screen->items[focus_index]; third_row = focus_index - 2; third_invalidate = true; - clear_third_region(); } } @@ -940,8 +939,8 @@ static void dpsmode_tick(void) } static void clear_third_region() { - tft_fill(0, YPOS_POWER, - TFT_WIDTH, FONT_METER_LARGE_MAX_GLYPH_HEIGHT, + tft_fill(0, YPOS_POWER - 1, + TFT_WIDTH, FONT_METER_LARGE_MAX_GLYPH_HEIGHT + 2, BLACK); } diff --git a/opendps/func_gen.c b/opendps/func_gen.c index fbd71cd0..73241106 100644 --- a/opendps/func_gen.c +++ b/opendps/func_gen.c @@ -464,10 +464,12 @@ static void func_changed(ui_icon_t *item) static void activated(void) { /** The screen is different here, let's clear it */ - tft_clear(); + // tft_clear(); + for (uint32_t i = 0; i < gen_screen.num_items; i++) { gen_screen.items[i]->draw(gen_screen.items[i]); } + tft_puts(FONT_FULL_SMALL, "Vout:", 6, 15+FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, 64, 20, WHITE, false); tft_puts(FONT_FULL_SMALL, "Freq:", 6, 42+FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, 64, 20, WHITE, false); tft_puts(FONT_FULL_SMALL, "Func:", 6, 69+FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, 64, 20, WHITE, false); diff --git a/opendps/uui.c b/opendps/uui.c index 1bc9050d..2c214a36 100644 --- a/opendps/uui.c +++ b/opendps/uui.c @@ -102,7 +102,6 @@ void uui_activate(uui_t *ui) { assert(ui); assert(ui->num_screens); - if (ui->num_screens > 0) { ui_screen_t *screen = ui->screens[ui->cur_screen]; /** Find the first focusable item */ @@ -112,13 +111,9 @@ void uui_activate(uui_t *ui) break; } } - /** @todo: add activation callback for each screen allowing for updating of U/I settings */ - - // do not immediately redraw the screen. The next ui tick should do this. - // uui_refresh(ui, true); - // tft_blit((uint16_t*) screen->icon_data, screen->icon_width, screen->icon_height, XPOS_ICON, 128-screen->icon_height); - + uui_refresh(ui, true); + tft_blit((uint16_t*) screen->icon_data, screen->icon_width, screen->icon_height, XPOS_ICON, 128-screen->icon_height); if (screen->activated) { screen->activated(); } @@ -279,7 +274,6 @@ void uui_set_screen(uui_t *ui, uint32_t screen_idx) ui->cur_screen = screen_idx; ui_screen_t *new_screen = ui->screens[ui->cur_screen]; assert(new_screen); - if (new_screen != cur_screen) { // cur_screen->enable(false); /** Alway disable current function when switching */ opendps_update_power_status(false); /** @todo: move */ From 0bd367f1f3d16cc123e26478209978c34e944b74 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Thu, 3 Oct 2019 21:06:47 -0600 Subject: [PATCH 082/175] Added event_shutoff --- opendps/event.h | 5 ++++- opendps/func_dpsmode.c | 20 ++++++++--------- opendps/opendps.c | 51 +++++++++--------------------------------- opendps/uui.c | 25 ++++++++++++--------- 4 files changed, 38 insertions(+), 63 deletions(-) diff --git a/opendps/event.h b/opendps/event.h index 13c2ca54..5b8b0053 100644 --- a/opendps/event.h +++ b/opendps/event.h @@ -47,9 +47,12 @@ typedef enum { event_rot_left_down, event_rot_right_down, event_rot_press, + event_uart_rx, event_ocp, - event_ovp + event_ovp, + + event_shutoff } event_t; typedef enum { diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index f55df210..e2b563ef 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -50,11 +50,15 @@ #include "opendps.h" /* - * This is the implementation of the DPS look-alike screen. It has 3 editable + * This is the implementation of the DPS look-alike screen. It has 3+ editable * properties. * Voltage limit (constant voltage) * Current limit (constant current) - * Power limit (over power protection, 0 to disable) + * Third Item. Displays one of: + * * Power limit (over power protection, 0 to disable) + * * Timer + * * Watt-hour + * * Brightness */ static void dpsmode_enable(bool _enable); @@ -513,8 +517,7 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { saved_t = recall_t[0]; // Turn off power - dpsmode_enable(false); - opendps_update_power_status(false); + event_put(event_shutoff, 0); // show the M1 recall graphics dpsmode_graphics &= ~CUR_GFX_M2_RECALL; @@ -528,8 +531,7 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { saved_t = recall_t[1]; // Turn off power - dpsmode_enable(false); - opendps_update_power_status(false); + event_put(event_shutoff, 0); // show the M2 recall graphics dpsmode_graphics &= ~CUR_GFX_M1_RECALL; @@ -858,8 +860,7 @@ static void dpsmode_tick(void) dpsmode_graphics &= ~CUR_GFX_TM; // power off - dpsmode_enable(false); - opendps_update_power_status(false); + event_put(event_shutoff, 0); } // over 80% power (if defined, or absolute maximum), show warning @@ -909,8 +910,7 @@ static void dpsmode_tick(void) third_invalidate = true; // power off - dpsmode_enable(false); - opendps_update_power_status(false); + event_put(event_shutoff, 0); } } diff --git a/opendps/opendps.c b/opendps/opendps.c index a443edb7..0b0d8636 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -473,6 +473,7 @@ static void ui_handle_event(event_t event, uint8_t data) if (event == event_rot_press && data == press_long) { opendps_lock(!is_locked); return; + } else if (event == event_button_sel && data == press_long) { tft_invert(!tft_is_inverted()); write_past_settings(); @@ -480,20 +481,8 @@ static void ui_handle_event(event_t event, uint8_t data) } if (is_locked) { - switch(event) { - case event_button_m1: - case event_button_m2: - case event_button_sel: - case event_rot_press: - case event_rot_left: - case event_rot_right: - case event_button_enable: - lock_flashing_period = LOCK_FLASHING_PERIOD; - lock_flash_counter = LOCK_FLASHING_COUNTER; - return; - default: - break; - } + lock_flashing_period = LOCK_FLASHING_PERIOD; + lock_flash_counter = LOCK_FLASHING_COUNTER; } switch(event) { @@ -509,7 +498,6 @@ static void ui_handle_event(event_t event, uint8_t data) #endif // CONFIG_OCP_DEBUGGING ui_flash(); /** @todo When OCP kicks in, show last I_out on screen */ opendps_update_power_status(false); - uui_handle_screen_event(current_ui, event, data); } break; @@ -525,7 +513,6 @@ static void ui_handle_event(event_t event, uint8_t data) #endif // CONFIG_OVP_DEBUGGING ui_flash(); /** @todo When OVP kicks in, show last V_out on screen */ opendps_update_power_status(false); - uui_handle_screen_event(current_ui, event, data); } break; @@ -534,44 +521,24 @@ static void ui_handle_event(event_t event, uint8_t data) opendps_change_screen(target_screen_id); break; - case event_button_enable: -#pragma GCC diagnostic ignored "-Wimplicit-fallthrough" - write_past_settings(); - /** Deliberate fallthrough */ - case event_button_m1: - case event_button_m2: - case event_button_sel: - case event_button_sel_m1: - case event_button_sel_m2: - case event_rot_press: - case event_rot_left: - case event_rot_right: - case event_rot_left_m1: - case event_rot_right_m1: - case event_rot_left_m2: - case event_rot_right_m2: - case event_rot_left_down: - case event_rot_right_down: - uui_handle_screen_event(current_ui, event, data); - //uui_refresh(current_ui, false); - break; - case event_rot_left_set: case event_rot_right_set: // lock out set+rotation when power is on if (pwrctl_vout_enabled()) { + // TODO: Show only briefly? lock_flashing_period = LOCK_FLASHING_PERIOD; lock_flash_counter = LOCK_FLASHING_COUNTER; break; } - uui_handle_screen_event(current_ui, event, data); - //uui_refresh(current_ui, false); break; - default: + case event_button_enable: + write_past_settings(); break; } + + uui_handle_screen_event(current_ui, event, data); } /** @@ -584,9 +551,11 @@ void opendps_lock(bool lock) if (is_locked != lock) { is_locked = lock; lock_flashing_period = 0; + if (is_locked) { lock_visible = true; tft_blit((uint16_t*) gfx_padlock, GFX_PADLOCK_WIDTH, GFX_PADLOCK_HEIGHT, XPOS_LOCK, ui_height-GFX_PADLOCK_HEIGHT); + } else { lock_visible = false; tft_fill(XPOS_LOCK, ui_height-GFX_PADLOCK_HEIGHT, GFX_PADLOCK_WIDTH, GFX_PADLOCK_HEIGHT, bg_color); diff --git a/opendps/uui.c b/opendps/uui.c index 2c214a36..b29495cc 100644 --- a/opendps/uui.c +++ b/opendps/uui.c @@ -174,17 +174,6 @@ void uui_handle_screen_event(uui_t *ui, event_t event, uint8_t data) uui_next_screen(ui); break; - case event_rot_left_m1: - case event_rot_right_m1: - case event_rot_left_m2: - case event_rot_right_m2: - case event_rot_left_down: - case event_rot_right_down: - case event_button_sel_m1: - case event_button_sel_m2: - // do nothing - break; - case event_rot_left: case event_rot_right: case event_rot_press: @@ -227,6 +216,7 @@ void uui_handle_screen_event(uui_t *ui, event_t event, uint8_t data) } break; + case event_shutoff: case event_button_enable: case event_ocp: case event_ovp: @@ -241,6 +231,19 @@ void uui_handle_screen_event(uui_t *ui, event_t event, uint8_t data) } break; + case event_rot_left_m1: + case event_rot_right_m1: + case event_rot_left_m2: + case event_rot_right_m2: + case event_rot_left_down: + case event_rot_right_down: + case event_button_sel_m1: + case event_button_sel_m2: + case event_shutoff: + case event_lock: + // do nothing + break; + default: assert(0); } From 414f2682e71e9c407f4b733c9f675d1eea3f6964 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Thu, 3 Oct 2019 21:11:47 -0600 Subject: [PATCH 083/175] Removed stringent uui.c event checks --- opendps/uui.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/opendps/uui.c b/opendps/uui.c index b29495cc..882c4211 100644 --- a/opendps/uui.c +++ b/opendps/uui.c @@ -230,22 +230,6 @@ void uui_handle_screen_event(uui_t *ui, event_t event, uint8_t data) opendps_update_power_status(screen->is_enabled); /** @todo: move */ } break; - - case event_rot_left_m1: - case event_rot_right_m1: - case event_rot_left_m2: - case event_rot_right_m2: - case event_rot_left_down: - case event_rot_right_down: - case event_button_sel_m1: - case event_button_sel_m2: - case event_shutoff: - case event_lock: - // do nothing - break; - - default: - assert(0); } } From 1bbb10b90a8a07d1726b187f1b094821652c5001 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Thu, 3 Oct 2019 21:15:01 -0600 Subject: [PATCH 084/175] Fixed bug with updating last time ui was drawn --- opendps/opendps.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/opendps/opendps.c b/opendps/opendps.c index 0b0d8636..574c748f 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -909,10 +909,9 @@ static void event_handler(void) /** Update on the first call and every UI_UPDATE_INTERVAL_MS ms */ if (last <= 0 || get_ticks() - last >= UI_UPDATE_INTERVAL_MS) { ui_tick(); + last = get_ticks(); } - last = get_ticks(); - } else { if (event) { emu_printf(" Event %d 0x%02x\n", event, data); From a46cd2ad9135509038f8119446eda0cc7c24fe76 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Thu, 3 Oct 2019 21:24:30 -0600 Subject: [PATCH 085/175] Locked inputs will now do nothing --- opendps/opendps.c | 1 + opendps/uui_time.c | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/opendps/opendps.c b/opendps/opendps.c index 574c748f..2b5898ce 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -483,6 +483,7 @@ static void ui_handle_event(event_t event, uint8_t data) if (is_locked) { lock_flashing_period = LOCK_FLASHING_PERIOD; lock_flash_counter = LOCK_FLASHING_COUNTER; + return; } switch(event) { diff --git a/opendps/uui_time.c b/opendps/uui_time.c index 93ffc1b1..038b87dd 100644 --- a/opendps/uui_time.c +++ b/opendps/uui_time.c @@ -257,8 +257,8 @@ static void number_draw(ui_item_t *_item) xpos += digit_w + spacing; // : - tft_putch(item->font_size, '.', xpos, _item->y - (h>>2) + (h >> 1), dot_width, h >> 4, color, false); - tft_putch(item->font_size, '.', xpos, _item->y - (h>>2) , dot_width, h >> 4, color, false); + tft_putch(item->font_size, '.', xpos, _item->y - (h>>2) + (h >> 1), dot_width, h >> 2, color, false); + tft_putch(item->font_size, '.', xpos, _item->y - (h>>2) , dot_width, h >> 2, color, false); xpos += dot_width + spacing; // MM @@ -281,8 +281,8 @@ static void number_draw(ui_item_t *_item) xpos += digit_w + spacing; // : - tft_putch(item->font_size, '.', xpos, _item->y - (h>>2) + (h >> 1), dot_width, h >> 3, color, false); - tft_putch(item->font_size, '.', xpos, _item->y - (h>>2) , dot_width, h >> 3, color, false); + tft_putch(item->font_size, '.', xpos, _item->y - (h>>2) + (h >> 1), dot_width, h >> 2, color, false); + tft_putch(item->font_size, '.', xpos, _item->y - (h>>2) , dot_width, h >> 2, color, false); xpos += dot_width + spacing; // SS From c0396c8ddcfe5e738881722d87d7e5f248104834 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Thu, 3 Oct 2019 21:29:31 -0600 Subject: [PATCH 086/175] Pressing rot should focus on 3rd item being displayed --- opendps/func_dpsmode.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index e2b563ef..101d9cca 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -573,6 +573,16 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { } break; + case event_rot_presse: + // pressing rot should focus on 3rd item if not already in select mode + if (third_item && ! select_mode) { + if (((ui_number_t *)third_item)->ui.can_focus) { + uui_focus(ui, (ui_item_t *)third_item); + select_mode = true; + return false; + } + break; + default: break; } From d084750ec1b0a4d36380ac6aae919f949f91b74c Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Thu, 3 Oct 2019 21:30:12 -0600 Subject: [PATCH 087/175] Fixed typo --- opendps/func_dpsmode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 101d9cca..dd904461 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -573,7 +573,7 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { } break; - case event_rot_presse: + case event_rot_press: // pressing rot should focus on 3rd item if not already in select mode if (third_item && ! select_mode) { if (((ui_number_t *)third_item)->ui.can_focus) { From 637f9daf98766eb970122fed8ffd43b82247cc0b Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Thu, 3 Oct 2019 21:31:06 -0600 Subject: [PATCH 088/175] Missing braket --- opendps/func_dpsmode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index dd904461..409d1b0b 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -581,6 +581,7 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { select_mode = true; return false; } + } break; default: From c926c8146ba6ce558b8a1c15dc6f98b66945e58f Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Thu, 3 Oct 2019 21:38:51 -0600 Subject: [PATCH 089/175] Added brightness label --- opendps/func_dpsmode.c | 6 ++++++ opendps/opendps.c | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 409d1b0b..0de52182 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -939,6 +939,12 @@ static void dpsmode_tick(void) clear_third_region(); } + // if drawing brightness, show "Brightness:" before value. + if (third_item == dpsmode_brightness) { + tft_puts(FONT_FULL_SMALL, "Brightness:", 5, YPOS_POWER, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 12, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, color, false); + } + + // draw 3rd item ((ui_number_t *)third_item)->ui.draw(& ((ui_number_t *)third_item)->ui); } else { diff --git a/opendps/opendps.c b/opendps/opendps.c index 2b5898ce..d8718758 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -529,7 +529,7 @@ static void ui_handle_event(event_t event, uint8_t data) // TODO: Show only briefly? lock_flashing_period = LOCK_FLASHING_PERIOD; lock_flash_counter = LOCK_FLASHING_COUNTER; - break; + return; } break; From e0035f9daf8918c1fd4ba3b90a6cfb4bf92a035b Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Thu, 3 Oct 2019 21:46:37 -0600 Subject: [PATCH 090/175] Recall setting will turn off power Brightness label should be aligned properly --- opendps/func_dpsmode.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 0de52182..0358caa7 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -503,6 +503,9 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { dpsmode_graphics |= CUR_GFX_M2_RECALL; } + // Turn off power + event_put(event_shutoff, 0); + return true; case event_button_sel: @@ -940,8 +943,10 @@ static void dpsmode_tick(void) } // if drawing brightness, show "Brightness:" before value. - if (third_item == dpsmode_brightness) { - tft_puts(FONT_FULL_SMALL, "Brightness:", 5, YPOS_POWER, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 12, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, color, false); + if (third_item == (ui_item_t *)&dpsmode_brightness) { + tft_puts(FONT_FULL_SMALL, "Brightness:", 5, YPOS_POWER + (FONT_FULL_SMALL_MAX_GLYPH_HEIGHT << 2), + FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 12, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, + WHITE, false); } // draw 3rd item From 8b79e14b705a11ab7023b293653956086affc76a Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Thu, 3 Oct 2019 21:50:11 -0600 Subject: [PATCH 091/175] Shutoff event always shuts power off Align brightness label --- opendps/func_dpsmode.c | 2 +- opendps/uui.c | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 0358caa7..b3db6189 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -944,7 +944,7 @@ static void dpsmode_tick(void) // if drawing brightness, show "Brightness:" before value. if (third_item == (ui_item_t *)&dpsmode_brightness) { - tft_puts(FONT_FULL_SMALL, "Brightness:", 5, YPOS_POWER + (FONT_FULL_SMALL_MAX_GLYPH_HEIGHT << 2), + tft_puts(FONT_FULL_SMALL, "Brightness:", 5, YPOS_POWER + (FONT_FULL_SMALL_MAX_GLYPH_HEIGHT << 1) + 5, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 12, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, WHITE, false); } diff --git a/opendps/uui.c b/opendps/uui.c index 882c4211..01e4501b 100644 --- a/opendps/uui.c +++ b/opendps/uui.c @@ -220,12 +220,21 @@ void uui_handle_screen_event(uui_t *ui, event_t event, uint8_t data) case event_button_enable: case event_ocp: case event_ovp: + /** If current screen can be enabled */ if (screen->enable) { - screen->is_enabled = !screen->is_enabled; + if (event == event_shutoff) { + // always turn off with shutoff event + screen->is_enabled = false; + } else { + // toggle + screen->is_enabled = ! screen->is_enabled; + } + if (screen->is_enabled && screen->past_save) { screen->past_save(ui->past); } + screen->enable(screen->is_enabled); opendps_update_power_status(screen->is_enabled); /** @todo: move */ } From 2a68c2c28529b1816e1dc3c47b47bfb173048604 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Thu, 3 Oct 2019 21:57:58 -0600 Subject: [PATCH 092/175] Brightness label alignment --- opendps/func_dpsmode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index b3db6189..7cd4c371 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -944,7 +944,7 @@ static void dpsmode_tick(void) // if drawing brightness, show "Brightness:" before value. if (third_item == (ui_item_t *)&dpsmode_brightness) { - tft_puts(FONT_FULL_SMALL, "Brightness:", 5, YPOS_POWER + (FONT_FULL_SMALL_MAX_GLYPH_HEIGHT << 1) + 5, + tft_puts(FONT_FULL_SMALL, "Brightness:", 5, YPOS_POWER + (FONT_FULL_SMALL_MAX_GLYPH_HEIGHT << 1) - 5, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 12, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, WHITE, false); } From 46947df56f7a0a36663acf4c0a0e6c3efd1706e9 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Thu, 3 Oct 2019 22:08:19 -0600 Subject: [PATCH 093/175] Brightness recall is adjusted properly Align Brightness label --- opendps/func_dpsmode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 7cd4c371..393548b8 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -810,7 +810,7 @@ static void dpsmode_tick(void) // update brightness if 0 (because it's most likely not set) if (dpsmode_brightness.value == 0) - dpsmode_brightness.value = hw_get_backlight(); + dpsmode_brightness.value = hw_get_backlight() / 1.28f; // power enabled if (pwrctl_vout_enabled()) { @@ -944,7 +944,7 @@ static void dpsmode_tick(void) // if drawing brightness, show "Brightness:" before value. if (third_item == (ui_item_t *)&dpsmode_brightness) { - tft_puts(FONT_FULL_SMALL, "Brightness:", 5, YPOS_POWER + (FONT_FULL_SMALL_MAX_GLYPH_HEIGHT << 1) - 5, + tft_puts(FONT_FULL_SMALL, "Brightness:", 5, YPOS_POWER + (FONT_FULL_SMALL_MAX_GLYPH_HEIGHT << 1) - 10, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 12, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, WHITE, false); } From 05ac26c6a167279ae8fba36114c65625b93b9e43 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Thu, 3 Oct 2019 22:14:14 -0600 Subject: [PATCH 094/175] Reset any modes on activation --- opendps/func_dpsmode.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 393548b8..0c2788f0 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -647,6 +647,10 @@ static void activated(void) { clear_bars(true); clear_third_region(); + // reset any odd modes + single_edit_mode = false; + select_mode = false; + // reset watthour value when we leave the screen. dpsmode_watthour.value = 0; } @@ -944,7 +948,7 @@ static void dpsmode_tick(void) // if drawing brightness, show "Brightness:" before value. if (third_item == (ui_item_t *)&dpsmode_brightness) { - tft_puts(FONT_FULL_SMALL, "Brightness:", 5, YPOS_POWER + (FONT_FULL_SMALL_MAX_GLYPH_HEIGHT << 1) - 10, + tft_puts(FONT_FULL_SMALL, "Brightness:", 5, YPOS_POWER + (FONT_FULL_SMALL_MAX_GLYPH_HEIGHT << 1) - 7, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 12, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, WHITE, false); } From 3fef0ae815dd25914acc7f37314fbf3167925009 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Thu, 3 Oct 2019 23:01:07 -0600 Subject: [PATCH 095/175] Fixed unresponsive ui --- opendps/opendps.c | 1 + 1 file changed, 1 insertion(+) diff --git a/opendps/opendps.c b/opendps/opendps.c index d8718758..ae8c7c93 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -540,6 +540,7 @@ static void ui_handle_event(event_t event, uint8_t data) } uui_handle_screen_event(current_ui, event, data); + uui_refresh(current_ui, false); } /** From db5957ac7b2f326086f00c0aeb7113d33a8586e1 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 5 Oct 2019 13:42:37 -0600 Subject: [PATCH 096/175] Makefile build should only contain dpsmode files if compiled with dpsmode Reverted some tweaks to OpenDPS defaults --- opendps/Makefile | 10 +--------- opendps/opendps.c | 25 ++++++++----------------- 2 files changed, 9 insertions(+), 26 deletions(-) diff --git a/opendps/Makefile b/opendps/Makefile index c377bf9e..2ec279b2 100644 --- a/opendps/Makefile +++ b/opendps/Makefile @@ -115,14 +115,6 @@ OBJS = \ gfx-crosshair.o \ gfx-cv.o \ gfx-cl.o \ - gfx-iconpower.o \ - gfx-cvbar.o \ - gfx-ccbar.o \ - gfx-ppbar.o \ - gfx-oppbar.o \ - gfx-tmbar.o \ - gfx-m1bar.o \ - gfx-m2bar.o \ gfx-padlock.o \ gfx-thermometer.o \ gfx-wifi.o \ @@ -164,7 +156,7 @@ endif ifeq ($(DPSMODE_ENABLE),1) CFLAGS +=-DCONFIG_DPSMODE_ENABLE - OBJS += func_dpsmode.o + OBJS += func_dpsmode.o gfx-cvbar.o gfx-ccbar.o gfx-ppbar.o gfx-oppbar.o gfx-tmbar.o gfx-m1bar.o gfx-m2bar.o gfx-iconpower.o endif ifeq ($(FUNCGEN_ENABLE),1) diff --git a/opendps/opendps.c b/opendps/opendps.c index c10139b8..e22bf89b 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -88,7 +88,7 @@ #endif // CONFIG_SPLASH_SCREEN /** How ofter we update the measurements in the UI (ms) */ -#define UI_UPDATE_INTERVAL_MS (100) +#define UI_UPDATE_INTERVAL_MS (250) /** Timeout for waiting for wifi connction (ms) */ #define WIFI_CONNECT_TIMEOUT (10000) @@ -520,7 +520,6 @@ static void ui_handle_event(event_t event, uint8_t data) opendps_update_power_status(false); } break; - case event_ovp: { #ifdef CONFIG_OVP_DEBUGGING @@ -535,8 +534,7 @@ static void ui_handle_event(event_t event, uint8_t data) opendps_update_power_status(false); } break; - - case event_button_m1_and_m2: ; + case event_buttom_m1_and_m2: uint8_t target_screen_id = current_ui == &func_ui ? SETTINGS_UI_ID : FUNC_UI_ID; /** Change between the settings and functional screen */ opendps_change_screen(target_screen_id); break; @@ -551,14 +549,13 @@ static void ui_handle_event(event_t event, uint8_t data) return; } - break; - case event_button_enable: write_past_settings(); + default: break; } - uui_handle_screen_event(current_ui, event, data); + uui_handle_screen_event(current_ui, event); uui_refresh(current_ui, false); } @@ -572,11 +569,9 @@ void opendps_lock(bool lock) if (is_locked != lock) { is_locked = lock; lock_flashing_period = 0; - if (is_locked) { lock_visible = true; tft_blit((uint16_t*) gfx_padlock, GFX_PADLOCK_WIDTH, GFX_PADLOCK_HEIGHT, XPOS_LOCK, ui_height-GFX_PADLOCK_HEIGHT); - } else { lock_visible = false; tft_fill(XPOS_LOCK, ui_height-GFX_PADLOCK_HEIGHT, GFX_PADLOCK_WIDTH, GFX_PADLOCK_HEIGHT, bg_color); @@ -601,7 +596,7 @@ void opendps_temperature_lock(bool lock) tft_clear(); uui_show(current_ui, false); uui_show(&main_ui, false); - // tft_blit((uint16_t*) gfx_thermometer, GFX_THERMOMETER_WIDTH, GFX_THERMOMETER_HEIGHT, 1+(ui_width-GFX_THERMOMETER_WIDTH)/2, 30); + tft_blit((uint16_t*) gfx_thermometer, GFX_THERMOMETER_WIDTH, GFX_THERMOMETER_HEIGHT, 1+(ui_width-GFX_THERMOMETER_WIDTH)/2, 30); } else { emu_printf("DPS enabled due to temperature\n"); tft_clear(); @@ -948,16 +943,14 @@ static void event_handler(void) while(1) { event_t event; uint8_t data = 0; - - if ( ! event_get(&event, &data)) { + if (!event_get(&event, &data)) { hw_longpress_check(); - /** Update on the first call and every UI_UPDATE_INTERVAL_MS ms */ + // update every UI_UPDATE_INTERVAL_MS if (last <= 0 || get_ticks() - last >= UI_UPDATE_INTERVAL_MS) { ui_tick(); last = get_ticks(); } - } else { if (event) { emu_printf(" Event %d 0x%02x\n", event, data); @@ -974,10 +967,8 @@ static void event_handler(void) default: break; } - ui_handle_event(event, data); - - // call ui_tick immediately because event could have caused UI changes + // update UI immediately on event ui_tick(); } } From 2165b88b6619e966aa3632f832f27532a799d27b Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 5 Oct 2019 13:44:37 -0600 Subject: [PATCH 097/175] Refined dps mode values --- opendps/dps-model.h | 9 +++++---- opendps/opendps.c | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/opendps/dps-model.h b/opendps/dps-model.h index 8c516e1a..c02aec0d 100644 --- a/opendps/dps-model.h +++ b/opendps/dps-model.h @@ -60,11 +60,12 @@ #define CONFIG_DPS_MAX_CURRENT (5000) #endif #define ADC_CHA_IOUT_GOLDEN_VALUE (0x45) - #define A_ADC_K (float) 1.71083908618961f - #define A_ADC_C (float) -120.124411804613f + #define A_ADC_K (float) 1.7068604363612f + #define A_ADC_C (float) -127.302771802896f - #define A_DAC_K (float) 0.647948164146868f - #define A_DAC_C (float) 278.025917926566f + + #define A_DAC_K (float) 0.65093572009764f + #define A_DAC_C (float) 271.440195280716f #define V_DAC_K (float) 0.076447899114725f #define V_DAC_C (float) 3.22404026358549f diff --git a/opendps/opendps.c b/opendps/opendps.c index 43204aa5..d999ee6b 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -550,6 +550,7 @@ static void ui_handle_event(event_t event, uint8_t data) } uui_handle_screen_event(current_ui, event, data); + uui_refresh(current_ui, false); } /** From b6ae18809be4a611ee02a8996c5e7beae5171582 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 5 Oct 2019 13:49:11 -0600 Subject: [PATCH 098/175] Fixed regression on opendps uui calls --- opendps/opendps.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opendps/opendps.c b/opendps/opendps.c index e22bf89b..e8d6b54f 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -534,7 +534,7 @@ static void ui_handle_event(event_t event, uint8_t data) opendps_update_power_status(false); } break; - case event_buttom_m1_and_m2: + case event_button_m1_and_m2: uint8_t target_screen_id = current_ui == &func_ui ? SETTINGS_UI_ID : FUNC_UI_ID; /** Change between the settings and functional screen */ opendps_change_screen(target_screen_id); break; @@ -555,7 +555,7 @@ static void ui_handle_event(event_t event, uint8_t data) break; } - uui_handle_screen_event(current_ui, event); + uui_handle_screen_event(current_ui, event, data); uui_refresh(current_ui, false); } From e8f3657cd8418f60d0b557170492e9e09bc93422 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 5 Oct 2019 13:56:43 -0600 Subject: [PATCH 099/175] Blinking done by MOD rather than bitshift --- opendps/func_dpsmode.c | 6 +++--- opendps/opendps.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 0c2788f0..afbf3688 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -1007,7 +1007,7 @@ static void draw_bars() { // draw timer if (dpsmode_graphics & CUR_GFX_TM) { // blink the timer icon - if ((get_ticks() >> 9) & 1) + if ((get_ticks() % 500) == 0) tft_blit((uint16_t*) gfx_tmbar, GFX_TMBAR_WIDTH, GFX_TMBAR_HEIGHT, TFT_WIDTH - GFX_TMBAR_WIDTH, @@ -1022,7 +1022,7 @@ static void draw_bars() { // draw opp if (dpsmode_graphics & CUR_GFX_OPP) { // blink the opp warning - if (((get_ticks() >> 9) & 1) == 0) + if ((get_ticks() % 500) == 0) tft_blit((uint16_t*) gfx_oppbar, GFX_OPPBAR_WIDTH, GFX_OPPBAR_HEIGHT, TFT_WIDTH - GFX_OPPBAR_WIDTH, @@ -1036,7 +1036,7 @@ static void draw_bars() { // draw pp else if (dpsmode_graphics & CUR_GFX_PP) { // if timer (or other icons), blink it so it is visible. - if (((get_ticks() >> 9) & 1) == 0) + if ((get_ticks() % 500) == 0) tft_blit((uint16_t*) gfx_ppbar, GFX_PPBAR_WIDTH, GFX_PPBAR_HEIGHT, TFT_WIDTH - GFX_PPBAR_WIDTH, diff --git a/opendps/opendps.c b/opendps/opendps.c index e8d6b54f..5aaabce5 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -534,7 +534,7 @@ static void ui_handle_event(event_t event, uint8_t data) opendps_update_power_status(false); } break; - case event_button_m1_and_m2: + case event_button_m1_and_m2:; uint8_t target_screen_id = current_ui == &func_ui ? SETTINGS_UI_ID : FUNC_UI_ID; /** Change between the settings and functional screen */ opendps_change_screen(target_screen_id); break; From e23a6bd34549182a47733f21ddc97a4e19293072 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 5 Oct 2019 14:32:40 -0600 Subject: [PATCH 100/175] Blink should be more constant Ensure that the timer is focused when it counts down --- opendps/func_dpsmode.c | 18 +++++++++++++----- opendps/uui_time.c | 8 ++++---- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index afbf3688..3a109bfe 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -250,7 +250,7 @@ ui_number_t dpsmode_brightness = { .pad_dot = false, .color = WHITE, .value = 0, - .min = 0, + .min = 1, .max = 100, .si_prefix = si_none, // percentage, so 0-100 .num_digits = 3, @@ -698,6 +698,11 @@ static void determine_focused_item(uui_t *ui, int8_t direction) { third_item = (ui_item_t *)screen->items[focus_index]; third_row = focus_index - 2; third_invalidate = true; + } else if (focus_index == 1) { + // because timer can change the screen's focused item, but not the screen's cur_item + // when moving to the 2nd item, both the timer and the last 3rd item are displayed + // invalidate this case to ensure this does not happen + third_invalidate = true; } } @@ -923,7 +928,10 @@ static void dpsmode_tick(void) // timer enabled, count down if (saved_t > 0 && dpsmode_timer.value <= 0) { // timer has counted down - // show the timer + // show the timer and ensure it's focused + uui_focus(ui, (ui_item_t *)third_item); + if (dpsmode_voltage.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_voltage); + third_item = &dpsmode_timer; third_invalidate = true; @@ -1007,7 +1015,7 @@ static void draw_bars() { // draw timer if (dpsmode_graphics & CUR_GFX_TM) { // blink the timer icon - if ((get_ticks() % 500) == 0) + if ((get_ticks() % 2000) <= 1000) tft_blit((uint16_t*) gfx_tmbar, GFX_TMBAR_WIDTH, GFX_TMBAR_HEIGHT, TFT_WIDTH - GFX_TMBAR_WIDTH, @@ -1022,7 +1030,7 @@ static void draw_bars() { // draw opp if (dpsmode_graphics & CUR_GFX_OPP) { // blink the opp warning - if ((get_ticks() % 500) == 0) + if ((get_ticks() % 2000) > 1000) tft_blit((uint16_t*) gfx_oppbar, GFX_OPPBAR_WIDTH, GFX_OPPBAR_HEIGHT, TFT_WIDTH - GFX_OPPBAR_WIDTH, @@ -1036,7 +1044,7 @@ static void draw_bars() { // draw pp else if (dpsmode_graphics & CUR_GFX_PP) { // if timer (or other icons), blink it so it is visible. - if ((get_ticks() % 500) == 0) + if ((get_ticks() % 2000) > 1000) tft_blit((uint16_t*) gfx_ppbar, GFX_PPBAR_WIDTH, GFX_PPBAR_HEIGHT, TFT_WIDTH - GFX_PPBAR_WIDTH, diff --git a/opendps/uui_time.c b/opendps/uui_time.c index 038b87dd..4af3f5c0 100644 --- a/opendps/uui_time.c +++ b/opendps/uui_time.c @@ -257,8 +257,8 @@ static void number_draw(ui_item_t *_item) xpos += digit_w + spacing; // : - tft_putch(item->font_size, '.', xpos, _item->y - (h>>2) + (h >> 1), dot_width, h >> 2, color, false); - tft_putch(item->font_size, '.', xpos, _item->y - (h>>2) , dot_width, h >> 2, color, false); + tft_putch(item->font_size, '.', xpos, _item->y - (h>>2) + (h >> 1), dot_width, 3, color, false); + tft_putch(item->font_size, '.', xpos, _item->y - (h>>2) , dot_width, 3, color, false); xpos += dot_width + spacing; // MM @@ -281,8 +281,8 @@ static void number_draw(ui_item_t *_item) xpos += digit_w + spacing; // : - tft_putch(item->font_size, '.', xpos, _item->y - (h>>2) + (h >> 1), dot_width, h >> 2, color, false); - tft_putch(item->font_size, '.', xpos, _item->y - (h>>2) , dot_width, h >> 2, color, false); + tft_putch(item->font_size, '.', xpos, _item->y - (h>>2) + (h >> 1), dot_width, 3, color, false); + tft_putch(item->font_size, '.', xpos, _item->y - (h>>2) , dot_width, 3, color, false); xpos += dot_width + spacing; // SS From 5cd3fad4aea146e8c8af9d73bb62bd186b2ece1e Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 5 Oct 2019 14:37:01 -0600 Subject: [PATCH 101/175] Added timer event to cause poweroff and UI updates --- opendps/event.h | 3 ++- opendps/func_dpsmode.c | 30 +++++++++++++----------------- opendps/uui.c | 1 + 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/opendps/event.h b/opendps/event.h index 5b8b0053..f2f363d5 100644 --- a/opendps/event.h +++ b/opendps/event.h @@ -52,7 +52,8 @@ typedef enum { event_ocp, event_ovp, - event_shutoff + event_shutoff, + event_timer } event_t; typedef enum { diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 3a109bfe..5a5a19c9 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -587,12 +587,6 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { } break; - default: - break; - } - - - switch(event) { case event_button_m1: // if in normal select mode, let parent handle it if (select_mode) { @@ -633,6 +627,17 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { return false; + case event_timer: + // timer has counted down + // show the timer and ensure it's focused + third_item = &dpsmode_timer; + third_invalidate = true; + + uui_focus(ui, (ui_item_t *)third_item); + if (dpsmode_voltage.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_voltage); + + return true; + default: return false; } @@ -927,18 +932,9 @@ static void dpsmode_tick(void) // timer enabled, count down if (saved_t > 0 && dpsmode_timer.value <= 0) { - // timer has counted down - // show the timer and ensure it's focused - uui_focus(ui, (ui_item_t *)third_item); - if (dpsmode_voltage.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_voltage); - - third_item = &dpsmode_timer; - third_invalidate = true; - - // power off - event_put(event_shutoff, 0); + // timer event will cause a power off + event_put(event_timer, 0); } - } diff --git a/opendps/uui.c b/opendps/uui.c index 01e4501b..7b59c7b8 100644 --- a/opendps/uui.c +++ b/opendps/uui.c @@ -216,6 +216,7 @@ void uui_handle_screen_event(uui_t *ui, event_t event, uint8_t data) } break; + case event_timer: case event_shutoff: case event_button_enable: case event_ocp: From 0b73386d4b643eb37cfb06a82f02b8965b4eb19d Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 5 Oct 2019 14:45:35 -0600 Subject: [PATCH 102/175] Fixed duplicate event cases --- opendps/func_dpsmode.c | 90 +++++++++++++++++++++++------------------- 1 file changed, 49 insertions(+), 41 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 5a5a19c9..6cfeccaf 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -509,6 +509,26 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { return true; case event_button_sel: + // leave single edit mode on any button press + if (single_edit_mode) { + single_edit_mode = false; + + // toggle focus on anything that is in focus (to unfocus) + if (dpsmode_voltage.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_voltage); + if (dpsmode_current.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_current); + } + + // toggle select mode, so parent can deal with other UI elements + // keep track, so this screen will not do anything until we leave this mode + select_mode = ! select_mode; + + if (select_mode) { + determine_focused_item(ui, 0); + return false; + } + + return false; + case event_button_m1: case event_button_m2: @@ -527,6 +547,7 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { dpsmode_graphics |= CUR_GFX_M1_RECALL; return true; } + if (event == event_button_m2 && data == press_long) { saved_v = recall_v[1]; saved_i = recall_i[1]; @@ -542,7 +563,6 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { return true; } - // leave single edit mode on any button press if (single_edit_mode) { single_edit_mode = false; @@ -550,11 +570,38 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { // toggle focus on anything that is in focus (to unfocus) if (dpsmode_voltage.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_voltage); if (dpsmode_current.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_current); + return true; } + // for either m1/m2 buttons: + if (event == event_button_m1) { + // if in normal select mode, let parent handle it + if (select_mode) { + // third item focused may have changed + determine_focused_item(ui, -1); - break; + return false; + } + + // focus on voltage if not already focused + if ( ! dpsmode_voltage.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_voltage); + + } + if (event == event_button_m2) { + if (select_mode) { + determine_focused_item(ui, 1); + return false; + } + + if ( ! dpsmode_current.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_current); + } + + // otherwise, enter single edit mode + single_edit_mode = true; + + // we handled it, parent should do nothing + return true; case event_rot_left_down: case event_rot_right_down: @@ -587,45 +634,6 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { } break; - case event_button_m1: - // if in normal select mode, let parent handle it - if (select_mode) { - // third item focused may have changed - determine_focused_item(ui, -1); - - return false; - } - - // otherwise, enter single edit mode - single_edit_mode = true; - - // focus on voltage if not already focused - if ( ! dpsmode_voltage.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_voltage); - - // we handled it, parent should do nothing - return true; - - case event_button_m2: - if (select_mode) { - determine_focused_item(ui, 1); - return false; - } - - single_edit_mode = true; - if ( ! dpsmode_current.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_current); - return true; - - case event_button_sel: - // toggle select mode, so parent can deal with other UI elements - // keep track, so this screen will not do anything until we leave this mode - select_mode = ! select_mode; - - if (select_mode) { - determine_focused_item(ui, 0); - return false; - } - - return false; case event_timer: // timer has counted down From f90ff78b6265b23f4884be644d4bead63015e5b6 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 5 Oct 2019 14:56:08 -0600 Subject: [PATCH 103/175] Timer event will trigger when timer value is set to 0 Set button will leave single edit mode properly --- opendps/func_dpsmode.c | 27 +++++++++++++++++++-------- opendps/uui.c | 4 ++-- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 6cfeccaf..ac685d0c 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -2,7 +2,7 @@ * The MIT License (MIT) * * Copyright (c) 2019 Johan Kanflo (github.com/kanflo) - * Modifications made by Leo Leung + * Leo Leung * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -422,6 +422,7 @@ static void dpsmode_enable(bool enabled) */ static void voltage_changed(ui_number_t *item) { + // clear recall as values no longer match dpsmode_graphics &= ~CUR_GFX_M1_RECALL; dpsmode_graphics &= ~CUR_GFX_M2_RECALL; @@ -436,6 +437,7 @@ static void voltage_changed(ui_number_t *item) */ static void current_changed(ui_number_t *item) { + // clear recall as values no longer match dpsmode_graphics &= ~CUR_GFX_M1_RECALL; dpsmode_graphics &= ~CUR_GFX_M2_RECALL; @@ -450,11 +452,11 @@ static void current_changed(ui_number_t *item) */ static void power_changed(ui_number_t *item) { + // clear recall as values no longer match dpsmode_graphics &= ~CUR_GFX_M1_RECALL; dpsmode_graphics &= ~CUR_GFX_M2_RECALL; saved_p = item->value; - // (void) pwrctl_set_iout(item->value); } /** @@ -467,15 +469,22 @@ static void watthour_changed(ui_number_t *item) { } static void timer_changed(ui_time_t *item) { + // clear recall as values no longer match dpsmode_graphics &= ~CUR_GFX_M1_RECALL; dpsmode_graphics &= ~CUR_GFX_M2_RECALL; - // do nothing yet... + // If timer changed from non-zero to zero, trigger timer event to stop power + if (saved_t > 0 && item->value <= 0) { + event_put(event_timer, 0); + } + + // update timer value saved_t = item->value; } static void brightness_changed(ui_number_t *item) { // update brightness + // 100% = 128, 0% = 0 hw_set_backlight(item->value * 1.28f); } @@ -516,6 +525,9 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { // toggle focus on anything that is in focus (to unfocus) if (dpsmode_voltage.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_voltage); if (dpsmode_current.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_current); + + // do nothing in uui + return true; } // toggle select mode, so parent can deal with other UI elements @@ -531,7 +543,6 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { case event_button_m1: case event_button_m2: - // do recall on press_long event_button_m1 or event_button_m2 if (event == event_button_m1 && data == press_long) { saved_v = recall_v[0]; @@ -636,8 +647,8 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { case event_timer: - // timer has counted down - // show the timer and ensure it's focused + // timer has counted down to zero + // Ensure that the timer is focused so it is obvious why power stopped third_item = &dpsmode_timer; third_invalidate = true; @@ -938,9 +949,9 @@ static void dpsmode_tick(void) dpsmode_watthour.value += ((power_actual * 1000.0 / 3600.0f) * secs) / 1000; } - // timer enabled, count down + // timer started with a non-zero value and it has counted to 0. if (saved_t > 0 && dpsmode_timer.value <= 0) { - // timer event will cause a power off + // fire a event_timer event to stop power event_put(event_timer, 0); } } diff --git a/opendps/uui.c b/opendps/uui.c index 7b59c7b8..870de813 100644 --- a/opendps/uui.c +++ b/opendps/uui.c @@ -224,8 +224,8 @@ void uui_handle_screen_event(uui_t *ui, event_t event, uint8_t data) /** If current screen can be enabled */ if (screen->enable) { - if (event == event_shutoff) { - // always turn off with shutoff event + if (event == event_shutoff || event == event_timer) { + // always turn off with shutoff or timer event screen->is_enabled = false; } else { // toggle From c749ce2d4714f957fc88b6caae618023f4aa598c Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 5 Oct 2019 15:11:04 -0600 Subject: [PATCH 104/175] Removed the timer change event_timer call --- opendps/func_dpsmode.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index ac685d0c..e00e7002 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -473,12 +473,7 @@ static void timer_changed(ui_time_t *item) { dpsmode_graphics &= ~CUR_GFX_M1_RECALL; dpsmode_graphics &= ~CUR_GFX_M2_RECALL; - // If timer changed from non-zero to zero, trigger timer event to stop power - if (saved_t > 0 && item->value <= 0) { - event_put(event_timer, 0); - } - - // update timer value + // update saved timer value saved_t = item->value; } From 4b67ed543d8961cb0efb0e5bcdf6d64a1f43723c Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 5 Oct 2019 15:16:04 -0600 Subject: [PATCH 105/175] Ensure that timer event can be handled by uui --- opendps/func_dpsmode.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index e00e7002..a379ddb4 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -473,6 +473,14 @@ static void timer_changed(ui_time_t *item) { dpsmode_graphics &= ~CUR_GFX_M1_RECALL; dpsmode_graphics &= ~CUR_GFX_M2_RECALL; + if (pwrctl_vout_enabled()) { + if (saved_t > 0 && dpsmode_timer.value <= 0) { + // fire a event_timer event to stop power + event_put(event_timer, 0); + } + return; + } + // update saved timer value saved_t = item->value; } @@ -648,9 +656,10 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { third_invalidate = true; uui_focus(ui, (ui_item_t *)third_item); - if (dpsmode_voltage.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_voltage); + if ((ui_item_t *)third_item.ui.has_focus) uui_focus(ui, (ui_item_t*) &third_item); - return true; + // let uui also handle event_timer to turn off power + return false; default: return false; From a21a898c1aeb3ae423c6546ee87420161d0ba42f Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 5 Oct 2019 15:42:42 -0600 Subject: [PATCH 106/175] Fix invalid focus issue --- opendps/func_dpsmode.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index a379ddb4..26194210 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -600,6 +600,7 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { // focus on voltage if not already focused if ( ! dpsmode_voltage.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_voltage); + determine_focused_item(ui, 0); } if (event == event_button_m2) { @@ -609,6 +610,7 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { } if ( ! dpsmode_current.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_current); + determine_focused_item(ui, 0); } // otherwise, enter single edit mode @@ -651,12 +653,16 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { case event_timer: // timer has counted down to zero - // Ensure that the timer is focused so it is obvious why power stopped - third_item = &dpsmode_timer; - third_invalidate = true; + // Ensure that the timer is focused but not selected so it is obvious why power stopped + // leave any edit modes + if ( ! single_edit_mode && ! select_mode) { + uui_focus(ui, (ui_item_t *)third_item); + if (((ui_number_t *)third_item)->ui.has_focus) uui_focus(ui, (ui_item_t *)third_item); + determine_focused_item(ui, 0); - uui_focus(ui, (ui_item_t *)third_item); - if ((ui_item_t *)third_item.ui.has_focus) uui_focus(ui, (ui_item_t*) &third_item); + third_item = &dpsmode_timer; + third_invalidate = true; + } // let uui also handle event_timer to turn off power return false; From 52e046d96387c439f9130f5ce1b696530b138d66 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 5 Oct 2019 15:58:30 -0600 Subject: [PATCH 107/175] Pressing rot should not focus on third item if already in single edit mode or select mode --- opendps/func_dpsmode.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 26194210..84da5e81 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -600,8 +600,6 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { // focus on voltage if not already focused if ( ! dpsmode_voltage.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_voltage); - determine_focused_item(ui, 0); - } if (event == event_button_m2) { if (select_mode) { @@ -610,7 +608,6 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { } if ( ! dpsmode_current.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_current); - determine_focused_item(ui, 0); } // otherwise, enter single edit mode @@ -641,7 +638,7 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { case event_rot_press: // pressing rot should focus on 3rd item if not already in select mode - if (third_item && ! select_mode) { + if (third_item && ! single_edit_mode && ! select_mode) { if (((ui_number_t *)third_item)->ui.can_focus) { uui_focus(ui, (ui_item_t *)third_item); select_mode = true; From 9f4224e34d6ff44e665b8addf5435e479be25926 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 5 Oct 2019 16:18:44 -0600 Subject: [PATCH 108/175] Added event_opp triggerd when over power protection kicks on --- opendps/event.h | 1 + opendps/func_dpsmode.c | 18 +++++++++++------- opendps/uui.c | 1 + 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/opendps/event.h b/opendps/event.h index f2f363d5..679fada7 100644 --- a/opendps/event.h +++ b/opendps/event.h @@ -51,6 +51,7 @@ typedef enum { event_uart_rx, event_ocp, event_ovp, + event_opp, event_shutoff, event_timer diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 84da5e81..ea7a23f3 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -648,15 +648,19 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { break; + case event_opp: + // opp mode + if ( ! single_edit_mode && ! select_mode) { + third_item = &dpsmode_power; + third_invalidate = true; + } + + // let uui also handle event_opp to turn off power + return false; + case event_timer: // timer has counted down to zero - // Ensure that the timer is focused but not selected so it is obvious why power stopped - // leave any edit modes if ( ! single_edit_mode && ! select_mode) { - uui_focus(ui, (ui_item_t *)third_item); - if (((ui_number_t *)third_item)->ui.has_focus) uui_focus(ui, (ui_item_t *)third_item); - determine_focused_item(ui, 0); - third_item = &dpsmode_timer; third_invalidate = true; } @@ -914,7 +918,7 @@ static void dpsmode_tick(void) dpsmode_graphics &= ~CUR_GFX_TM; // power off - event_put(event_shutoff, 0); + event_put(event_opp, 0); } // over 80% power (if defined, or absolute maximum), show warning diff --git a/opendps/uui.c b/opendps/uui.c index 870de813..d084acd6 100644 --- a/opendps/uui.c +++ b/opendps/uui.c @@ -221,6 +221,7 @@ void uui_handle_screen_event(uui_t *ui, event_t event, uint8_t data) case event_button_enable: case event_ocp: case event_ovp: + case event_opp: /** If current screen can be enabled */ if (screen->enable) { From 22e82b94001a5c902bd2493e8f88a23ffb6e8c33 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 5 Oct 2019 16:27:10 -0600 Subject: [PATCH 109/175] Reverted some changes made to Makefile and function generator --- opendps/Makefile | 2 +- opendps/func_gen.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/opendps/Makefile b/opendps/Makefile index 2ec279b2..848d22a2 100644 --- a/opendps/Makefile +++ b/opendps/Makefile @@ -31,7 +31,7 @@ DEBUG ?= 0 METER_FONT_FILE ?= gfx/Ubuntu-C.ttf METER_FONT_SMALL_SIZE ?= 18 METER_FONT_MEDIUM_SIZE ?= 24 -METER_FONT_LARGE_SIZE ?= 42 +METER_FONT_LARGE_SIZE ?= 48 FULL_FONT_FILE ?= gfx/ProggyClean.ttf FULL_FONT_SMALL_SIZE ?= 16 diff --git a/opendps/func_gen.c b/opendps/func_gen.c index 73241106..be030409 100644 --- a/opendps/func_gen.c +++ b/opendps/func_gen.c @@ -464,8 +464,7 @@ static void func_changed(ui_icon_t *item) static void activated(void) { /** The screen is different here, let's clear it */ - // tft_clear(); - + tft_clear(); for (uint32_t i = 0; i < gen_screen.num_items; i++) { gen_screen.items[i]->draw(gen_screen.items[i]); } From 92d7fa04208e56908f999a7f1f499d21510884fe Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 6 Oct 2019 13:37:31 -0600 Subject: [PATCH 110/175] Initial commit --- opendps/Makefile | 8 + opendps/func_settings.c | 480 ++++++++++++++++++++++++++++++++++++++++ opendps/func_settings.h | 37 ++++ 3 files changed, 525 insertions(+) create mode 100644 opendps/func_settings.c create mode 100644 opendps/func_settings.h diff --git a/opendps/Makefile b/opendps/Makefile index 01bff99a..ca7f4ccd 100644 --- a/opendps/Makefile +++ b/opendps/Makefile @@ -55,6 +55,9 @@ CL_ENABLE ?= 1 # Enable function generator mode FUNCGEN_ENABLE ?= 1 +# Enable settings +SETTINGS_ENABLE ?= 1 + # Enable invert color feature INVERT_ENABLE ?= 0 @@ -153,6 +156,11 @@ ifeq ($(FUNCGEN_ENABLE),1) OBJS += func_gen.o uui_icon.o gfx-square.o gfx-saw.o gfx-sin.o endif +ifeq ($(FUNCSETTINGS_ENABLE),1) + CFLAGS +=-DCONFIG_FUNCSETTINGS_ENABLE + OBJS += func_settings.o +endif + ifeq ($(SPLASH_SCREEN),1) CFLAGS +=-DCONFIG_SPLASH_SCREEN endif diff --git a/opendps/func_settings.c b/opendps/func_settings.c new file mode 100644 index 00000000..4720a51d --- /dev/null +++ b/opendps/func_settings.c @@ -0,0 +1,480 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include +#include +#include "hw.h" +#include "func_settings.h" +#include "uui.h" +#include "uui_number.h" +#include "dbg_printf.h" +#include "mini-printf.h" +#include "dps-model.h" +#include "ili9163c.h" + +/* + * This is the implementation of the Settings screen. + */ + +static void settings_enable(bool _enable); +static void settings_tick(void); + +static void past_save(past_t *past); +static void past_restore(past_t *past); + +static void field_changed(ui_number_t *item); +static void set_page(int8_t page); + +static set_param_status_t set_parameter(char *name, char *value); +static set_param_status_t get_parameter(char *name, char *value, uint32_t value_len); + +// want to calibrate V_ADC,DAC A_ADC,DAC VIN_DAC Brightness, refresh timing +// so 12 fields in total... +// possibly want OCP, OVP, OPP? + +static int32_t get_v_adc_k() { + return v_adc_k_coef * 1000; +} +static void set_v_adc_k(ui_number_t *item) { + v_adc_k_coef = item->value / 1000.0f; +} +static int32_t get_v_adc_c() { + return v_adc_c_coef * 1000; +} +static void set_v_adc_c(ui_number_t *item) { + v_adc_c_coef = item->value / 1000.0f; +} + + +static int32_t get_v_dac_k() { + return v_dac_k_coef * 1000; +} +static void set_v_dac_k(ui_number_t *item) { + v_adc_k_coef = item->value / 1000.0f; +} +static int32_t get_v_dac_c() { + return v_dac_c_coef * 1000; +} +static void set_v_dac_c(ui_number_t *item) { + v_adc_c_coef = item->value / 1000.0f; +} + + + +static int32_t get_a_adc_k() { + return a_adc_k_coef * 1000; +} +static void set_a_adc_k(ui_number_t *item) { + a_adc_k_coef = item->value / 1000.0f; +} +static int32_t get_a_adc_c() { + return a_adc_c_coef * 1000; +} +static void set_a_adc_c(ui_number_t *item) { + a_adc_c_coef = item->value / 1000.0f; +} + + +static int32_t get_a_dac_k() { + return a_dac_k_coef * 1000; +} +static void set_a_dac_k(ui_number_t *item) { + a_adc_k_coef = item->value / 1000.0f; +} +static int32_t get_a_dac_c() { + return a_dac_c_coef * 1000; +} +static void set_a_dac_c(ui_number_t *item) { + a_adc_c_coef = item->value / 1000.0f; +} + + +static int32_t get_vin_adc_k() { + return vin_dac_c_coef * 1000; +} +static void set_vin_adc_k(ui_number_t *item) { + vin_adc_k_coef = item->value / 1000.0f; +} +static int32_t get_vin_adc_c() { + return vin_adc_c_coef * 1000; +} +static void set_vin_adc_c(ui_number_t *item) { + vin_adc_c_coef = item->value / 1000.0f; +} + + +static int32_t get_brightness() { + return 100; +} +static void set_brightness(ui_number_t *item) { + // +} + +static int32_t get_refresh() { + return 250; +} +static void set_refresh(ui_number_t *item) { + // +} + + + +typedef void (*set_func)(struct ui_number_t *item); +typedef int32_t (*get_func)(); + +#define ITEMS_PER_PAGE = 5 +#define ITEMS = 12; +#define PAGES = 3; // 12 / 5 = 3 pages worth + +// which page we are currently on. +static int8_t current_page = 0; +static int8_t current_item = 0; // 0 through 4 + +get_func get_functions[] = { + &get_v_adc_k, + &get_v_adc_c, + &get_v_dac_k, + &get_v_dac_c, + &get_a_adc_k, + &get_a_adc_c, + &get_a_dac_k, + &get_a_dac_c, + &get_vin_adc_k, + &get_vin_adc_c, + &get_brightness, + &get_refresh +}; + +set_func set_functions[] = { + &set_v_adc_k, + &set_v_adc_c, + &set_v_dac_k, + &set_v_dac_c, + &set_a_adc_k, + &set_a_adc_c, + &set_a_dac_k, + &set_a_dac_c, + &set_vin_adc_k, + &set_vin_adc_c, + &set_brightness, + &set_refresh +}; + +// fields that can be changed +const char* const field_label[] = { + "Voltage ADC K", + "Voltage ADC C", + "Voltage DAC K", + "Voltage DAC C", + "Current ADC K", + "Current ADC C", + "Current DAC K", + "Current DAC C", + "Vin ADC C", + "Vin ADC K", + "Brightness", + "Refresh Rate", +}; + + +// 5 fields +ui_number_t field[] = { +{ + { + .type = ui_item_number, + .id = 10, + .x = 120, + .y = 15, + .can_focus = true, + }, + .font_size = FONT_FULL_SMALL, + .alignment = ui_text_right_aligned, + .pad_dot = false, + .color = WHITE, + .value = 0, + .min = 0, + .max = 0, + .si_prefix = si_milli, + .num_digits = 3, + .num_decimals = 3, + .unit = unit_none, + .changed = NULL, +}, +{ + { + .type = ui_item_number, + .id = 11, + .x = 120, + .y = 30, + .can_focus = true, + }, + .font_size = FONT_FULL_SMALL, + .alignment = ui_text_right_aligned, + .pad_dot = false, + .color = WHITE, + .value = 0, + .min = 0, + .max = 0, + .si_prefix = si_milli, + .num_digits = 3, + .num_decimals = 3, + .unit = unit_none, + .changed = NULL, +}, +{ + { + .type = ui_item_number, + .id = 12, + .x = 120, + .y = 45, + .can_focus = true, + }, + .font_size = FONT_FULL_SMALL, + .alignment = ui_text_right_aligned, + .pad_dot = false, + .color = WHITE, + .value = 0, + .min = 0, + .max = 0, + .si_prefix = si_milli, + .num_digits = 3, + .num_decimals = 3, + .unit = unit_none, + .changed = NULL, +}, +{ + { + .type = ui_item_number, + .id = 13, + .x = 120, + .y = 60, + .can_focus = true, + }, + .font_size = FONT_FULL_SMALL, + .alignment = ui_text_right_aligned, + .pad_dot = false, + .color = WHITE, + .value = 0, + .min = 0, + .max = 0, + .si_prefix = si_milli, + .num_digits = 3, + .num_decimals = 3, + .unit = unit_none, + .changed = NULL, +}, +{ + { + .type = ui_item_number, + .id = 14, + .x = 120, + .y = 65, + .can_focus = true, + }, + .font_size = FONT_FULL_SMALL, + .alignment = ui_text_right_aligned, + .pad_dot = false, + .color = WHITE, + .value = 0, + .min = 0, + .max = 0, + .si_prefix = si_milli, + .num_digits = 3, + .num_decimals = 3, + .unit = unit_none, + .changed = NULL, +} +} + + +ui_screen_t settings_screen = { + .id = SCREEN_ID, + .name = "settings", + .icon_data = (uint8_t *) gfx_cv, + .icon_data_len = sizeof(gfx_cv), + .icon_width = GFX_CV_WIDTH, + .icon_height = GFX_CV_HEIGHT, + .event = event, + .activated = NULL, + .deactivated = NULL, + .enable = &settings_enable, + .past_save = NULL, + .past_restore = NULL, + .tick = &settings_tick, + .num_items = ITEMS_PER_PAGE, + .items = { + (ui_item_t*) &settings_field[0], + (ui_item_t*) &settings_field[1], + (ui_item_t*) &settings_field[2], + (ui_item_t*) &settings_field[3], + (ui_item_t*) &settings_field[4] + } + .set_parameter = &set_parameter, + .get_parameter = &get_parameter, + .parameters = { + { + .name = {'\0'} /** Terminator */ + }, + }, +}; + + + +/** + * @brief Set function parameter + * + * @param[in] name name of parameter + * @param[in] value value of parameter as a string - always in SI units + * + * @retval set_param_status_t status code + */ +static set_param_status_t set_parameter(char *name, char *value) +{ + return ps_unknown_name; +} + +/** + * @brief Get function parameter + * + * @param[in] name name of parameter + * @param[in] value value of parameter as a string - always in SI units + * @param[in] value_len length of value buffer + * + * @retval set_param_status_t status code + */ +static set_param_status_t get_parameter(char *name, char *value, uint32_t value_len) { + return ps_unknown_name; +} + + +static bool event(uui_t *ui, event_t event, uint8_t data) { + switch (event) { + case event_button_m1: + case event_button_m2: + if ( ! select_mode) { + return false; + } + + // go up + if ( event == event_buttom_m1 && current_item <= 0) { + // wrap around to bottom + current_item = ITEMS_PER_PAGE - 1; + if (current_page >= 1) set_page(current_page - 1); + if (current_page <= 0) set_page(PAGES - 1); + + // go down + } else if (event == event_buttom_m2 && current_item >= ITEMS_PER_PAGE - 1) { + // wrap around to top + current_item = 0; + if (current_page < PAGES - 1) set_page(current_page+1); + if (current_page > 0) set_page(current_page-1); + } + + return false; + + case event_button_sel: + select_mode = ! select_mode; + return false; + + default: + return false; + } + + return false; +} + +// generic field change function called by all fields +// the current item is used to determine the actual field being changed +static void field_changed(ui_number_t *item) { + int8_t page_offset = current_page * ITEMS_PER_PAGE; + + if (page_offset + current_item >= ITEMS) { + // nope + return; + } + + // call the appropriate set function + set_functions[page_offset + current_item](item); +} + +// called whenever the page is changed +static void set_page(int8_t page) { + current_page = page; + + int8_t page_offset = current_page * ITEMS_PER_PAGE; + + // draw each field with its corresponding label + for (uint8_t i = 0; i < ITEMS_PER_PAGE; i++) { + // if greater than total number of items, clear the area + if (page_offset + i >= ITEMS) { + break; + } + + // update field value using value from the get function + settings_field[page_offset + i].value = get_functions[page_offset + i](); + } +} + +static void settings_enable(bool enabled) { +} + +static void settings_tick(void) { + int8_t page_offset = current_page * ITEMS_PER_PAGE; + + // draw each field with its corresponding label + for (uint8_t i = 0; i < 5; i++) { + uint16_t x = settings_field[i].ui.x; + uint16_t y = settings_field[i].ui.y; + + + // if greater than total number of items, clear the area + if (page_offset + i >= ITEMS) { + tft_fill(0, y, + TFT_WIDTH, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, + BLACK); + } else { + tft_puts(FONT_FULL_SMALL, + field_label[page_offset + i], 5 /* x */, y, + FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 15, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, + WHITE, false); + + settings_field[page_offset + i].ui.draw(&settings_field[page_offset + i].ui); + } + } +} + +/** + * @brief Initialise the CV module and add its screen to the UI + * + * @param ui The user interface + */ +void func_settings_init(uui_t *ui) { + for (uint8_t i = 0; i < 5; i++) { + number_init(&settings_field[i]); + } + + uui_add_screen(ui, &settings_screen); +} diff --git a/opendps/func_settings.h b/opendps/func_settings.h new file mode 100644 index 00000000..9abb8eb3 --- /dev/null +++ b/opendps/func_settings.h @@ -0,0 +1,37 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef __FUNC_SETTINGS_H__ +#define __FUNC_SETTINGS_H__ + +#include "uui.h" + +/** + * @brief Add the SETTINGS function to the UI + * + * @param ui The user interface + */ +void func_settings_init(uui_t *ui); + +#endif // __FUNC_SETTINGS_H__ From b25eb9af9527b9f054f11dfaf4e76ac4340c9a32 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 6 Oct 2019 13:41:53 -0600 Subject: [PATCH 111/175] Added func_settings init in opendps.c --- opendps/Makefile | 4 ++-- opendps/opendps.c | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/opendps/Makefile b/opendps/Makefile index ca7f4ccd..34ccc84b 100644 --- a/opendps/Makefile +++ b/opendps/Makefile @@ -156,8 +156,8 @@ ifeq ($(FUNCGEN_ENABLE),1) OBJS += func_gen.o uui_icon.o gfx-square.o gfx-saw.o gfx-sin.o endif -ifeq ($(FUNCSETTINGS_ENABLE),1) - CFLAGS +=-DCONFIG_FUNCSETTINGS_ENABLE +ifeq ($(SETTINGS_ENABLE),1) + CFLAGS +=-DCONFIG_SETTINGS_ENABLE OBJS += func_settings.o endif diff --git a/opendps/opendps.c b/opendps/opendps.c index f7f455a1..24af2e34 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -458,6 +458,9 @@ static void ui_init(void) #ifdef CONFIG_FUNCGEN_ENABLE func_gen_init(&func_ui); #endif // CONFIG_FUNCGEN_ENABLE +#ifdef CONFIG_SETTINGS_ENABLE + func_settings_init(&func_ui); +#endif // CONFIG_SETTINGS_ENABLE /** Initialise the settings screens */ From f2463f4279cab4e616d966689bc87e7a7097632e Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 6 Oct 2019 13:50:35 -0600 Subject: [PATCH 112/175] Fixed syntax issues --- opendps/func_settings.c | 15 +++++++++------ opendps/opendps.c | 3 +++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index 4720a51d..094b462d 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -34,6 +34,7 @@ #include "mini-printf.h" #include "dps-model.h" #include "ili9163c.h" +#include "font-full_small.h" /* * This is the implementation of the Settings screen. @@ -51,6 +52,8 @@ static void set_page(int8_t page); static set_param_status_t set_parameter(char *name, char *value); static set_param_status_t get_parameter(char *name, char *value, uint32_t value_len); +static bool select_mode; + // want to calibrate V_ADC,DAC A_ADC,DAC VIN_DAC Brightness, refresh timing // so 12 fields in total... // possibly want OCP, OVP, OPP? @@ -113,7 +116,7 @@ static void set_a_dac_c(ui_number_t *item) { static int32_t get_vin_adc_k() { - return vin_dac_c_coef * 1000; + return vin_adc_k_coef * 1000; } static void set_vin_adc_k(ui_number_t *item) { vin_adc_k_coef = item->value / 1000.0f; @@ -145,9 +148,9 @@ static void set_refresh(ui_number_t *item) { typedef void (*set_func)(struct ui_number_t *item); typedef int32_t (*get_func)(); -#define ITEMS_PER_PAGE = 5 -#define ITEMS = 12; -#define PAGES = 3; // 12 / 5 = 3 pages worth +#define ITEMS_PER_PAGE 5 +#define ITEMS 12; +#define PAGES 3; // 12 / 5 = 3 pages worth // which page we are currently on. static int8_t current_page = 0; @@ -201,7 +204,7 @@ const char* const field_label[] = { // 5 fields -ui_number_t field[] = { +ui_number_t settings_field[] = { { { .type = ui_item_number, @@ -307,7 +310,7 @@ ui_number_t field[] = { .unit = unit_none, .changed = NULL, } -} +}; ui_screen_t settings_screen = { diff --git a/opendps/opendps.c b/opendps/opendps.c index 24af2e34..310984e9 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -75,6 +75,9 @@ #ifdef CONFIG_FUNCGEN_ENABLE #include "func_gen.h" #endif // CONFIG_FUNCGEN_ENABLE +#ifdef CONFIG_SETTINGS_ENABLE +#include "func_settings.h" +#endif // CONFIG_SETTINGS_ENABLE #ifdef DPS_EMULATOR #include "dpsemul.h" From e0a8155db31f45fbaee042fd885ec2b7d5919c08 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 6 Oct 2019 13:53:57 -0600 Subject: [PATCH 113/175] More syntax issues --- opendps/func_settings.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index 094b462d..701aa2b1 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -35,6 +35,12 @@ #include "dps-model.h" #include "ili9163c.h" #include "font-full_small.h" +#include "opendps.h" +#include "gfx-crosshair.h" + + +#define SCREEN_ID (7) + /* * This is the implementation of the Settings screen. @@ -46,6 +52,7 @@ static void settings_tick(void); static void past_save(past_t *past); static void past_restore(past_t *past); +static bool event(uui_t *ui, event_t event, uint8_t data); static void field_changed(ui_number_t *item); static void set_page(int8_t page); @@ -149,8 +156,8 @@ typedef void (*set_func)(struct ui_number_t *item); typedef int32_t (*get_func)(); #define ITEMS_PER_PAGE 5 -#define ITEMS 12; -#define PAGES 3; // 12 / 5 = 3 pages worth +#define ITEMS 12 +#define PAGES 3 // 12 / 5 = 3 pages worth // which page we are currently on. static int8_t current_page = 0; @@ -316,10 +323,10 @@ ui_number_t settings_field[] = { ui_screen_t settings_screen = { .id = SCREEN_ID, .name = "settings", - .icon_data = (uint8_t *) gfx_cv, - .icon_data_len = sizeof(gfx_cv), - .icon_width = GFX_CV_WIDTH, - .icon_height = GFX_CV_HEIGHT, + .icon_data = (uint8_t *) gfx_crosshair, + .icon_data_len = sizeof(gfx_crosshair), + .icon_width = GFX_CROSSHAIR_WIDTH, + .icon_height = GFX_CROSSHAIR_HEIGHT, .event = event, .activated = NULL, .deactivated = NULL, @@ -334,7 +341,7 @@ ui_screen_t settings_screen = { (ui_item_t*) &settings_field[2], (ui_item_t*) &settings_field[3], (ui_item_t*) &settings_field[4] - } + }, .set_parameter = &set_parameter, .get_parameter = &get_parameter, .parameters = { @@ -382,14 +389,14 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { } // go up - if ( event == event_buttom_m1 && current_item <= 0) { + if ( event == event_button_m1 && current_item <= 0) { // wrap around to bottom current_item = ITEMS_PER_PAGE - 1; if (current_page >= 1) set_page(current_page - 1); if (current_page <= 0) set_page(PAGES - 1); // go down - } else if (event == event_buttom_m2 && current_item >= ITEMS_PER_PAGE - 1) { + } else if (event == event_button_m2 && current_item >= ITEMS_PER_PAGE - 1) { // wrap around to top current_item = 0; if (current_page < PAGES - 1) set_page(current_page+1); From 684d0aa231851ee22d3d573f7aafb17d80dd854f Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 6 Oct 2019 14:08:07 -0600 Subject: [PATCH 114/175] Putting everything inline --- opendps/func_settings.c | 75 ++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 28 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index 701aa2b1..702409a3 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -158,6 +158,7 @@ typedef int32_t (*get_func)(); #define ITEMS_PER_PAGE 5 #define ITEMS 12 #define PAGES 3 // 12 / 5 = 3 pages worth +#define ROW_HEIGHT 30 // which page we are currently on. static int8_t current_page = 0; @@ -216,12 +217,12 @@ ui_number_t settings_field[] = { { .type = ui_item_number, .id = 10, - .x = 120, - .y = 15, + .x = 5, + .y = FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, .can_focus = true, }, .font_size = FONT_FULL_SMALL, - .alignment = ui_text_right_aligned, + .alignment = ui_text_left_aligned, .pad_dot = false, .color = WHITE, .value = 0, @@ -237,12 +238,12 @@ ui_number_t settings_field[] = { { .type = ui_item_number, .id = 11, - .x = 120, - .y = 30, + .x = 5, + .y = FONT_FULL_SMALL_MAX_GLYPH_HEIGHT + (1 * ROW_HEIGHT), .can_focus = true, }, .font_size = FONT_FULL_SMALL, - .alignment = ui_text_right_aligned, + .alignment = ui_text_left_aligned, .pad_dot = false, .color = WHITE, .value = 0, @@ -258,12 +259,12 @@ ui_number_t settings_field[] = { { .type = ui_item_number, .id = 12, - .x = 120, - .y = 45, + .x = 5, + .y = FONT_FULL_SMALL_MAX_GLYPH_HEIGHT + (2*ROW_HEIGHT), .can_focus = true, }, .font_size = FONT_FULL_SMALL, - .alignment = ui_text_right_aligned, + .alignment = ui_text_left_aligned, .pad_dot = false, .color = WHITE, .value = 0, @@ -279,12 +280,12 @@ ui_number_t settings_field[] = { { .type = ui_item_number, .id = 13, - .x = 120, - .y = 60, + .x = 5, + .y = FONT_FULL_SMALL_MAX_GLYPH_HEIGHT + (3*ROW_HEIGHT), .can_focus = true, }, .font_size = FONT_FULL_SMALL, - .alignment = ui_text_right_aligned, + .alignment = ui_text_left_aligned, .pad_dot = false, .color = WHITE, .value = 0, @@ -300,12 +301,12 @@ ui_number_t settings_field[] = { { .type = ui_item_number, .id = 14, - .x = 120, - .y = 65, + .x = 5, + .y = FONT_FULL_SMALL_MAX_GLYPH_HEIGHT + (4*ROW_HEIGHT), .can_focus = true, }, .font_size = FONT_FULL_SMALL, - .alignment = ui_text_right_aligned, + .alignment = ui_text_left_aligned, .pad_dot = false, .color = WHITE, .value = 0, @@ -389,18 +390,36 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { } // go up - if ( event == event_button_m1 && current_item <= 0) { - // wrap around to bottom - current_item = ITEMS_PER_PAGE - 1; - if (current_page >= 1) set_page(current_page - 1); - if (current_page <= 0) set_page(PAGES - 1); + if ( event == event_button_m1 ) { + // first item selected, going up will wrap around to previous page + if (current_item <= 0) { + // wrap around to bottom of previous page + current_item = ITEMS_PER_PAGE - 1; + + // previous page being the last page (if we're on page 0) + if (current_page <= 0) set_page(PAGES - 1); + else set_page(current_page - 1); + + // otherwise, go up one item + } else { + current_item--; + } // go down - } else if (event == event_button_m2 && current_item >= ITEMS_PER_PAGE - 1) { - // wrap around to top - current_item = 0; - if (current_page < PAGES - 1) set_page(current_page+1); - if (current_page > 0) set_page(current_page-1); + } else if (event == event_button_m2) { + // last item selected, going down will go to the next page and first item + if (current_item >= ITEMS_PER_PAGE - 1) { + // wrap to first item + current_item = 0; + + // of the next page + if (current_page >= PAGES - 1) set_page(0); + else set_page(current_page + 1); + + // otherwise go to the next item + } else { + current_item++; + } } return false; @@ -462,12 +481,12 @@ static void settings_tick(void) { // if greater than total number of items, clear the area if (page_offset + i >= ITEMS) { - tft_fill(0, y, - TFT_WIDTH, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, + tft_fill(0 /* x */, i * ROW_HEIGHT /* y */, + TFT_WIDTH, ROW_HEIGHT, BLACK); } else { tft_puts(FONT_FULL_SMALL, - field_label[page_offset + i], 5 /* x */, y, + field_label[page_offset + i], 0 /* x */, i * ROW_HEIGHT /* y */ , FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 15, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, WHITE, false); From ccbd3f6b969e2995f4c2329909077af3f4921a15 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 6 Oct 2019 14:16:03 -0600 Subject: [PATCH 115/175] Adjusting layout --- opendps/func_settings.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index 702409a3..b1273266 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -66,30 +66,30 @@ static bool select_mode; // possibly want OCP, OVP, OPP? static int32_t get_v_adc_k() { - return v_adc_k_coef * 1000; + return v_adc_k_coef * 1000000; } static void set_v_adc_k(ui_number_t *item) { - v_adc_k_coef = item->value / 1000.0f; + v_adc_k_coef = item->value / 1000000.0f; } static int32_t get_v_adc_c() { - return v_adc_c_coef * 1000; + return v_adc_c_coef * 1000000; } static void set_v_adc_c(ui_number_t *item) { - v_adc_c_coef = item->value / 1000.0f; + v_adc_c_coef = item->value / 1000000.0f; } static int32_t get_v_dac_k() { - return v_dac_k_coef * 1000; + return v_dac_k_coef * 1000000; } static void set_v_dac_k(ui_number_t *item) { - v_adc_k_coef = item->value / 1000.0f; + v_adc_k_coef = item->value / 1000000.0f; } static int32_t get_v_dac_c() { - return v_dac_c_coef * 1000; + return v_dac_c_coef * 1000000; } static void set_v_dac_c(ui_number_t *item) { - v_adc_c_coef = item->value / 1000.0f; + v_adc_c_coef = item->value / 1000000.0f; } @@ -159,6 +159,7 @@ typedef int32_t (*get_func)(); #define ITEMS 12 #define PAGES 3 // 12 / 5 = 3 pages worth #define ROW_HEIGHT 30 +#define FIELD_Y_OFFSET 20 // which page we are currently on. static int8_t current_page = 0; @@ -218,7 +219,7 @@ ui_number_t settings_field[] = { .type = ui_item_number, .id = 10, .x = 5, - .y = FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, + .y = FIELD_Y_OFFSET, .can_focus = true, }, .font_size = FONT_FULL_SMALL, @@ -239,7 +240,7 @@ ui_number_t settings_field[] = { .type = ui_item_number, .id = 11, .x = 5, - .y = FONT_FULL_SMALL_MAX_GLYPH_HEIGHT + (1 * ROW_HEIGHT), + .y = FIELD_Y_OFFSET + (1 * ROW_HEIGHT), .can_focus = true, }, .font_size = FONT_FULL_SMALL, @@ -260,7 +261,7 @@ ui_number_t settings_field[] = { .type = ui_item_number, .id = 12, .x = 5, - .y = FONT_FULL_SMALL_MAX_GLYPH_HEIGHT + (2*ROW_HEIGHT), + .y = FIELD_Y_OFFSET + (2*ROW_HEIGHT), .can_focus = true, }, .font_size = FONT_FULL_SMALL, @@ -281,7 +282,7 @@ ui_number_t settings_field[] = { .type = ui_item_number, .id = 13, .x = 5, - .y = FONT_FULL_SMALL_MAX_GLYPH_HEIGHT + (3*ROW_HEIGHT), + .y = FIELD_Y_OFFSET + (3*ROW_HEIGHT), .can_focus = true, }, .font_size = FONT_FULL_SMALL, @@ -302,7 +303,7 @@ ui_number_t settings_field[] = { .type = ui_item_number, .id = 14, .x = 5, - .y = FONT_FULL_SMALL_MAX_GLYPH_HEIGHT + (4*ROW_HEIGHT), + .y = FIELD_Y_OFFSET + (4*ROW_HEIGHT), .can_focus = true, }, .font_size = FONT_FULL_SMALL, @@ -486,8 +487,9 @@ static void settings_tick(void) { BLACK); } else { tft_puts(FONT_FULL_SMALL, - field_label[page_offset + i], 0 /* x */, i * ROW_HEIGHT /* y */ , - FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 15, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, + field_label[page_offset + i], + 0 /* x */, (i * ROW_HEIGHT) + FONT_FULL_SMALL_MAX_GLYPH_HEIGHT /* y */ , + TFT_WIDTH, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, WHITE, false); settings_field[page_offset + i].ui.draw(&settings_field[page_offset + i].ui); From 8e603bc0082e89ae8b32627b406bbc7fa6f08302 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 6 Oct 2019 14:32:31 -0600 Subject: [PATCH 116/175] Rendering everything in 2 columns --- opendps/func_settings.c | 99 +++++++++++++++++++++++------------------ 1 file changed, 56 insertions(+), 43 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index b1273266..fb8ee242 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -158,8 +158,9 @@ typedef int32_t (*get_func)(); #define ITEMS_PER_PAGE 5 #define ITEMS 12 #define PAGES 3 // 12 / 5 = 3 pages worth -#define ROW_HEIGHT 30 -#define FIELD_Y_OFFSET 20 +#define ROW_HEIGHT 20 +#define FIELD_Y_OFFSET 0 // 15 +#define FIELD_X_OFFSET 64 // half of screen // which page we are currently on. static int8_t current_page = 0; @@ -197,18 +198,18 @@ set_func set_functions[] = { // fields that can be changed const char* const field_label[] = { - "Voltage ADC K", - "Voltage ADC C", - "Voltage DAC K", - "Voltage DAC C", - "Current ADC K", - "Current ADC C", - "Current DAC K", - "Current DAC C", + "V ADC K", + "V ADC C", + "V DAC K", + "V DAC C", + "I ADC K", + "I ADC C", + "I DAC K", + "I DAC C", "Vin ADC C", "Vin ADC K", - "Brightness", - "Refresh Rate", + "Scr-LED", + "Refresh", }; @@ -218,7 +219,7 @@ ui_number_t settings_field[] = { { .type = ui_item_number, .id = 10, - .x = 5, + .x = FIELD_X_OFFSET, .y = FIELD_Y_OFFSET, .can_focus = true, }, @@ -239,7 +240,7 @@ ui_number_t settings_field[] = { { .type = ui_item_number, .id = 11, - .x = 5, + .x = FIELD_X_OFFSET, .y = FIELD_Y_OFFSET + (1 * ROW_HEIGHT), .can_focus = true, }, @@ -260,7 +261,7 @@ ui_number_t settings_field[] = { { .type = ui_item_number, .id = 12, - .x = 5, + .x = FIELD_X_OFFSET, .y = FIELD_Y_OFFSET + (2*ROW_HEIGHT), .can_focus = true, }, @@ -281,7 +282,7 @@ ui_number_t settings_field[] = { { .type = ui_item_number, .id = 13, - .x = 5, + .x = FIELD_X_OFFSET, .y = FIELD_Y_OFFSET + (3*ROW_HEIGHT), .can_focus = true, }, @@ -302,7 +303,7 @@ ui_number_t settings_field[] = { { .type = ui_item_number, .id = 14, - .x = 5, + .x = FIELD_X_OFFSET, .y = FIELD_Y_OFFSET + (4*ROW_HEIGHT), .can_focus = true, }, @@ -392,38 +393,47 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { // go up if ( event == event_button_m1 ) { - // first item selected, going up will wrap around to previous page - if (current_item <= 0) { - // wrap around to bottom of previous page - current_item = ITEMS_PER_PAGE - 1; - - // previous page being the last page (if we're on page 0) - if (current_page <= 0) set_page(PAGES - 1); - else set_page(current_page - 1); - - // otherwise, go up one item - } else { + // not first item, move up one + if (current_item > 0) { current_item--; + return false; + } + + // we are left with current_item == 0. + + if (current_page == 0) { + // do nothing for first page/first item + return true; } + // current_item == 0, and current_page != 0 + set_page(current_page - 1); + return false; + // go down - } else if (event == event_button_m2) { - // last item selected, going down will go to the next page and first item - if (current_item >= ITEMS_PER_PAGE - 1) { - // wrap to first item - current_item = 0; - - // of the next page - if (current_page >= PAGES - 1) set_page(0); - else set_page(current_page + 1); - - // otherwise go to the next item - } else { + } else { + // not last item, go down + if (current_item < ITEMS_PER_PAGE - 1) { + // do nothing if we are on the last item already + if ((current_page * ITEMS_PER_PAGE) + current_item >= ITEMS - 1) + return true; + + // otherwise, go down one item current_item++; + return false; } - } - return false; + // we are left with current_item == last item + + if (current_page == PAGES - 1) { + // last page. do nothing + return true; + } + + // last item, but not last page + set_page(current_page + 1); + return false; + } case event_button_sel: select_mode = ! select_mode; @@ -489,7 +499,7 @@ static void settings_tick(void) { tft_puts(FONT_FULL_SMALL, field_label[page_offset + i], 0 /* x */, (i * ROW_HEIGHT) + FONT_FULL_SMALL_MAX_GLYPH_HEIGHT /* y */ , - TFT_WIDTH, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, + TFT_WIDTH/2, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, WHITE, false); settings_field[page_offset + i].ui.draw(&settings_field[page_offset + i].ui); @@ -507,5 +517,8 @@ void func_settings_init(uui_t *ui) { number_init(&settings_field[i]); } + // init to page 0 + set_page(0); + uui_add_screen(ui, &settings_screen); } From a7b8aea6204e6e60d8a8bc20e13b3f7fbd675533 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 6 Oct 2019 14:39:29 -0600 Subject: [PATCH 117/175] Ensure that current_item is bound --- opendps/func_settings.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index fb8ee242..3ea33822 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -66,30 +66,30 @@ static bool select_mode; // possibly want OCP, OVP, OPP? static int32_t get_v_adc_k() { - return v_adc_k_coef * 1000000; + return v_adc_k_coef * 1000; } static void set_v_adc_k(ui_number_t *item) { - v_adc_k_coef = item->value / 1000000.0f; + v_adc_k_coef = item->value / 1000.0f; } static int32_t get_v_adc_c() { - return v_adc_c_coef * 1000000; + return v_adc_c_coef * 1000; } static void set_v_adc_c(ui_number_t *item) { - v_adc_c_coef = item->value / 1000000.0f; + v_adc_c_coef = item->value / 1000.0f; } static int32_t get_v_dac_k() { - return v_dac_k_coef * 1000000; + return v_dac_k_coef * 1000; } static void set_v_dac_k(ui_number_t *item) { - v_adc_k_coef = item->value / 1000000.0f; + v_adc_k_coef = item->value / 1000.0f; } static int32_t get_v_dac_c() { - return v_dac_c_coef * 1000000; + return v_dac_c_coef * 1000; } static void set_v_dac_c(ui_number_t *item) { - v_adc_c_coef = item->value / 1000000.0f; + v_adc_c_coef = item->value / 1000.0f; } @@ -408,6 +408,7 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { // current_item == 0, and current_page != 0 set_page(current_page - 1); + current_item = ITEMS_PER_PAGE - 1; return false; // go down @@ -432,6 +433,7 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { // last item, but not last page set_page(current_page + 1); + current_item = 0; return false; } @@ -476,6 +478,9 @@ static void set_page(int8_t page) { // update field value using value from the get function settings_field[page_offset + i].value = get_functions[page_offset + i](); } + + // debug: + tft_clear(); } static void settings_enable(bool enabled) { @@ -519,6 +524,7 @@ void func_settings_init(uui_t *ui) { // init to page 0 set_page(0); + current_item = 0; uui_add_screen(ui, &settings_screen); } From ad150e8f8afcc22a6256cf11819fcfabce9dcd79 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 6 Oct 2019 14:52:39 -0600 Subject: [PATCH 118/175] Hacking signed numbers to work --- opendps/func_settings.c | 47 ++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index 3ea33822..bd653592 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -69,13 +69,13 @@ static int32_t get_v_adc_k() { return v_adc_k_coef * 1000; } static void set_v_adc_k(ui_number_t *item) { - v_adc_k_coef = item->value / 1000.0f; + v_adc_k_coef = item->value / (item->color == RED) ? -1000.0f : 1000.0f; } static int32_t get_v_adc_c() { return v_adc_c_coef * 1000; } static void set_v_adc_c(ui_number_t *item) { - v_adc_c_coef = item->value / 1000.0f; + v_adc_c_coef = item->value / (item->color == RED) ? -1000.0f : 1000.0f; } @@ -83,13 +83,13 @@ static int32_t get_v_dac_k() { return v_dac_k_coef * 1000; } static void set_v_dac_k(ui_number_t *item) { - v_adc_k_coef = item->value / 1000.0f; + v_adc_k_coef = item->value / (item->color == RED) ? -1000.0f : 1000.0f; } static int32_t get_v_dac_c() { return v_dac_c_coef * 1000; } static void set_v_dac_c(ui_number_t *item) { - v_adc_c_coef = item->value / 1000.0f; + v_adc_c_coef = item->value / (item->color == RED) ? -1000.0f : 1000.0f; } @@ -98,13 +98,13 @@ static int32_t get_a_adc_k() { return a_adc_k_coef * 1000; } static void set_a_adc_k(ui_number_t *item) { - a_adc_k_coef = item->value / 1000.0f; + a_adc_k_coef = item->value / (item->color == RED) ? -1000.0f : 1000.0f; } static int32_t get_a_adc_c() { return a_adc_c_coef * 1000; } static void set_a_adc_c(ui_number_t *item) { - a_adc_c_coef = item->value / 1000.0f; + a_adc_c_coef = item->value / (item->color == RED) ? -1000.0f : 1000.0f; } @@ -112,13 +112,13 @@ static int32_t get_a_dac_k() { return a_dac_k_coef * 1000; } static void set_a_dac_k(ui_number_t *item) { - a_adc_k_coef = item->value / 1000.0f; + a_adc_k_coef = item->value / (item->color == RED) ? -1000.0f : 1000.0f; } static int32_t get_a_dac_c() { return a_dac_c_coef * 1000; } static void set_a_dac_c(ui_number_t *item) { - a_adc_c_coef = item->value / 1000.0f; + a_adc_c_coef = item->value / (item->color == RED) ? -1000.0f : 1000.0f; } @@ -126,13 +126,13 @@ static int32_t get_vin_adc_k() { return vin_adc_k_coef * 1000; } static void set_vin_adc_k(ui_number_t *item) { - vin_adc_k_coef = item->value / 1000.0f; + vin_adc_k_coef = item->value / (item->color == RED) ? -1000.0f : 1000.0f; } static int32_t get_vin_adc_c() { return vin_adc_c_coef * 1000; } static void set_vin_adc_c(ui_number_t *item) { - vin_adc_c_coef = item->value / 1000.0f; + vin_adc_c_coef = item->value / (item->color == RED) ? -1000.0f : 1000.0f; } @@ -224,7 +224,7 @@ ui_number_t settings_field[] = { .can_focus = true, }, .font_size = FONT_FULL_SMALL, - .alignment = ui_text_left_aligned, + .alignment = ui_text_right_aligned, .pad_dot = false, .color = WHITE, .value = 0, @@ -245,7 +245,7 @@ ui_number_t settings_field[] = { .can_focus = true, }, .font_size = FONT_FULL_SMALL, - .alignment = ui_text_left_aligned, + .alignment = ui_text_right_aligned, .pad_dot = false, .color = WHITE, .value = 0, @@ -266,7 +266,7 @@ ui_number_t settings_field[] = { .can_focus = true, }, .font_size = FONT_FULL_SMALL, - .alignment = ui_text_left_aligned, + .alignment = ui_text_right_aligned, .pad_dot = false, .color = WHITE, .value = 0, @@ -287,7 +287,7 @@ ui_number_t settings_field[] = { .can_focus = true, }, .font_size = FONT_FULL_SMALL, - .alignment = ui_text_left_aligned, + .alignment = ui_text_right_aligned, .pad_dot = false, .color = WHITE, .value = 0, @@ -308,7 +308,7 @@ ui_number_t settings_field[] = { .can_focus = true, }, .font_size = FONT_FULL_SMALL, - .alignment = ui_text_left_aligned, + .alignment = ui_text_right_aligned, .pad_dot = false, .color = WHITE, .value = 0, @@ -476,7 +476,16 @@ static void set_page(int8_t page) { } // update field value using value from the get function - settings_field[page_offset + i].value = get_functions[page_offset + i](); + int32_t value = get_functions[page_offset + i](); + if (value < 0) { + // because uui_number doesn't support signed values (i think??) + // color represents the sign + settings_field[i].value = -value; + settings_field[i].color = RED; + } else { + settings_field[i].value = value; + settings_field[i].color = WHITE; + } } // debug: @@ -490,7 +499,7 @@ static void settings_tick(void) { int8_t page_offset = current_page * ITEMS_PER_PAGE; // draw each field with its corresponding label - for (uint8_t i = 0; i < 5; i++) { + for (uint8_t i = 0; i < ITEMS_PER_PAGE; i++) { uint16_t x = settings_field[i].ui.x; uint16_t y = settings_field[i].ui.y; @@ -507,7 +516,7 @@ static void settings_tick(void) { TFT_WIDTH/2, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, WHITE, false); - settings_field[page_offset + i].ui.draw(&settings_field[page_offset + i].ui); + settings_field[i].ui.draw(&settings_field[i].ui); } } } @@ -518,7 +527,7 @@ static void settings_tick(void) { * @param ui The user interface */ void func_settings_init(uui_t *ui) { - for (uint8_t i = 0; i < 5; i++) { + for (uint8_t i = 0; i < ITEMS_PER_PAGE; i++) { number_init(&settings_field[i]); } From 46b2fab0a9d43ec7d2098508832b66a92ebdf27d Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 6 Oct 2019 15:08:22 -0600 Subject: [PATCH 119/175] Added persistence --- opendps/func_settings.c | 31 +++++++++++++++++++++++++++++-- opendps/pwrctl.c | 21 +++++++++++++++++++++ opendps/pwrctl.h | 7 +++++++ 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index bd653592..40cd2835 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -37,6 +37,7 @@ #include "font-full_small.h" #include "opendps.h" #include "gfx-crosshair.h" +#include "pastunits.h" #define SCREEN_ID (7) @@ -48,6 +49,7 @@ static void settings_enable(bool _enable); static void settings_tick(void); +static void settings_reset(void); static void past_save(past_t *past); static void past_restore(past_t *past); @@ -160,7 +162,7 @@ typedef int32_t (*get_func)(); #define PAGES 3 // 12 / 5 = 3 pages worth #define ROW_HEIGHT 20 #define FIELD_Y_OFFSET 0 // 15 -#define FIELD_X_OFFSET 64 // half of screen +#define FIELD_X_OFFSET 128 // 64 // half of screen // which page we are currently on. static int8_t current_page = 0; @@ -334,7 +336,7 @@ ui_screen_t settings_screen = { .activated = NULL, .deactivated = NULL, .enable = &settings_enable, - .past_save = NULL, + .past_save = &past_save, .past_restore = NULL, .tick = &settings_tick, .num_items = ITEMS_PER_PAGE, @@ -438,6 +440,12 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { } case event_button_sel: + // long SET press will reest all values + if (data == press_long) { + settings_reset(); + return true; + } + select_mode = ! select_mode; return false; @@ -521,6 +529,25 @@ static void settings_tick(void) { } } + +static void settings_reset() { + a_adc_k_coef = A_ADC_K; + a_adc_c_coef = A_ADC_C; + a_dac_k_coef = A_DAC_K; + a_dac_c_coef = A_DAC_C; + v_adc_k_coef = V_ADC_K; + v_adc_c_coef = V_ADC_C; + v_dac_k_coef = V_DAC_K; + v_dac_c_coef = V_DAC_C; + vin_adc_k_coef = VIN_ADC_K; + vin_adc_c_coef = VIN_ADC_C; +} + +static void past_save(past_t *past) { + pwrctl_past_save(past); +} + + /** * @brief Initialise the CV module and add its screen to the UI * diff --git a/opendps/pwrctl.c b/opendps/pwrctl.c index cf51ca1a..d1515803 100644 --- a/opendps/pwrctl.c +++ b/opendps/pwrctl.c @@ -97,6 +97,27 @@ void pwrctl_init(past_t *past) pwrctl_enable_vout(false); } + +void pwrctl_past_save(past_t *past) { + + float *v = a_adc_k_coef; + + if ( past_write_unit(past, past_A_ADC_K, (void*) &a_adc_k_coef, 4) + && past_write_unit(past, past_A_ADC_C, (void*) &a_adc_c_coef, 4) + && past_write_unit(past, past_A_DAC_K, (void*) &a_dac_k_coef, 4) + && past_write_unit(past, past_A_DAC_C, (void*) &a_dac_c_coef, 4) + && past_write_unit(past, past_V_ADC_K, (void*) &v_adc_k_coef, 4) + && past_write_unit(past, past_V_ADC_C, (void*) &v_adc_c_coef, 4) + && past_write_unit(past, past_V_DAC_K, (void*) &v_dac_k_coef, 4) + && past_write_unit(past, past_V_DAC_C, (void*) &v_dac_c_coef, 4) + && past_write_unit(past, past_VIN_ADC_K, (void*) &vin_adc_k_coef, 4) + && past_write_unit(past, past_VIN_ADC_C, (void*) &vin_adc_c_coef, 4) + ) { + // write ok + } +} + + /** * @brief Set voltage output * @param value_mv voltage in milli volt diff --git a/opendps/pwrctl.h b/opendps/pwrctl.h index 31fde92f..19b8980d 100644 --- a/opendps/pwrctl.h +++ b/opendps/pwrctl.h @@ -48,6 +48,13 @@ extern float vin_adc_c_coef; */ void pwrctl_init(past_t *past); + +/** + * @brief Saves past data + * @retval none + */ +void pwrctl_past_save(past_t *past); + /** * @brief Set voltage output * @param value_mv voltage in millivolt From e5d3e49a6680928cd5e4b29bb00cb9b52be7e289 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 6 Oct 2019 15:20:04 -0600 Subject: [PATCH 120/175] Added another row. Values should have a min/max set so it can be adjusted --- opendps/func_settings.c | 55 ++++++++++++++++++++++++++++------------- opendps/pwrctl.c | 3 --- 2 files changed, 38 insertions(+), 20 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index 40cd2835..54e9bc46 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -139,14 +139,14 @@ static void set_vin_adc_c(ui_number_t *item) { static int32_t get_brightness() { - return 100; + return 100 * 1000; } static void set_brightness(ui_number_t *item) { // } static int32_t get_refresh() { - return 250; + return 250 * 1000; } static void set_refresh(ui_number_t *item) { // @@ -157,10 +157,10 @@ static void set_refresh(ui_number_t *item) { typedef void (*set_func)(struct ui_number_t *item); typedef int32_t (*get_func)(); -#define ITEMS_PER_PAGE 5 +#define ITEMS_PER_PAGE 6 #define ITEMS 12 -#define PAGES 3 // 12 / 5 = 3 pages worth -#define ROW_HEIGHT 20 +#define PAGES 2 // 12 / 6 = 2 pages worth +#define ROW_HEIGHT 17 #define FIELD_Y_OFFSET 0 // 15 #define FIELD_X_OFFSET 128 // 64 // half of screen @@ -215,7 +215,6 @@ const char* const field_label[] = { }; -// 5 fields ui_number_t settings_field[] = { { { @@ -230,8 +229,8 @@ ui_number_t settings_field[] = { .pad_dot = false, .color = WHITE, .value = 0, - .min = 0, - .max = 0, + .min = -1000000, + .max = 1000000, .si_prefix = si_milli, .num_digits = 3, .num_decimals = 3, @@ -251,8 +250,8 @@ ui_number_t settings_field[] = { .pad_dot = false, .color = WHITE, .value = 0, - .min = 0, - .max = 0, + .min = -1000000, + .max = 1000000, .si_prefix = si_milli, .num_digits = 3, .num_decimals = 3, @@ -272,8 +271,8 @@ ui_number_t settings_field[] = { .pad_dot = false, .color = WHITE, .value = 0, - .min = 0, - .max = 0, + .min = -1000000, + .max = 1000000, .si_prefix = si_milli, .num_digits = 3, .num_decimals = 3, @@ -293,8 +292,8 @@ ui_number_t settings_field[] = { .pad_dot = false, .color = WHITE, .value = 0, - .min = 0, - .max = 0, + .min = -1000000, + .max = 1000000, .si_prefix = si_milli, .num_digits = 3, .num_decimals = 3, @@ -314,8 +313,29 @@ ui_number_t settings_field[] = { .pad_dot = false, .color = WHITE, .value = 0, - .min = 0, - .max = 0, + .min = -1000000, + .max = 1000000, + .si_prefix = si_milli, + .num_digits = 3, + .num_decimals = 3, + .unit = unit_none, + .changed = NULL, +}, +{ + { + .type = ui_item_number, + .id = 15, + .x = FIELD_X_OFFSET, + .y = FIELD_Y_OFFSET + (5*ROW_HEIGHT), + .can_focus = true, + }, + .font_size = FONT_FULL_SMALL, + .alignment = ui_text_right_aligned, + .pad_dot = false, + .color = WHITE, + .value = 0, + .min = -1000000, + .max = 1000000, .si_prefix = si_milli, .num_digits = 3, .num_decimals = 3, @@ -345,7 +365,8 @@ ui_screen_t settings_screen = { (ui_item_t*) &settings_field[1], (ui_item_t*) &settings_field[2], (ui_item_t*) &settings_field[3], - (ui_item_t*) &settings_field[4] + (ui_item_t*) &settings_field[4], + (ui_item_t*) &settings_field[5] }, .set_parameter = &set_parameter, .get_parameter = &get_parameter, diff --git a/opendps/pwrctl.c b/opendps/pwrctl.c index d1515803..0b2bc0a0 100644 --- a/opendps/pwrctl.c +++ b/opendps/pwrctl.c @@ -99,9 +99,6 @@ void pwrctl_init(past_t *past) void pwrctl_past_save(past_t *past) { - - float *v = a_adc_k_coef; - if ( past_write_unit(past, past_A_ADC_K, (void*) &a_adc_k_coef, 4) && past_write_unit(past, past_A_ADC_C, (void*) &a_adc_c_coef, 4) && past_write_unit(past, past_A_DAC_K, (void*) &a_dac_k_coef, 4) From 2e2ec5660a2c5fed637fd819b1937f7325f2ce2f Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 6 Oct 2019 15:21:12 -0600 Subject: [PATCH 121/175] Updating page again on reset to update values --- opendps/func_settings.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index 54e9bc46..52ccb9b7 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -464,6 +464,8 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { // long SET press will reest all values if (data == press_long) { settings_reset(); + // update page to update values + set_page(current_page); return true; } From 1a4750ae73a3f34e441890c9363b2393cde83af6 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 6 Oct 2019 15:23:45 -0600 Subject: [PATCH 122/175] Added update interval --- opendps/func_settings.c | 1 + opendps/opendps.c | 8 +++----- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index 52ccb9b7..da121ec6 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -146,6 +146,7 @@ static void set_brightness(ui_number_t *item) { } static int32_t get_refresh() { + return opendps_update_interval; return 250 * 1000; } static void set_refresh(ui_number_t *item) { diff --git a/opendps/opendps.c b/opendps/opendps.c index 310984e9..32e4ecb8 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -90,9 +90,6 @@ #define TFT_HEIGHT (128) #define TFT_WIDTH (128) -/** How ofter we update the measurements in the UI (ms) */ -#define UI_UPDATE_INTERVAL_MS (250) - /** Timeout for waiting for wifi connction (ms) */ #define WIFI_CONNECT_TIMEOUT (10000) @@ -119,6 +116,7 @@ static void check_master_reset(void); static uint16_t bg_color; static uint32_t ui_width; static uint32_t ui_height; +uint16_t opendps_update_interval = 250; /** Used to make the screen flash */ static uint32_t tft_flashing_period; @@ -635,8 +633,8 @@ static void ui_tick(void) static uint64_t last_lock_flash = 0; static uint64_t last = 0; - /** Update on the first call and every UI_UPDATE_INTERVAL_MS ms */ - if (last > 0 && get_ticks() - last < UI_UPDATE_INTERVAL_MS) { + /** Update on the first call and every opendps_update_interval ms */ + if (last > 0 && get_ticks() - last < opendps_update_interval) { return; } From b8f2dd2c75c07d5ee1f0f9f1eae225082465af5e Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 6 Oct 2019 15:26:25 -0600 Subject: [PATCH 123/175] Extern the update interval variable --- opendps/func_settings.c | 1 + 1 file changed, 1 insertion(+) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index da121ec6..940b6724 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -62,6 +62,7 @@ static set_param_status_t set_parameter(char *name, char *value); static set_param_status_t get_parameter(char *name, char *value, uint32_t value_len); static bool select_mode; +extern uint16_t opendps_update_interval; // want to calibrate V_ADC,DAC A_ADC,DAC VIN_DAC Brightness, refresh timing // so 12 fields in total... From c34cf6297de4851ad9b94d70145e4447a267e817 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 6 Oct 2019 15:38:59 -0600 Subject: [PATCH 124/175] Field changes should now call the field change function --- opendps/func_settings.c | 35 +++++++++++++++++++++++------------ opendps/opendps.h | 2 ++ 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index 940b6724..6a19d724 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -38,6 +38,7 @@ #include "opendps.h" #include "gfx-crosshair.h" #include "pastunits.h" +#include "opendps.h" #define SCREEN_ID (7) @@ -62,7 +63,6 @@ static set_param_status_t set_parameter(char *name, char *value); static set_param_status_t get_parameter(char *name, char *value, uint32_t value_len); static bool select_mode; -extern uint16_t opendps_update_interval; // want to calibrate V_ADC,DAC A_ADC,DAC VIN_DAC Brightness, refresh timing // so 12 fields in total... @@ -140,18 +140,29 @@ static void set_vin_adc_c(ui_number_t *item) { static int32_t get_brightness() { - return 100 * 1000; + return (hw_get_backlight() / 1.28f) * 1000; } static void set_brightness(ui_number_t *item) { - // + if (item->value > 100 * 1000) item->value = 100 * 1000; + if (item->value < 0) item->value = 0; + + hw_set_backlight((item->value / 1000.0f) * 1.28f); } static int32_t get_refresh() { - return opendps_update_interval; - return 250 * 1000; + return opendps_update_interval * 1000; } static void set_refresh(ui_number_t *item) { - // + // todo: make this persistent + opendps_update_interval = item->value / 1000; + + // ensure sane values + if (opendps_update_interval > 1000) { + opendps_update_interval = 1000; + } + if (opendps_update_interval < 10) { + opendps_update_interval = 10; + } } @@ -237,7 +248,7 @@ ui_number_t settings_field[] = { .num_digits = 3, .num_decimals = 3, .unit = unit_none, - .changed = NULL, + .changed = &field_changed, }, { { @@ -258,7 +269,7 @@ ui_number_t settings_field[] = { .num_digits = 3, .num_decimals = 3, .unit = unit_none, - .changed = NULL, + .changed = &field_changed, }, { { @@ -279,7 +290,7 @@ ui_number_t settings_field[] = { .num_digits = 3, .num_decimals = 3, .unit = unit_none, - .changed = NULL, + .changed = &field_changed, }, { { @@ -300,7 +311,7 @@ ui_number_t settings_field[] = { .num_digits = 3, .num_decimals = 3, .unit = unit_none, - .changed = NULL, + .changed = &field_changed, }, { { @@ -321,7 +332,7 @@ ui_number_t settings_field[] = { .num_digits = 3, .num_decimals = 3, .unit = unit_none, - .changed = NULL, + .changed = &field_changed, }, { { @@ -342,7 +353,7 @@ ui_number_t settings_field[] = { .num_digits = 3, .num_decimals = 3, .unit = unit_none, - .changed = NULL, + .changed = &field_changed, } }; diff --git a/opendps/opendps.h b/opendps/opendps.h index 2d35a9c3..fb650b30 100644 --- a/opendps/opendps.h +++ b/opendps/opendps.h @@ -32,6 +32,8 @@ /** Max number of parameters to a function */ #define OPENDPS_MAX_PARAMETERS (8) +extern uint16_t opendps_update_interval; + /** * @brief Enable specified function * From ede443bf70f64b9cd2938ca21f9fb080c42c6159 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 6 Oct 2019 15:46:33 -0600 Subject: [PATCH 125/175] Ensure that current item is in sync on activation --- opendps/func_settings.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index 6a19d724..cd2af4a5 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -55,6 +55,9 @@ static void settings_reset(void); static void past_save(past_t *past); static void past_restore(past_t *past); +static void activated(void); +static void deactivated(void); + static bool event(uui_t *ui, event_t event, uint8_t data); static void field_changed(ui_number_t *item); static void set_page(int8_t page); @@ -182,6 +185,8 @@ static int8_t current_page = 0; static int8_t current_item = 0; // 0 through 4 get_func get_functions[] = { + &get_brightness, + &get_refresh, &get_v_adc_k, &get_v_adc_c, &get_v_dac_k, @@ -192,11 +197,11 @@ get_func get_functions[] = { &get_a_dac_c, &get_vin_adc_k, &get_vin_adc_c, - &get_brightness, - &get_refresh }; set_func set_functions[] = { + &set_brightness, + &set_refresh, &set_v_adc_k, &set_v_adc_c, &set_v_dac_k, @@ -207,12 +212,12 @@ set_func set_functions[] = { &set_a_dac_c, &set_vin_adc_k, &set_vin_adc_c, - &set_brightness, - &set_refresh }; // fields that can be changed const char* const field_label[] = { + "Scr-LED", + "Refresh", "V ADC K", "V ADC C", "V DAC K", @@ -223,8 +228,6 @@ const char* const field_label[] = { "I DAC C", "Vin ADC C", "Vin ADC K", - "Scr-LED", - "Refresh", }; @@ -366,8 +369,8 @@ ui_screen_t settings_screen = { .icon_width = GFX_CROSSHAIR_WIDTH, .icon_height = GFX_CROSSHAIR_HEIGHT, .event = event, - .activated = NULL, - .deactivated = NULL, + .activated = &activated, + .deactivated = &deactivated, .enable = &settings_enable, .past_save = &past_save, .past_restore = NULL, @@ -583,6 +586,12 @@ static void past_save(past_t *past) { pwrctl_past_save(past); } +static void activated() { + current_item = 0; +} + +static void deactivated() { +} /** * @brief Initialise the CV module and add its screen to the UI From 494c899463d0a998d9b0538e1ad91370dbaef639 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 6 Oct 2019 15:52:42 -0600 Subject: [PATCH 126/175] Reset page on reactivation --- opendps/func_settings.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index cd2af4a5..a5ec2520 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -587,10 +587,12 @@ static void past_save(past_t *past) { } static void activated() { + set_page(0); current_item = 0; } static void deactivated() { + tft_clear(); } /** From 52cea35d8206b1a9abcd2f87c910147a47bbe060 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 6 Oct 2019 15:57:13 -0600 Subject: [PATCH 127/175] On activation, we leave select mode --- opendps/func_settings.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index a5ec2520..626f8de2 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -589,6 +589,7 @@ static void past_save(past_t *past) { static void activated() { set_page(0); current_item = 0; + select_mode = 0; } static void deactivated() { @@ -608,6 +609,7 @@ void func_settings_init(uui_t *ui) { // init to page 0 set_page(0); current_item = 0; + select_mode = 0; uui_add_screen(ui, &settings_screen); } From 1b893a936b76cbd525fc78175430ce3daa4c1dcc Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 6 Oct 2019 16:03:43 -0600 Subject: [PATCH 128/175] Dividing coefficient values as floats --- opendps/func_settings.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index 626f8de2..4f071fab 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -75,13 +75,13 @@ static int32_t get_v_adc_k() { return v_adc_k_coef * 1000; } static void set_v_adc_k(ui_number_t *item) { - v_adc_k_coef = item->value / (item->color == RED) ? -1000.0f : 1000.0f; + v_adc_k_coef = (float)item->value / (item->color == RED) ? -1000.0f : 1000.0f; } static int32_t get_v_adc_c() { return v_adc_c_coef * 1000; } static void set_v_adc_c(ui_number_t *item) { - v_adc_c_coef = item->value / (item->color == RED) ? -1000.0f : 1000.0f; + v_adc_c_coef = (float)item->value / (item->color == RED) ? -1000.0f : 1000.0f; } @@ -89,13 +89,13 @@ static int32_t get_v_dac_k() { return v_dac_k_coef * 1000; } static void set_v_dac_k(ui_number_t *item) { - v_adc_k_coef = item->value / (item->color == RED) ? -1000.0f : 1000.0f; + v_adc_k_coef = (float)item->value / (item->color == RED) ? -1000.0f : 1000.0f; } static int32_t get_v_dac_c() { return v_dac_c_coef * 1000; } static void set_v_dac_c(ui_number_t *item) { - v_adc_c_coef = item->value / (item->color == RED) ? -1000.0f : 1000.0f; + v_dac_c_coef = (float)item->value / (item->color == RED) ? -1000.0f : 1000.0f; } @@ -104,13 +104,13 @@ static int32_t get_a_adc_k() { return a_adc_k_coef * 1000; } static void set_a_adc_k(ui_number_t *item) { - a_adc_k_coef = item->value / (item->color == RED) ? -1000.0f : 1000.0f; + a_adc_k_coef = (float)item->value / (item->color == RED) ? -1000.0f : 1000.0f; } static int32_t get_a_adc_c() { return a_adc_c_coef * 1000; } static void set_a_adc_c(ui_number_t *item) { - a_adc_c_coef = item->value / (item->color == RED) ? -1000.0f : 1000.0f; + a_adc_c_coef = (float)item->value / (item->color == RED) ? -1000.0f : 1000.0f; } @@ -118,13 +118,13 @@ static int32_t get_a_dac_k() { return a_dac_k_coef * 1000; } static void set_a_dac_k(ui_number_t *item) { - a_adc_k_coef = item->value / (item->color == RED) ? -1000.0f : 1000.0f; + a_dac_k_coef = (float)item->value / (item->color == RED) ? -1000.0f : 1000.0f; } static int32_t get_a_dac_c() { return a_dac_c_coef * 1000; } static void set_a_dac_c(ui_number_t *item) { - a_adc_c_coef = item->value / (item->color == RED) ? -1000.0f : 1000.0f; + a_dac_c_coef = (float)item->value / (item->color == RED) ? -1000.0f : 1000.0f; } @@ -132,13 +132,13 @@ static int32_t get_vin_adc_k() { return vin_adc_k_coef * 1000; } static void set_vin_adc_k(ui_number_t *item) { - vin_adc_k_coef = item->value / (item->color == RED) ? -1000.0f : 1000.0f; + vin_adc_k_coef = (float)item->value / (item->color == RED) ? -1000.0f : 1000.0f; } static int32_t get_vin_adc_c() { return vin_adc_c_coef * 1000; } static void set_vin_adc_c(ui_number_t *item) { - vin_adc_c_coef = item->value / (item->color == RED) ? -1000.0f : 1000.0f; + vin_adc_c_coef = (float)item->value / (item->color == RED) ? -1000.0f : 1000.0f; } From 0daeb777560f8a8742b573bb8065418b26434a15 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 6 Oct 2019 16:12:45 -0600 Subject: [PATCH 129/175] Properly handling negatives --- opendps/func_settings.c | 54 ++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index 4f071fab..364ae8bc 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -75,13 +75,15 @@ static int32_t get_v_adc_k() { return v_adc_k_coef * 1000; } static void set_v_adc_k(ui_number_t *item) { - v_adc_k_coef = (float)item->value / (item->color == RED) ? -1000.0f : 1000.0f; + v_adc_k_coef = item->value / 1000.0f; + if (item->color == RED) v_adc_k_coef = - v_adc_k_coef; } static int32_t get_v_adc_c() { return v_adc_c_coef * 1000; } static void set_v_adc_c(ui_number_t *item) { - v_adc_c_coef = (float)item->value / (item->color == RED) ? -1000.0f : 1000.0f; + v_adc_c_coef = item->value / 1000.0f; + if (item->color == RED) v_adc_c_coef = - v_adc_c_coef; } @@ -89,13 +91,15 @@ static int32_t get_v_dac_k() { return v_dac_k_coef * 1000; } static void set_v_dac_k(ui_number_t *item) { - v_adc_k_coef = (float)item->value / (item->color == RED) ? -1000.0f : 1000.0f; + v_adc_k_coef = item->value / 1000.0f; + if (item->color == RED) v_adc_k_coef = - v_adc_k_coef; } static int32_t get_v_dac_c() { return v_dac_c_coef * 1000; } static void set_v_dac_c(ui_number_t *item) { - v_dac_c_coef = (float)item->value / (item->color == RED) ? -1000.0f : 1000.0f; + v_dac_c_coef = item->value / 1000.0f; + if (item->color == RED) v_dac_c_coef = - v_dac_c_coef; } @@ -104,13 +108,15 @@ static int32_t get_a_adc_k() { return a_adc_k_coef * 1000; } static void set_a_adc_k(ui_number_t *item) { - a_adc_k_coef = (float)item->value / (item->color == RED) ? -1000.0f : 1000.0f; + a_adc_k_coef = item->value / 1000.0f; + if (item->color == RED) a_adc_k_coef = - a_adc_k_coef; } static int32_t get_a_adc_c() { return a_adc_c_coef * 1000; } static void set_a_adc_c(ui_number_t *item) { - a_adc_c_coef = (float)item->value / (item->color == RED) ? -1000.0f : 1000.0f; + a_adc_c_coef = item->value / 1000.0f; + if (item->color == RED) a_adc_c_coef = - a_adc_c_coef; } @@ -118,13 +124,15 @@ static int32_t get_a_dac_k() { return a_dac_k_coef * 1000; } static void set_a_dac_k(ui_number_t *item) { - a_dac_k_coef = (float)item->value / (item->color == RED) ? -1000.0f : 1000.0f; + a_dac_k_coef = item->value / 1000.0f; + if (item->color == RED) a_dac_k_coef = - a_dac_k_coef; } static int32_t get_a_dac_c() { return a_dac_c_coef * 1000; } static void set_a_dac_c(ui_number_t *item) { - a_dac_c_coef = (float)item->value / (item->color == RED) ? -1000.0f : 1000.0f; + a_dac_c_coef = item->value / 1000.0f; + if (item->color == RED) a_dac_c_coef = - a_dac_c_coef; } @@ -132,13 +140,15 @@ static int32_t get_vin_adc_k() { return vin_adc_k_coef * 1000; } static void set_vin_adc_k(ui_number_t *item) { - vin_adc_k_coef = (float)item->value / (item->color == RED) ? -1000.0f : 1000.0f; + vin_adc_k_coef = item->value / 1000.0f; + if (item->color == RED) vin_adc_k_coef = - vin_adc_k_coef; } static int32_t get_vin_adc_c() { return vin_adc_c_coef * 1000; } static void set_vin_adc_c(ui_number_t *item) { - vin_adc_c_coef = (float)item->value / (item->color == RED) ? -1000.0f : 1000.0f; + vin_adc_c_coef = item->value / 1000.0f; + if (item->color == RED) vin_adc_c_coef = - vin_adc_c_coef; } @@ -245,8 +255,8 @@ ui_number_t settings_field[] = { .pad_dot = false, .color = WHITE, .value = 0, - .min = -1000000, - .max = 1000000, + .min = -999999, + .max = 999999, .si_prefix = si_milli, .num_digits = 3, .num_decimals = 3, @@ -266,8 +276,8 @@ ui_number_t settings_field[] = { .pad_dot = false, .color = WHITE, .value = 0, - .min = -1000000, - .max = 1000000, + .min = -999999, + .max = 999999, .si_prefix = si_milli, .num_digits = 3, .num_decimals = 3, @@ -287,8 +297,8 @@ ui_number_t settings_field[] = { .pad_dot = false, .color = WHITE, .value = 0, - .min = -1000000, - .max = 1000000, + .min = -999999, + .max = 999999, .si_prefix = si_milli, .num_digits = 3, .num_decimals = 3, @@ -308,8 +318,8 @@ ui_number_t settings_field[] = { .pad_dot = false, .color = WHITE, .value = 0, - .min = -1000000, - .max = 1000000, + .min = -999999, + .max = 999999, .si_prefix = si_milli, .num_digits = 3, .num_decimals = 3, @@ -329,8 +339,8 @@ ui_number_t settings_field[] = { .pad_dot = false, .color = WHITE, .value = 0, - .min = -1000000, - .max = 1000000, + .min = -999999, + .max = 999999, .si_prefix = si_milli, .num_digits = 3, .num_decimals = 3, @@ -350,8 +360,8 @@ ui_number_t settings_field[] = { .pad_dot = false, .color = WHITE, .value = 0, - .min = -1000000, - .max = 1000000, + .min = -999999, + .max = 999999, .si_prefix = si_milli, .num_digits = 3, .num_decimals = 3, From 0c32b3555a36127693c9dde72a70e7a754093290 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 6 Oct 2019 16:26:03 -0600 Subject: [PATCH 130/175] Saving the opendps update interval to past --- opendps/func_settings.c | 11 ++++++++--- opendps/opendps.c | 13 ++++++++++++- opendps/pastunits.h | 1 + 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index 364ae8bc..4fa7a838 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -91,8 +91,8 @@ static int32_t get_v_dac_k() { return v_dac_k_coef * 1000; } static void set_v_dac_k(ui_number_t *item) { - v_adc_k_coef = item->value / 1000.0f; - if (item->color == RED) v_adc_k_coef = - v_adc_k_coef; + v_dac_k_coef = item->value / 1000.0f; + if (item->color == RED) v_dac_k_coef = - v_dac_k_coef; } static int32_t get_v_dac_c() { return v_dac_c_coef * 1000; @@ -383,7 +383,7 @@ ui_screen_t settings_screen = { .deactivated = &deactivated, .enable = &settings_enable, .past_save = &past_save, - .past_restore = NULL, + .past_restore = &past_restore, .tick = &settings_tick, .num_items = ITEMS_PER_PAGE, .items = { @@ -590,12 +590,17 @@ static void settings_reset() { v_dac_c_coef = V_DAC_C; vin_adc_k_coef = VIN_ADC_K; vin_adc_c_coef = VIN_ADC_C; + + opendps_clear_calibration(); } static void past_save(past_t *past) { pwrctl_past_save(past); } +static void past_restore(past_t *past) { +} + static void activated() { set_page(0); current_item = 0; diff --git a/opendps/opendps.c b/opendps/opendps.c index 32e4ecb8..b9bd1ddf 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -116,7 +116,7 @@ static void check_master_reset(void); static uint16_t bg_color; static uint32_t ui_width; static uint32_t ui_height; -uint16_t opendps_update_interval = 250; +uint32_t opendps_update_interval = 250; /** Used to make the screen flash */ static uint32_t tft_flashing_period; @@ -888,6 +888,11 @@ static void read_past_settings(void) } hw_set_backlight(last_tft_brightness); + if (past_read_unit(&g_past, opendps_update_interval, (const void**) &p, &length)) { + if (p) { + opendps_update_interval = *p; + } + } #ifdef GIT_VERSION /** Update app git hash in past if needed */ @@ -934,6 +939,12 @@ static void write_past_settings(void) dbg_printf("Error: past write inv failed!\n"); } } + + // save the update interval value + if ( ! past_write_unit(past, past_UPDATE_INTERVAL, (void*) &opendps_update_interval, sizeof(opendps_update_interval))) { + dbg_printf("Error: past write inv failed!\n"); + } + } /** diff --git a/opendps/pastunits.h b/opendps/pastunits.h index 9f0a8410..50c0bbd9 100644 --- a/opendps/pastunits.h +++ b/opendps/pastunits.h @@ -46,6 +46,7 @@ typedef enum { past_VIN_ADC_K, past_VIN_ADC_C, past_tft_brightness, + past_UPDATE_INTERVAL, /** A past unit who's precense indicates we have a non finished upgrade and must not boot */ past_upgrade_started = 0xff From 10921bef91f934bde65ad73caa7e4abc44f44afb Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 6 Oct 2019 16:26:56 -0600 Subject: [PATCH 131/175] Bad past reference --- opendps/opendps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opendps/opendps.c b/opendps/opendps.c index b9bd1ddf..b9129fa4 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -941,7 +941,7 @@ static void write_past_settings(void) } // save the update interval value - if ( ! past_write_unit(past, past_UPDATE_INTERVAL, (void*) &opendps_update_interval, sizeof(opendps_update_interval))) { + if ( ! past_write_unit(&g_past, past_UPDATE_INTERVAL, (void*) &opendps_update_interval, sizeof(opendps_update_interval))) { dbg_printf("Error: past write inv failed!\n"); } From 50eb7e246848499efd3af68907c638e36b9690eb Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 6 Oct 2019 16:27:41 -0600 Subject: [PATCH 132/175] Fixed bad update_interval type --- opendps/opendps.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opendps/opendps.h b/opendps/opendps.h index fb650b30..6a5f2d3a 100644 --- a/opendps/opendps.h +++ b/opendps/opendps.h @@ -32,7 +32,7 @@ /** Max number of parameters to a function */ #define OPENDPS_MAX_PARAMETERS (8) -extern uint16_t opendps_update_interval; +extern uint32_t opendps_update_interval; /** * @brief Enable specified function From 04735a887784013ef5b6388e490337bafbefa322 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 6 Oct 2019 16:32:54 -0600 Subject: [PATCH 133/175] Fixed bad reference to part_UPDATE_INTERVAL --- opendps/opendps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opendps/opendps.c b/opendps/opendps.c index b9129fa4..fd7fa005 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -888,7 +888,7 @@ static void read_past_settings(void) } hw_set_backlight(last_tft_brightness); - if (past_read_unit(&g_past, opendps_update_interval, (const void**) &p, &length)) { + if (past_read_unit(&g_past, past_UPDATE_INTERVAL, (const void**) &p, &length)) { if (p) { opendps_update_interval = *p; } From 56fc46d4e665f6361a6f6dc3c32387c060df9012 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 6 Oct 2019 17:20:42 -0600 Subject: [PATCH 134/175] Moved TFT_WIDTH/TFT_HEIGHT to opendps.h --- opendps/opendps.c | 3 --- opendps/opendps.h | 4 ++++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/opendps/opendps.c b/opendps/opendps.c index fd7fa005..14cfecdd 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -87,9 +87,6 @@ #include "logo.h" #endif // CONFIG_SPLASH_SCREEN -#define TFT_HEIGHT (128) -#define TFT_WIDTH (128) - /** Timeout for waiting for wifi connction (ms) */ #define WIFI_CONNECT_TIMEOUT (10000) diff --git a/opendps/opendps.h b/opendps/opendps.h index 6a5f2d3a..002ddc98 100644 --- a/opendps/opendps.h +++ b/opendps/opendps.h @@ -32,6 +32,10 @@ /** Max number of parameters to a function */ #define OPENDPS_MAX_PARAMETERS (8) +/** UI Width/Height */ +#define TFT_HEIGHT (128) +#define TFT_WIDTH (128) + extern uint32_t opendps_update_interval; /** From aea1bc087e81e531f088e06401eabf9177f2cee0 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 6 Oct 2019 17:39:46 -0600 Subject: [PATCH 135/175] Added missing events code so it works with master Cleaned up prototype declarations --- opendps/func_settings.c | 290 +++++++++++++++++++++++----------------- opendps/func_settings.h | 2 +- opendps/uui.c | 4 + opendps/uui.h | 23 ++-- 4 files changed, 186 insertions(+), 133 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index 4fa7a838..e3df8da8 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2019 + * Copyright (c) 2019 Leo Leung * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -48,12 +48,10 @@ * This is the implementation of the Settings screen. */ -static void settings_enable(bool _enable); static void settings_tick(void); static void settings_reset(void); static void past_save(past_t *past); -static void past_restore(past_t *past); static void activated(void); static void deactivated(void); @@ -67,116 +65,36 @@ static set_param_status_t get_parameter(char *name, char *value, uint32_t value_ static bool select_mode; + // want to calibrate V_ADC,DAC A_ADC,DAC VIN_DAC Brightness, refresh timing // so 12 fields in total... // possibly want OCP, OVP, OPP? - -static int32_t get_v_adc_k() { - return v_adc_k_coef * 1000; -} -static void set_v_adc_k(ui_number_t *item) { - v_adc_k_coef = item->value / 1000.0f; - if (item->color == RED) v_adc_k_coef = - v_adc_k_coef; -} -static int32_t get_v_adc_c() { - return v_adc_c_coef * 1000; -} -static void set_v_adc_c(ui_number_t *item) { - v_adc_c_coef = item->value / 1000.0f; - if (item->color == RED) v_adc_c_coef = - v_adc_c_coef; -} - - -static int32_t get_v_dac_k() { - return v_dac_k_coef * 1000; -} -static void set_v_dac_k(ui_number_t *item) { - v_dac_k_coef = item->value / 1000.0f; - if (item->color == RED) v_dac_k_coef = - v_dac_k_coef; -} -static int32_t get_v_dac_c() { - return v_dac_c_coef * 1000; -} -static void set_v_dac_c(ui_number_t *item) { - v_dac_c_coef = item->value / 1000.0f; - if (item->color == RED) v_dac_c_coef = - v_dac_c_coef; -} - - - -static int32_t get_a_adc_k() { - return a_adc_k_coef * 1000; -} -static void set_a_adc_k(ui_number_t *item) { - a_adc_k_coef = item->value / 1000.0f; - if (item->color == RED) a_adc_k_coef = - a_adc_k_coef; -} -static int32_t get_a_adc_c() { - return a_adc_c_coef * 1000; -} -static void set_a_adc_c(ui_number_t *item) { - a_adc_c_coef = item->value / 1000.0f; - if (item->color == RED) a_adc_c_coef = - a_adc_c_coef; -} - - -static int32_t get_a_dac_k() { - return a_dac_k_coef * 1000; -} -static void set_a_dac_k(ui_number_t *item) { - a_dac_k_coef = item->value / 1000.0f; - if (item->color == RED) a_dac_k_coef = - a_dac_k_coef; -} -static int32_t get_a_dac_c() { - return a_dac_c_coef * 1000; -} -static void set_a_dac_c(ui_number_t *item) { - a_dac_c_coef = item->value / 1000.0f; - if (item->color == RED) a_dac_c_coef = - a_dac_c_coef; -} - - -static int32_t get_vin_adc_k() { - return vin_adc_k_coef * 1000; -} -static void set_vin_adc_k(ui_number_t *item) { - vin_adc_k_coef = item->value / 1000.0f; - if (item->color == RED) vin_adc_k_coef = - vin_adc_k_coef; -} -static int32_t get_vin_adc_c() { - return vin_adc_c_coef * 1000; -} -static void set_vin_adc_c(ui_number_t *item) { - vin_adc_c_coef = item->value / 1000.0f; - if (item->color == RED) vin_adc_c_coef = - vin_adc_c_coef; -} - - -static int32_t get_brightness() { - return (hw_get_backlight() / 1.28f) * 1000; -} -static void set_brightness(ui_number_t *item) { - if (item->value > 100 * 1000) item->value = 100 * 1000; - if (item->value < 0) item->value = 0; - - hw_set_backlight((item->value / 1000.0f) * 1.28f); -} - -static int32_t get_refresh() { - return opendps_update_interval * 1000; -} -static void set_refresh(ui_number_t *item) { - // todo: make this persistent - opendps_update_interval = item->value / 1000; - - // ensure sane values - if (opendps_update_interval > 1000) { - opendps_update_interval = 1000; - } - if (opendps_update_interval < 10) { - opendps_update_interval = 10; - } -} +// +// +static int32_t get_v_adc_k(void); +static void set_v_adc_k(ui_number_t *item); +static int32_t get_v_adc_c(void); +static void set_v_adc_c(ui_number_t *item); +static int32_t get_v_dac_k(void); +static void set_v_dac_k(ui_number_t *item); +static int32_t get_v_dac_c(void); +static void set_v_dac_c(ui_number_t *item); +static int32_t get_a_adc_k(void); +static void set_a_adc_k(ui_number_t *item); +static int32_t get_a_adc_c(void); +static void set_a_adc_c(ui_number_t *item); +static int32_t get_a_dac_k(void); +static void set_a_dac_k(ui_number_t *item); +static int32_t get_a_dac_c(void); +static void set_a_dac_c(ui_number_t *item); +static int32_t get_vin_adc_k(void); +static void set_vin_adc_k(ui_number_t *item); +static int32_t get_vin_adc_c(void); +static void set_vin_adc_c(ui_number_t *item); +static int32_t get_brightness(void); +static void set_brightness(ui_number_t *item); +static int32_t get_refresh(void); +static void set_refresh(ui_number_t *item); @@ -381,9 +299,9 @@ ui_screen_t settings_screen = { .event = event, .activated = &activated, .deactivated = &deactivated, - .enable = &settings_enable, + .enable = NULL, .past_save = &past_save, - .past_restore = &past_restore, + .past_restore = NULL, .tick = &settings_tick, .num_items = ITEMS_PER_PAGE, .items = { @@ -432,6 +350,118 @@ static set_param_status_t get_parameter(char *name, char *value, uint32_t value_ } +static int32_t get_v_adc_k() { + return v_adc_k_coef * 1000; +} +static void set_v_adc_k(ui_number_t *item) { + v_adc_k_coef = item->value / 1000.0f; + if (item->color == RED) v_adc_k_coef = - v_adc_k_coef; +} +static int32_t get_v_adc_c() { + return v_adc_c_coef * 1000; +} +static void set_v_adc_c(ui_number_t *item) { + v_adc_c_coef = item->value / 1000.0f; + if (item->color == RED) v_adc_c_coef = - v_adc_c_coef; +} + + +static int32_t get_v_dac_k() { + return v_dac_k_coef * 1000; +} +static void set_v_dac_k(ui_number_t *item) { + v_dac_k_coef = item->value / 1000.0f; + if (item->color == RED) v_dac_k_coef = - v_dac_k_coef; +} +static int32_t get_v_dac_c() { + return v_dac_c_coef * 1000; +} +static void set_v_dac_c(ui_number_t *item) { + v_dac_c_coef = item->value / 1000.0f; + if (item->color == RED) v_dac_c_coef = - v_dac_c_coef; +} + + + +static int32_t get_a_adc_k() { + return a_adc_k_coef * 1000; +} +static void set_a_adc_k(ui_number_t *item) { + a_adc_k_coef = item->value / 1000.0f; + if (item->color == RED) a_adc_k_coef = - a_adc_k_coef; +} +static int32_t get_a_adc_c() { + return a_adc_c_coef * 1000; +} +static void set_a_adc_c(ui_number_t *item) { + a_adc_c_coef = item->value / 1000.0f; + if (item->color == RED) a_adc_c_coef = - a_adc_c_coef; +} + + +static int32_t get_a_dac_k() { + return a_dac_k_coef * 1000; +} +static void set_a_dac_k(ui_number_t *item) { + a_dac_k_coef = item->value / 1000.0f; + if (item->color == RED) a_dac_k_coef = - a_dac_k_coef; +} +static int32_t get_a_dac_c() { + return a_dac_c_coef * 1000; +} +static void set_a_dac_c(ui_number_t *item) { + a_dac_c_coef = item->value / 1000.0f; + if (item->color == RED) a_dac_c_coef = - a_dac_c_coef; +} + + +static int32_t get_vin_adc_k() { + return vin_adc_k_coef * 1000; +} +static void set_vin_adc_k(ui_number_t *item) { + vin_adc_k_coef = item->value / 1000.0f; + if (item->color == RED) vin_adc_k_coef = - vin_adc_k_coef; +} +static int32_t get_vin_adc_c() { + return vin_adc_c_coef * 1000; +} +static void set_vin_adc_c(ui_number_t *item) { + vin_adc_c_coef = item->value / 1000.0f; + if (item->color == RED) vin_adc_c_coef = - vin_adc_c_coef; +} + + +static int32_t get_brightness() { + return (hw_get_backlight() / 1.28f) * 1000; +} +static void set_brightness(ui_number_t *item) { + if (item->value > 100 * 1000) item->value = 100 * 1000; + if (item->value < 0) item->value = 0; + + hw_set_backlight((item->value / 1000.0f) * 1.28f); +} + +static int32_t get_refresh() { + return opendps_update_interval * 1000; +} +static void set_refresh(ui_number_t *item) { + // todo: make this persistent + opendps_update_interval = item->value / 1000; + + // ensure sane values + if (opendps_update_interval > 1000) { + opendps_update_interval = 1000; + } + if (opendps_update_interval < 10) { + opendps_update_interval = 10; + } +} + + +/** + * @brief event handler: We only care about the SET, M1 and M2 buttons + * used to keep track of where we are in the menu + */ static bool event(uui_t *ui, event_t event, uint8_t data) { switch (event) { case event_button_m1: @@ -519,7 +549,10 @@ static void field_changed(ui_number_t *item) { set_functions[page_offset + current_item](item); } -// called whenever the page is changed +/** + * @brief set_page will change the current settings page + * to the given page number. + */ static void set_page(int8_t page) { current_page = page; @@ -535,8 +568,8 @@ static void set_page(int8_t page) { // update field value using value from the get function int32_t value = get_functions[page_offset + i](); if (value < 0) { - // because uui_number doesn't support signed values (i think??) - // color represents the sign + // because uui_number doesn't support signed values + // color represents the sign. This is is gross hack, I know. settings_field[i].value = -value; settings_field[i].color = RED; } else { @@ -545,13 +578,13 @@ static void set_page(int8_t page) { } } - // debug: tft_clear(); } -static void settings_enable(bool enabled) { -} +/** + * @brief settings_tick will render the UI + */ static void settings_tick(void) { int8_t page_offset = current_page * ITEMS_PER_PAGE; @@ -560,7 +593,6 @@ static void settings_tick(void) { uint16_t x = settings_field[i].ui.x; uint16_t y = settings_field[i].ui.y; - // if greater than total number of items, clear the area if (page_offset + i >= ITEMS) { tft_fill(0 /* x */, i * ROW_HEIGHT /* y */, @@ -579,6 +611,9 @@ static void settings_tick(void) { } +/** + * @brief resets the settings value. + */ static void settings_reset() { a_adc_k_coef = A_ADC_K; a_adc_c_coef = A_ADC_C; @@ -591,22 +626,35 @@ static void settings_reset() { vin_adc_k_coef = VIN_ADC_K; vin_adc_c_coef = VIN_ADC_C; + // clear calibration settings from past opendps_clear_calibration(); + + // reset interval and brightness settings + opendps_update_interval = 250; + hw_set_backlight(128); } + +/** + * @brief ensure power constants are saved + */ static void past_save(past_t *past) { pwrctl_past_save(past); } -static void past_restore(past_t *past) { -} +/** + * @brief on activation, reset to first page + */ static void activated() { set_page(0); current_item = 0; select_mode = 0; } +/** + * @brief on deactivation, clear the screen + */ static void deactivated() { tft_clear(); } diff --git a/opendps/func_settings.h b/opendps/func_settings.h index 9abb8eb3..f4d6eb17 100644 --- a/opendps/func_settings.h +++ b/opendps/func_settings.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2019 + * Copyright (c) 2019 Leo Leung * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/opendps/uui.c b/opendps/uui.c index f44d0ef7..4e222eb7 100644 --- a/opendps/uui.c +++ b/opendps/uui.c @@ -141,6 +141,10 @@ void uui_handle_screen_event(uui_t *ui, event_t event) return; } + // If the screen handled the event, do nothing. + if (ui->screens[ui->cur_screen]->event && ui->screens[ui->cur_screen]->event(ui, event)) + return; + switch(event) { case event_rot_left_set: uui_prev_screen(ui); diff --git a/opendps/uui.h b/opendps/uui.h index f4c4b2d1..dafbe602 100644 --- a/opendps/uui.h +++ b/opendps/uui.h @@ -149,6 +149,17 @@ typedef struct ui_item_t { */ #define MCALL(item, operation, ...) ((ui_item_t*) (item))->operation((ui_item_t*) item, ##__VA_ARGS__) +/** + * A UI consists of several screens + */ +typedef struct { + uint8_t num_screens; + uint8_t cur_screen; + bool is_visible; + ui_screen_t *screens[MAX_SCREENS]; + past_t *past; +} uui_t; + /** * A screen has a name and holds num_items UI items */ @@ -166,6 +177,7 @@ struct ui_screen { void (*activated)(void); /** Called when the screen is switched to */ void (*deactivated)(void); /** Called when the screen is about to be changed from */ void (*enable)(bool _enable); /** Called when the enable button is pressed */ + bool (*event)(uui_t *ui, event_t event); /** Called when an event occurs (eg. button press). Return false if unhandled so main UI can handle it */ void (*tick)(void); /** Called periodically allowing the UI to do house keeping */ void (*past_save)(past_t *past); void (*past_restore)(past_t *past); @@ -174,17 +186,6 @@ struct ui_screen { ui_item_t *items[]; }; -/** - * A UI consists of several screens - */ -typedef struct { - uint8_t num_screens; - uint8_t cur_screen; - bool is_visible; - ui_screen_t *screens[MAX_SCREENS]; - past_t *past; -} uui_t; - /** * @brief Initialize the UUI instance * From f17871eaa149ce002e46f8172cfa2ab1f4808641 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 6 Oct 2019 17:59:38 -0600 Subject: [PATCH 136/175] Added the enable function back so that past write gets called --- opendps/func_settings.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index e3df8da8..027614fe 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -47,7 +47,7 @@ /* * This is the implementation of the Settings screen. */ - +static void settings_enable(bool _enable); static void settings_tick(void); static void settings_reset(void); @@ -299,7 +299,7 @@ ui_screen_t settings_screen = { .event = event, .activated = &activated, .deactivated = &deactivated, - .enable = NULL, + .enable = &settings_enable, .past_save = &past_save, .past_restore = NULL, .tick = &settings_tick, @@ -659,6 +659,9 @@ static void deactivated() { tft_clear(); } +static void settings_enable(bool enabled) { +} + /** * @brief Initialise the CV module and add its screen to the UI * From 2f4cc9b2c0cb90b70396c550de03f5c00c207bc4 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 6 Oct 2019 20:54:23 -0600 Subject: [PATCH 137/175] Minor changes --- opendps/opendps.c | 4 ++-- opendps/opendps.h | 5 ----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/opendps/opendps.c b/opendps/opendps.c index 8ebab3cf..5ef0fbdb 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -971,8 +971,8 @@ static void event_handler(void) if ( ! event_get(&event, &data)) { hw_longpress_check(); - /** Update on the first call and every UI_UPDATE_INTERVAL_MS ms */ - if (last <= 0 || get_ticks() - last >= UI_UPDATE_INTERVAL_MS) { + /** Update on the first call and every opendps_update_interval ms */ + if (last <= 0 || get_ticks() - last >= opendps_update_interval) { ui_tick(); last = get_ticks(); } diff --git a/opendps/opendps.h b/opendps/opendps.h index cd7e24b5..002ddc98 100644 --- a/opendps/opendps.h +++ b/opendps/opendps.h @@ -33,15 +33,10 @@ #define OPENDPS_MAX_PARAMETERS (8) /** UI Width/Height */ -<<<<<<< HEAD -#define TFT_WIDTH (128) -#define TFT_HEIGHT (128) -======= #define TFT_HEIGHT (128) #define TFT_WIDTH (128) extern uint32_t opendps_update_interval; ->>>>>>> aea1bc087e81e531f088e06401eabf9177f2cee0 /** * @brief Enable specified function From fcb475e8f65f6d0f0298d2e9b60b5fe507c4e3fe Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Mon, 7 Oct 2019 10:05:17 -0600 Subject: [PATCH 138/175] Ensure that pressing rot will not enter edit mode if already in edit mode. --- opendps/func_dpsmode.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index ea7a23f3..5a86d211 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -637,16 +637,24 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { break; case event_rot_press: - // pressing rot should focus on 3rd item if not already in select mode - if (third_item && ! single_edit_mode && ! select_mode) { - if (((ui_number_t *)third_item)->ui.can_focus) { - uui_focus(ui, (ui_item_t *)third_item); - select_mode = true; - return false; - } + // let parent handle event if no valid third item exists + if ( ! third_item) { + return false; } - break; + // Let parent handle event if we are in single edit mode, or select mode + // This is to avoid interfereing with existing edit selection + if (single_edit_mode || select_mode) { + return true; + } + + // Otherwise, if we have a valid third item and not in any edit mode + // we will focus on and edit the third item + if (((ui_number_t *)third_item)->ui.can_focus) { + uui_focus(ui, (ui_item_t *)third_item); + select_mode = true; + } + return false; case event_opp: // opp mode From 1534f725bab999601c44405d361d860041df1680 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Mon, 7 Oct 2019 19:29:18 -0600 Subject: [PATCH 139/175] Documentation and minor refactor --- opendps/func_settings.c | 112 +++++++++++++++++++++++----------------- opendps/func_settings.h | 3 ++ opendps/opendps.c | 10 ++-- opendps/opendps.h | 2 +- opendps/pwrctl.c | 22 ++++---- 5 files changed, 85 insertions(+), 64 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index 027614fe..65a39136 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -40,9 +40,27 @@ #include "pastunits.h" #include "opendps.h" - #define SCREEN_ID (7) +// Number of fields shown per page +#define ITEMS_PER_PAGE 6 + +// Total number of fields that can be edited +#define ITEMS 12 + +// PAGES = ceil(ITEMS / ITEMS_PER_PAGE) +#define PAGES 2 + +// UI Row height in pixels +#define ROW_HEIGHT 17 + +// Field X/Y offsets. Fields are shown on the right-hand side of the screen +#define FIELD_Y_OFFSET 0 +#define FIELD_X_OFFSET 128 + +// which page we are currently on. +static int8_t current_page = 0; +static int8_t current_item = 0; /* * This is the implementation of the Settings screen. @@ -66,11 +84,9 @@ static set_param_status_t get_parameter(char *name, char *value, uint32_t value_ static bool select_mode; -// want to calibrate V_ADC,DAC A_ADC,DAC VIN_DAC Brightness, refresh timing -// so 12 fields in total... -// possibly want OCP, OVP, OPP? -// -// +/* + * Get/Set functions used as callbacks for all editable fields + */ static int32_t get_v_adc_k(void); static void set_v_adc_k(ui_number_t *item); static int32_t get_v_adc_c(void); @@ -96,22 +112,27 @@ static void set_brightness(ui_number_t *item); static int32_t get_refresh(void); static void set_refresh(ui_number_t *item); +/* + * Field labels + */ +const char* const field_label[] = { + "Scr-LED", + "Refresh", + "V ADC K", + "V ADC C", + "V DAC K", + "V DAC C", + "I ADC K", + "I ADC C", + "I DAC K", + "I DAC C", + "Vin ADC C", + "Vin ADC K", +}; - -typedef void (*set_func)(struct ui_number_t *item); -typedef int32_t (*get_func)(); - -#define ITEMS_PER_PAGE 6 -#define ITEMS 12 -#define PAGES 2 // 12 / 6 = 2 pages worth -#define ROW_HEIGHT 17 -#define FIELD_Y_OFFSET 0 // 15 -#define FIELD_X_OFFSET 128 // 64 // half of screen - -// which page we are currently on. -static int8_t current_page = 0; -static int8_t current_item = 0; // 0 through 4 - +/* + * Field get callbacks + */ get_func get_functions[] = { &get_brightness, &get_refresh, @@ -127,6 +148,9 @@ get_func get_functions[] = { &get_vin_adc_c, }; +/* + * Field set callbacks + */ set_func set_functions[] = { &set_brightness, &set_refresh, @@ -142,23 +166,10 @@ set_func set_functions[] = { &set_vin_adc_c, }; -// fields that can be changed -const char* const field_label[] = { - "Scr-LED", - "Refresh", - "V ADC K", - "V ADC C", - "V DAC K", - "V DAC C", - "I ADC K", - "I ADC C", - "I DAC K", - "I DAC C", - "Vin ADC C", - "Vin ADC K", -}; - - +/* + * Field UI elements + * One for each row + */ ui_number_t settings_field[] = { { { @@ -289,6 +300,9 @@ ui_number_t settings_field[] = { }; +/* + * Main screen UI + */ ui_screen_t settings_screen = { .id = SCREEN_ID, .name = "settings", @@ -322,7 +336,6 @@ ui_screen_t settings_screen = { }; - /** * @brief Set function parameter * @@ -350,6 +363,9 @@ static set_param_status_t get_parameter(char *name, char *value, uint32_t value_ } +/* + * Get / Set callback functions + */ static int32_t get_v_adc_k() { return v_adc_k_coef * 1000; } @@ -442,18 +458,18 @@ static void set_brightness(ui_number_t *item) { } static int32_t get_refresh() { - return opendps_update_interval * 1000; + return opendps_screen_update_ms * 1000; } static void set_refresh(ui_number_t *item) { // todo: make this persistent - opendps_update_interval = item->value / 1000; + opendps_screen_update_ms = item->value / 1000; // ensure sane values - if (opendps_update_interval > 1000) { - opendps_update_interval = 1000; + if (opendps_screen_update_ms > 1000) { + opendps_screen_update_ms = 1000; } - if (opendps_update_interval < 10) { - opendps_update_interval = 10; + if (opendps_screen_update_ms < 10) { + opendps_screen_update_ms = 10; } } @@ -630,7 +646,7 @@ static void settings_reset() { opendps_clear_calibration(); // reset interval and brightness settings - opendps_update_interval = 250; + opendps_screen_update_ms = 250; hw_set_backlight(128); } @@ -672,8 +688,8 @@ void func_settings_init(uui_t *ui) { number_init(&settings_field[i]); } - // init to page 0 - set_page(0); + // screen activation will cause cur_item to be reset + // Ensure current item matches the UI system current_item = 0; select_mode = 0; diff --git a/opendps/func_settings.h b/opendps/func_settings.h index f4d6eb17..27c1345c 100644 --- a/opendps/func_settings.h +++ b/opendps/func_settings.h @@ -27,6 +27,9 @@ #include "uui.h" +typedef void (*set_func)(struct ui_number_t *item); +typedef int32_t (*get_func)(); + /** * @brief Add the SETTINGS function to the UI * diff --git a/opendps/opendps.c b/opendps/opendps.c index 14cfecdd..21431b18 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -113,7 +113,7 @@ static void check_master_reset(void); static uint16_t bg_color; static uint32_t ui_width; static uint32_t ui_height; -uint32_t opendps_update_interval = 250; +uint32_t opendps_screen_update_ms = 250; /** Used to make the screen flash */ static uint32_t tft_flashing_period; @@ -630,8 +630,8 @@ static void ui_tick(void) static uint64_t last_lock_flash = 0; static uint64_t last = 0; - /** Update on the first call and every opendps_update_interval ms */ - if (last > 0 && get_ticks() - last < opendps_update_interval) { + /** Update on the first call and every opendps_screen_update_ms ms */ + if (last > 0 && get_ticks() - last < opendps_screen_update_ms) { return; } @@ -887,7 +887,7 @@ static void read_past_settings(void) if (past_read_unit(&g_past, past_UPDATE_INTERVAL, (const void**) &p, &length)) { if (p) { - opendps_update_interval = *p; + opendps_screen_update_ms = *p; } } @@ -938,7 +938,7 @@ static void write_past_settings(void) } // save the update interval value - if ( ! past_write_unit(&g_past, past_UPDATE_INTERVAL, (void*) &opendps_update_interval, sizeof(opendps_update_interval))) { + if ( ! past_write_unit(&g_past, past_UPDATE_INTERVAL, (void*) &opendps_screen_update_ms, sizeof(opendps_screen_update_ms))) { dbg_printf("Error: past write inv failed!\n"); } diff --git a/opendps/opendps.h b/opendps/opendps.h index 002ddc98..4b1e1ef9 100644 --- a/opendps/opendps.h +++ b/opendps/opendps.h @@ -36,7 +36,7 @@ #define TFT_HEIGHT (128) #define TFT_WIDTH (128) -extern uint32_t opendps_update_interval; +extern uint32_t opendps_screen_update_ms; /** * @brief Enable specified function diff --git a/opendps/pwrctl.c b/opendps/pwrctl.c index 0b2bc0a0..0bb9ac7e 100644 --- a/opendps/pwrctl.c +++ b/opendps/pwrctl.c @@ -99,18 +99,20 @@ void pwrctl_init(past_t *past) void pwrctl_past_save(past_t *past) { - if ( past_write_unit(past, past_A_ADC_K, (void*) &a_adc_k_coef, 4) - && past_write_unit(past, past_A_ADC_C, (void*) &a_adc_c_coef, 4) - && past_write_unit(past, past_A_DAC_K, (void*) &a_dac_k_coef, 4) - && past_write_unit(past, past_A_DAC_C, (void*) &a_dac_c_coef, 4) - && past_write_unit(past, past_V_ADC_K, (void*) &v_adc_k_coef, 4) - && past_write_unit(past, past_V_ADC_C, (void*) &v_adc_c_coef, 4) - && past_write_unit(past, past_V_DAC_K, (void*) &v_dac_k_coef, 4) - && past_write_unit(past, past_V_DAC_C, (void*) &v_dac_c_coef, 4) - && past_write_unit(past, past_VIN_ADC_K, (void*) &vin_adc_k_coef, 4) - && past_write_unit(past, past_VIN_ADC_C, (void*) &vin_adc_c_coef, 4) + if ( past_write_unit(past, past_A_ADC_K, (void*) &a_adc_k_coef, sizeof(a_adc_k_coef)) + && past_write_unit(past, past_A_ADC_C, (void*) &a_adc_c_coef, sizeof(a_adc_c_coef)) + && past_write_unit(past, past_A_DAC_K, (void*) &a_dac_k_coef, sizeof(a_dac_k_coef)) + && past_write_unit(past, past_A_DAC_C, (void*) &a_dac_c_coef, sizeof(a_dac_c_coef)) + && past_write_unit(past, past_V_ADC_K, (void*) &v_adc_k_coef, sizeof(v_adc_k_coef)) + && past_write_unit(past, past_V_ADC_C, (void*) &v_adc_c_coef, sizeof(v_adc_c_coef)) + && past_write_unit(past, past_V_DAC_K, (void*) &v_dac_k_coef, sizeof(v_dac_k_coef)) + && past_write_unit(past, past_V_DAC_C, (void*) &v_dac_c_coef, sizeof(v_dac_c_coef)) + && past_write_unit(past, past_VIN_ADC_K, (void*) &vin_adc_k_coef, sizeof(vin_adc_k_coef)) + && past_write_unit(past, past_VIN_ADC_C, (void*) &vin_adc_c_coef, sizeof(vin_adc_c_coef)) ) { // write ok + } else { + dbg_printf("Error: past write pwrctl_past_save failed\n"); } } From 2ad32324885234041fee46f238fac8805cecb4e9 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Mon, 7 Oct 2019 19:40:33 -0600 Subject: [PATCH 140/175] Added missing dbg_debug --- opendps/func_settings.c | 4 ++++ opendps/pwrctl.c | 1 + 2 files changed, 5 insertions(+) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index 65a39136..ef5c2356 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -690,8 +690,12 @@ void func_settings_init(uui_t *ui) { // screen activation will cause cur_item to be reset // Ensure current item matches the UI system + // Move back to previous page on init. + set_page(current_page); current_item = 0; select_mode = 0; uui_add_screen(ui, &settings_screen); } + + diff --git a/opendps/pwrctl.c b/opendps/pwrctl.c index 0bb9ac7e..147ebd41 100644 --- a/opendps/pwrctl.c +++ b/opendps/pwrctl.c @@ -25,6 +25,7 @@ #include "pwrctl.h" #include "dps-model.h" #include "pastunits.h" +#include "dbg_printf.h" #include #include From 54c5b551f7f08fc184e99c57c7899d0bff48660e Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Mon, 7 Oct 2019 19:43:03 -0600 Subject: [PATCH 141/175] Page remains the same on screen re-activation --- opendps/func_settings.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index ef5c2356..c078af60 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -663,7 +663,10 @@ static void past_save(past_t *past) { * @brief on activation, reset to first page */ static void activated() { - set_page(0); + // screen activation will cause cur_item to be reset + // Ensure current item matches the UI system + // Move back to previous page on init. + set_page(current_page); current_item = 0; select_mode = 0; } @@ -688,10 +691,8 @@ void func_settings_init(uui_t *ui) { number_init(&settings_field[i]); } - // screen activation will cause cur_item to be reset - // Ensure current item matches the UI system - // Move back to previous page on init. - set_page(current_page); + // initialize page and selected items + set_page(0); current_item = 0; select_mode = 0; From 5b449cc678845859d762253ea358bd04f470fe9e Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Mon, 7 Oct 2019 19:49:09 -0600 Subject: [PATCH 142/175] Fixed opendps_screen_update_ms --- opendps/opendps.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opendps/opendps.c b/opendps/opendps.c index d79358d6..b2335db6 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -965,8 +965,8 @@ static void event_handler(void) if (!event_get(&event, &data)) { hw_longpress_check(); - /** Update on the first call and every opendps_update_interval ms */ - if (last <= 0 || get_ticks() - last >= opendps_update_interval) { + /** Update on the first call and every opendps_screen_update_ms ms */ + if (last <= 0 || get_ticks() - last >= opendps_screen_update_ms) { ui_tick(); last = get_ticks(); } From ecb70ce8164a430e5fe2f00013a6835be919191a Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Mon, 7 Oct 2019 19:58:03 -0600 Subject: [PATCH 143/175] Pulled in missing refresh changes from dpsmode --- opendps/opendps.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/opendps/opendps.c b/opendps/opendps.c index 21431b18..b6625d21 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -629,13 +629,6 @@ static void ui_tick(void) static uint64_t last_tft_flash = 0; static uint64_t last_lock_flash = 0; - static uint64_t last = 0; - /** Update on the first call and every opendps_screen_update_ms ms */ - if (last > 0 && get_ticks() - last < opendps_screen_update_ms) { - return; - } - - last = get_ticks(); uui_tick(current_ui); uui_tick(&main_ui); @@ -966,12 +959,19 @@ static void check_master_reset(void) */ static void event_handler(void) { + static uint64_t last = 0; + while(1) { event_t event; uint8_t data = 0; if (!event_get(&event, &data)) { hw_longpress_check(); - ui_tick(); + + // update every opendps_screen_update_ms + if (last <= 0 || get_ticks() - last >= opendps_screen_update_ms) { + ui_tick(); + last = get_ticks(); + } } else { if (event) { emu_printf(" Event %d 0x%02x\n", event, data); @@ -989,6 +989,7 @@ static void event_handler(void) break; } ui_handle_event(event, data); + ui_tick(); } } } From 85c3e6a34ca80a4f24cebde2a925dd68974efdc2 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Mon, 7 Oct 2019 20:10:13 -0600 Subject: [PATCH 144/175] Ensure pressing rot will still work in single edit or select mode --- opendps/func_dpsmode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 5a86d211..89a9d948 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -645,7 +645,7 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { // Let parent handle event if we are in single edit mode, or select mode // This is to avoid interfereing with existing edit selection if (single_edit_mode || select_mode) { - return true; + return false; } // Otherwise, if we have a valid third item and not in any edit mode From 6512ac70924cbf91ab9aeaa50590d59ba0eb09d9 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Wed, 9 Oct 2019 22:21:10 -0600 Subject: [PATCH 145/175] Added decimilli unit 10^-4 due to lack of precision with just 10^-3 --- opendps/func_settings.c | 49 +++++++++++++++++++++-------------------- opendps/uui.h | 1 + 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index c078af60..9873a6f8 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -184,11 +184,11 @@ ui_number_t settings_field[] = { .pad_dot = false, .color = WHITE, .value = 0, - .min = -999999, - .max = 999999, - .si_prefix = si_milli, + .min = -9999999, + .max = 9999999, + .si_prefix = si_decimilli, .num_digits = 3, - .num_decimals = 3, + .num_decimals = 4, .unit = unit_none, .changed = &field_changed, }, @@ -205,11 +205,11 @@ ui_number_t settings_field[] = { .pad_dot = false, .color = WHITE, .value = 0, - .min = -999999, - .max = 999999, - .si_prefix = si_milli, + .min = -9999999, + .max = 9999999, + .si_prefix = si_decimilli, .num_digits = 3, - .num_decimals = 3, + .num_decimals = 4, .unit = unit_none, .changed = &field_changed, }, @@ -226,11 +226,11 @@ ui_number_t settings_field[] = { .pad_dot = false, .color = WHITE, .value = 0, - .min = -999999, - .max = 999999, - .si_prefix = si_milli, + .min = -9999999, + .max = 9999999, + .si_prefix = si_decimilli, .num_digits = 3, - .num_decimals = 3, + .num_decimals = 4, .unit = unit_none, .changed = &field_changed, }, @@ -247,11 +247,11 @@ ui_number_t settings_field[] = { .pad_dot = false, .color = WHITE, .value = 0, - .min = -999999, - .max = 999999, - .si_prefix = si_milli, + .min = -9999999, + .max = 9999999, + .si_prefix = si_decimilli, .num_digits = 3, - .num_decimals = 3, + .num_decimals = 4, .unit = unit_none, .changed = &field_changed, }, @@ -268,11 +268,11 @@ ui_number_t settings_field[] = { .pad_dot = false, .color = WHITE, .value = 0, - .min = -999999, - .max = 999999, - .si_prefix = si_milli, + .min = -9999999, + .max = 9999999, + .si_prefix = si_decimilli, .num_digits = 3, - .num_decimals = 3, + .num_decimals = 4, .unit = unit_none, .changed = &field_changed, }, @@ -289,11 +289,11 @@ ui_number_t settings_field[] = { .pad_dot = false, .color = WHITE, .value = 0, - .min = -999999, - .max = 999999, - .si_prefix = si_milli, + .min = -9999999, + .max = 9999999, + .si_prefix = si_decimilli, .num_digits = 3, - .num_decimals = 3, + .num_decimals = 4, .unit = unit_none, .changed = &field_changed, } @@ -679,6 +679,7 @@ static void deactivated() { } static void settings_enable(bool enabled) { + (void)enabled; } /** diff --git a/opendps/uui.h b/opendps/uui.h index dafbe602..aeda80ce 100644 --- a/opendps/uui.h +++ b/opendps/uui.h @@ -75,6 +75,7 @@ typedef enum { */ typedef enum { si_micro = -6, + si_decimilli = -4, si_milli = -3, si_centi = -2, si_deci = -1, From 54dfbc2c755aba2846d50a3697f24d2db63be369 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Wed, 9 Oct 2019 23:46:32 -0600 Subject: [PATCH 146/175] Placed all fields into an array of struct --- opendps/func_settings.c | 193 ++++++++++++++++++---------------------- opendps/func_settings.h | 2 - 2 files changed, 88 insertions(+), 107 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index 9873a6f8..4c9abdc4 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -88,82 +88,50 @@ static bool select_mode; * Get/Set functions used as callbacks for all editable fields */ static int32_t get_v_adc_k(void); -static void set_v_adc_k(ui_number_t *item); +static void set_v_adc_k(struct ui_number_t *); static int32_t get_v_adc_c(void); -static void set_v_adc_c(ui_number_t *item); +static void set_v_adc_c(struct ui_number_t *); static int32_t get_v_dac_k(void); -static void set_v_dac_k(ui_number_t *item); +static void set_v_dac_k(struct ui_number_t *); static int32_t get_v_dac_c(void); -static void set_v_dac_c(ui_number_t *item); +static void set_v_dac_c(struct ui_number_t *item); static int32_t get_a_adc_k(void); -static void set_a_adc_k(ui_number_t *item); +static void set_a_adc_k(struct ui_number_t *item); static int32_t get_a_adc_c(void); -static void set_a_adc_c(ui_number_t *item); +static void set_a_adc_c(struct ui_number_t *item); static int32_t get_a_dac_k(void); -static void set_a_dac_k(ui_number_t *item); +static void set_a_dac_k(struct ui_number_t *item); static int32_t get_a_dac_c(void); -static void set_a_dac_c(ui_number_t *item); +static void set_a_dac_c(struct ui_number_t *item); static int32_t get_vin_adc_k(void); -static void set_vin_adc_k(ui_number_t *item); +static void set_vin_adc_k(struct ui_number_t *item); static int32_t get_vin_adc_c(void); -static void set_vin_adc_c(ui_number_t *item); +static void set_vin_adc_c(struct ui_number_t *item); static int32_t get_brightness(void); -static void set_brightness(ui_number_t *item); +static void set_brightness(struct ui_number_t *); static int32_t get_refresh(void); -static void set_refresh(ui_number_t *item); +static void set_refresh(struct ui_number_t *item); -/* - * Field labels - */ -const char* const field_label[] = { - "Scr-LED", - "Refresh", - "V ADC K", - "V ADC C", - "V DAC K", - "V DAC C", - "I ADC K", - "I ADC C", - "I DAC K", - "I DAC C", - "Vin ADC C", - "Vin ADC K", -}; -/* - * Field get callbacks - */ -get_func get_functions[] = { - &get_brightness, - &get_refresh, - &get_v_adc_k, - &get_v_adc_c, - &get_v_dac_k, - &get_v_dac_c, - &get_a_adc_k, - &get_a_adc_c, - &get_a_dac_k, - &get_a_dac_c, - &get_vin_adc_k, - &get_vin_adc_c, +struct field_item { + char* label; + int32_t (*get_func)(void); + void (*set_func)(struct ui_number_t *i); }; -/* - * Field set callbacks - */ -set_func set_functions[] = { - &set_brightness, - &set_refresh, - &set_v_adc_k, - &set_v_adc_c, - &set_v_dac_k, - &set_v_dac_c, - &set_a_adc_k, - &set_a_adc_c, - &set_a_dac_k, - &set_a_dac_c, - &set_vin_adc_k, - &set_vin_adc_c, +struct field_item field_items[] = { + {"Scr-LED", &get_brightness, &set_brightness }, + {"Refresh", &get_refresh, &set_refresh }, + {"V ADC K", &get_v_adc_k, &set_v_adc_k }, + {"V ADC C", &get_v_adc_c, &set_v_adc_c }, + {"V DAC K", &get_v_dac_k, &set_v_dac_k }, + {"V DAC C", &get_v_dac_c, &set_v_dac_c }, + {"I ADC K", &get_a_adc_k, &set_a_adc_k }, + {"I ADC C", &get_a_adc_c, &set_a_adc_c }, + {"I DAC K", &get_a_dac_k, &set_a_dac_k }, + {"I DAC C", &get_a_dac_c, &set_a_dac_c }, + {"Vin ADC C", &get_vin_adc_k, &set_vin_adc_k }, + {"Vin ADC K", &get_vin_adc_c, &set_vin_adc_c }, }; /* @@ -184,7 +152,7 @@ ui_number_t settings_field[] = { .pad_dot = false, .color = WHITE, .value = 0, - .min = -9999999, + .min = 0, .max = 9999999, .si_prefix = si_decimilli, .num_digits = 3, @@ -205,7 +173,7 @@ ui_number_t settings_field[] = { .pad_dot = false, .color = WHITE, .value = 0, - .min = -9999999, + .min = 0, .max = 9999999, .si_prefix = si_decimilli, .num_digits = 3, @@ -226,7 +194,7 @@ ui_number_t settings_field[] = { .pad_dot = false, .color = WHITE, .value = 0, - .min = -9999999, + .min = 0, .max = 9999999, .si_prefix = si_decimilli, .num_digits = 3, @@ -247,7 +215,7 @@ ui_number_t settings_field[] = { .pad_dot = false, .color = WHITE, .value = 0, - .min = -9999999, + .min = 0, .max = 9999999, .si_prefix = si_decimilli, .num_digits = 3, @@ -268,7 +236,7 @@ ui_number_t settings_field[] = { .pad_dot = false, .color = WHITE, .value = 0, - .min = -9999999, + .min = 0, .max = 9999999, .si_prefix = si_decimilli, .num_digits = 3, @@ -289,7 +257,7 @@ ui_number_t settings_field[] = { .pad_dot = false, .color = WHITE, .value = 0, - .min = -9999999, + .min = 0, .max = 9999999, .si_prefix = si_decimilli, .num_digits = 3, @@ -310,7 +278,7 @@ ui_screen_t settings_screen = { .icon_data_len = sizeof(gfx_crosshair), .icon_width = GFX_CROSSHAIR_WIDTH, .icon_height = GFX_CROSSHAIR_HEIGHT, - .event = event, + .event = &event, .activated = &activated, .deactivated = &deactivated, .enable = &settings_enable, @@ -344,8 +312,10 @@ ui_screen_t settings_screen = { * * @retval set_param_status_t status code */ -static set_param_status_t set_parameter(char *name, char *value) -{ +static set_param_status_t set_parameter(char *name, char *value) { + (void)name; + (void)value; + return ps_unknown_name; } @@ -359,6 +329,10 @@ static set_param_status_t set_parameter(char *name, char *value) * @retval set_param_status_t status code */ static set_param_status_t get_parameter(char *name, char *value, uint32_t value_len) { + (void)name; + (void)value; + (void)value_len; + return ps_unknown_name; } @@ -367,106 +341,116 @@ static set_param_status_t get_parameter(char *name, char *value, uint32_t value_ * Get / Set callback functions */ static int32_t get_v_adc_k() { - return v_adc_k_coef * 1000; + return v_adc_k_coef * 10000; } static void set_v_adc_k(ui_number_t *item) { - v_adc_k_coef = item->value / 1000.0f; + v_adc_k_coef = item->value / 10000.0f; + if (v_adc_k_coef <= 0) item->color = (item->color == RED) ? WHITE : RED; if (item->color == RED) v_adc_k_coef = - v_adc_k_coef; } static int32_t get_v_adc_c() { - return v_adc_c_coef * 1000; + return v_adc_c_coef * 10000; } static void set_v_adc_c(ui_number_t *item) { - v_adc_c_coef = item->value / 1000.0f; + v_adc_c_coef = item->value / 10000.0f; + if (v_adc_c_coef <= 0) item->color = (item->color == RED) ? WHITE : RED; if (item->color == RED) v_adc_c_coef = - v_adc_c_coef; } static int32_t get_v_dac_k() { - return v_dac_k_coef * 1000; + return v_dac_k_coef * 10000; } static void set_v_dac_k(ui_number_t *item) { - v_dac_k_coef = item->value / 1000.0f; + v_dac_k_coef = item->value / 10000.0f; + if (v_dac_k_coef <= 0) item->color = (item->color == RED) ? WHITE : RED; if (item->color == RED) v_dac_k_coef = - v_dac_k_coef; } static int32_t get_v_dac_c() { - return v_dac_c_coef * 1000; + return v_dac_c_coef * 10000; } static void set_v_dac_c(ui_number_t *item) { - v_dac_c_coef = item->value / 1000.0f; + v_dac_c_coef = item->value / 10000.0f; + if (v_dac_c_coef <= 0) item->color = (item->color == RED) ? WHITE : RED; if (item->color == RED) v_dac_c_coef = - v_dac_c_coef; } static int32_t get_a_adc_k() { - return a_adc_k_coef * 1000; + return a_adc_k_coef * 10000; } static void set_a_adc_k(ui_number_t *item) { - a_adc_k_coef = item->value / 1000.0f; + a_adc_k_coef = item->value / 10000.0f; + if (a_adc_k_coef <= 0) item->color = (item->color == RED) ? WHITE : RED; if (item->color == RED) a_adc_k_coef = - a_adc_k_coef; } static int32_t get_a_adc_c() { - return a_adc_c_coef * 1000; + return a_adc_c_coef * 10000; } static void set_a_adc_c(ui_number_t *item) { - a_adc_c_coef = item->value / 1000.0f; + a_adc_c_coef = item->value / 10000.0f; + if (a_adc_c_coef <= 0) item->color = (item->color == RED) ? WHITE : RED; if (item->color == RED) a_adc_c_coef = - a_adc_c_coef; } static int32_t get_a_dac_k() { - return a_dac_k_coef * 1000; + return a_dac_k_coef * 10000; } static void set_a_dac_k(ui_number_t *item) { - a_dac_k_coef = item->value / 1000.0f; + a_dac_k_coef = item->value / 10000.0f; + if (a_dac_k_coef <= 0) item->color = (item->color == RED) ? WHITE : RED; if (item->color == RED) a_dac_k_coef = - a_dac_k_coef; } static int32_t get_a_dac_c() { - return a_dac_c_coef * 1000; + return a_dac_c_coef * 10000; } static void set_a_dac_c(ui_number_t *item) { - a_dac_c_coef = item->value / 1000.0f; + a_dac_c_coef = item->value / 10000.0f; + if (a_dac_c_coef <= 0) item->color = (item->color == RED) ? WHITE : RED; if (item->color == RED) a_dac_c_coef = - a_dac_c_coef; } static int32_t get_vin_adc_k() { - return vin_adc_k_coef * 1000; + return vin_adc_k_coef * 10000; } static void set_vin_adc_k(ui_number_t *item) { - vin_adc_k_coef = item->value / 1000.0f; + vin_adc_k_coef = item->value / 10000.0f; + if (vin_adc_k_coef <= 0) item->color = (item->color == RED) ? WHITE : RED; if (item->color == RED) vin_adc_k_coef = - vin_adc_k_coef; } static int32_t get_vin_adc_c() { - return vin_adc_c_coef * 1000; + return vin_adc_c_coef * 10000; } static void set_vin_adc_c(ui_number_t *item) { - vin_adc_c_coef = item->value / 1000.0f; + vin_adc_c_coef = item->value / 10000.0f; + if (vin_adc_k_coef <= 0) item->color = (item->color == RED) ? WHITE : RED; if (item->color == RED) vin_adc_c_coef = - vin_adc_c_coef; } static int32_t get_brightness() { - return (hw_get_backlight() / 1.28f) * 1000; + return (hw_get_backlight() / 1.28f) * 10000; } static void set_brightness(ui_number_t *item) { - if (item->value > 100 * 1000) item->value = 100 * 1000; - if (item->value < 0) item->value = 0; + if (item->value > 100 * 10000) item->value = 100 * 10000; + if (item->value <= 0) item->value = 0; - hw_set_backlight((item->value / 1000.0f) * 1.28f); + hw_set_backlight((item->value / 10000.0f) * 1.28f); } static int32_t get_refresh() { - return opendps_screen_update_ms * 1000; + return opendps_screen_update_ms * 10000; } static void set_refresh(ui_number_t *item) { // todo: make this persistent - opendps_screen_update_ms = item->value / 1000; + opendps_screen_update_ms = item->value / 10000; // ensure sane values - if (opendps_screen_update_ms > 1000) { - opendps_screen_update_ms = 1000; + if (opendps_screen_update_ms > 10000) { + opendps_screen_update_ms = 10000; } if (opendps_screen_update_ms < 10) { opendps_screen_update_ms = 10; @@ -479,6 +463,8 @@ static void set_refresh(ui_number_t *item) { * used to keep track of where we are in the menu */ static bool event(uui_t *ui, event_t event, uint8_t data) { + (void)ui; + switch (event) { case event_button_m1: case event_button_m2: @@ -553,7 +539,7 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { // generic field change function called by all fields // the current item is used to determine the actual field being changed -static void field_changed(ui_number_t *item) { +static void field_changed(struct ui_number_t *item) { int8_t page_offset = current_page * ITEMS_PER_PAGE; if (page_offset + current_item >= ITEMS) { @@ -562,7 +548,7 @@ static void field_changed(ui_number_t *item) { } // call the appropriate set function - set_functions[page_offset + current_item](item); + field_items[page_offset + current_item].set_func(item); } /** @@ -582,7 +568,7 @@ static void set_page(int8_t page) { } // update field value using value from the get function - int32_t value = get_functions[page_offset + i](); + int32_t value = field_items[page_offset + i].get_func(); if (value < 0) { // because uui_number doesn't support signed values // color represents the sign. This is is gross hack, I know. @@ -606,9 +592,6 @@ static void settings_tick(void) { // draw each field with its corresponding label for (uint8_t i = 0; i < ITEMS_PER_PAGE; i++) { - uint16_t x = settings_field[i].ui.x; - uint16_t y = settings_field[i].ui.y; - // if greater than total number of items, clear the area if (page_offset + i >= ITEMS) { tft_fill(0 /* x */, i * ROW_HEIGHT /* y */, @@ -616,7 +599,7 @@ static void settings_tick(void) { BLACK); } else { tft_puts(FONT_FULL_SMALL, - field_label[page_offset + i], + field_items[page_offset + i].label, 0 /* x */, (i * ROW_HEIGHT) + FONT_FULL_SMALL_MAX_GLYPH_HEIGHT /* y */ , TFT_WIDTH/2, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, WHITE, false); diff --git a/opendps/func_settings.h b/opendps/func_settings.h index 27c1345c..d6d68546 100644 --- a/opendps/func_settings.h +++ b/opendps/func_settings.h @@ -27,8 +27,6 @@ #include "uui.h" -typedef void (*set_func)(struct ui_number_t *item); -typedef int32_t (*get_func)(); /** * @brief Add the SETTINGS function to the UI From dcb72144d5451c734780570400a93ed2e06ee221 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Wed, 9 Oct 2019 23:55:55 -0600 Subject: [PATCH 147/175] Added min/max to fields table --- opendps/func_settings.c | 43 +++++++++++++++++++++-------------------- opendps/func_settings.h | 1 - 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index 4c9abdc4..bc963959 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -114,24 +114,26 @@ static void set_refresh(struct ui_number_t *item); struct field_item { - char* label; - int32_t (*get_func)(void); - void (*set_func)(struct ui_number_t *i); + const char* label; + int32_t min; + int32_t max; + int32_t (*get)(void); + void (*set)(struct ui_number_t *i); }; struct field_item field_items[] = { - {"Scr-LED", &get_brightness, &set_brightness }, - {"Refresh", &get_refresh, &set_refresh }, - {"V ADC K", &get_v_adc_k, &set_v_adc_k }, - {"V ADC C", &get_v_adc_c, &set_v_adc_c }, - {"V DAC K", &get_v_dac_k, &set_v_dac_k }, - {"V DAC C", &get_v_dac_c, &set_v_dac_c }, - {"I ADC K", &get_a_adc_k, &set_a_adc_k }, - {"I ADC C", &get_a_adc_c, &set_a_adc_c }, - {"I DAC K", &get_a_dac_k, &set_a_dac_k }, - {"I DAC C", &get_a_dac_c, &set_a_dac_c }, - {"Vin ADC C", &get_vin_adc_k, &set_vin_adc_k }, - {"Vin ADC K", &get_vin_adc_c, &set_vin_adc_c }, + {"Scr-LED", 10000, 1000000, &get_brightness, &set_brightness }, + {"Refresh", 100000, 9999999, &get_refresh, &set_refresh }, + {"V ADC K", 0, 9999999, &get_v_adc_k, &set_v_adc_k }, + {"V ADC C", 0, 9999999, &get_v_adc_c, &set_v_adc_c }, + {"V DAC K", 0, 9999999, &get_v_dac_k, &set_v_dac_k }, + {"V DAC C", 0, 9999999, &get_v_dac_c, &set_v_dac_c }, + {"I ADC K", 0, 9999999, &get_a_adc_k, &set_a_adc_k }, + {"I ADC C", 0, 9999999, &get_a_adc_c, &set_a_adc_c }, + {"I DAC K", 0, 9999999, &get_a_dac_k, &set_a_dac_k }, + {"I DAC C", 0, 9999999, &get_a_dac_c, &set_a_dac_c }, + {"Vin ADC C", 0, 9999999, &get_vin_adc_k, &set_vin_adc_k }, + {"Vin ADC K", 0, 9999999, &get_vin_adc_c, &set_vin_adc_c }, }; /* @@ -435,9 +437,6 @@ static int32_t get_brightness() { return (hw_get_backlight() / 1.28f) * 10000; } static void set_brightness(ui_number_t *item) { - if (item->value > 100 * 10000) item->value = 100 * 10000; - if (item->value <= 0) item->value = 0; - hw_set_backlight((item->value / 10000.0f) * 1.28f); } @@ -445,7 +444,6 @@ static int32_t get_refresh() { return opendps_screen_update_ms * 10000; } static void set_refresh(ui_number_t *item) { - // todo: make this persistent opendps_screen_update_ms = item->value / 10000; // ensure sane values @@ -548,7 +546,7 @@ static void field_changed(struct ui_number_t *item) { } // call the appropriate set function - field_items[page_offset + current_item].set_func(item); + field_items[page_offset + current_item].set(item); } /** @@ -568,7 +566,7 @@ static void set_page(int8_t page) { } // update field value using value from the get function - int32_t value = field_items[page_offset + i].get_func(); + int32_t value = field_items[page_offset + i].get(); if (value < 0) { // because uui_number doesn't support signed values // color represents the sign. This is is gross hack, I know. @@ -578,6 +576,9 @@ static void set_page(int8_t page) { settings_field[i].value = value; settings_field[i].color = WHITE; } + + settings_field[i].min = field_items[page_offset + i].min; + settings_field[i].max = field_items[page_offset + i].max; } tft_clear(); diff --git a/opendps/func_settings.h b/opendps/func_settings.h index d6d68546..f4d6eb17 100644 --- a/opendps/func_settings.h +++ b/opendps/func_settings.h @@ -27,7 +27,6 @@ #include "uui.h" - /** * @brief Add the SETTINGS function to the UI * From dd303eebdcd3feb28aa4363d085032555a1f1f3c Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 13 Oct 2019 13:30:27 -0600 Subject: [PATCH 148/175] Removed lock icon from appearing when attempting to change screens while output is enabled --- opendps/opendps.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/opendps/opendps.c b/opendps/opendps.c index 5aaabce5..ad1d4b10 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -539,16 +539,6 @@ static void ui_handle_event(event_t event, uint8_t data) opendps_change_screen(target_screen_id); break; - case event_rot_left_set: - case event_rot_right_set: - // lock out set+rotation when power is on - if (pwrctl_vout_enabled()) { - // TODO: Show only briefly? - lock_flashing_period = LOCK_FLASHING_PERIOD; - lock_flash_counter = LOCK_FLASHING_COUNTER; - return; - } - case event_button_enable: write_past_settings(); default: From d125dab676c19c8168aabe5fffb4da52fb395845 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 13 Oct 2019 14:13:22 -0600 Subject: [PATCH 149/175] Fixed compile warnings in dpsmode --- opendps/func_dpsmode.c | 24 +++++++++++------------- opendps/uui.h | 2 +- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 89a9d948..2bcd5820 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -127,9 +127,9 @@ enum { #define YPOS_POWER (80) /* Overriding white color */ -#define COLOR_VOLTAGE GREEN -#define COLOR_AMPERAGE YELLOW -#define COLOR_WATTAGE MAGENTA +#define DPS_COLOR_VOLTAGE GREEN +#define DPS_COLOR_AMPERAGE YELLOW +#define DPS_COLOR_WATTAGE MAGENTA /* This is the definition of the voltage item in the UI */ ui_number_t dpsmode_voltage = { @@ -143,7 +143,7 @@ ui_number_t dpsmode_voltage = { .font_size = FONT_METER_LARGE, .alignment = ui_text_right_aligned, .pad_dot = false, - .color = COLOR_VOLTAGE, + .color = DPS_COLOR_VOLTAGE, .value = 0, .min = 0, .max = 0, /** Set at init, continously updated in the tick callback */ @@ -165,7 +165,7 @@ ui_number_t dpsmode_current = { .font_size = FONT_METER_LARGE, .alignment = ui_text_right_aligned, .pad_dot = false, - .color = COLOR_AMPERAGE, + .color = DPS_COLOR_AMPERAGE, .value = 0, .min = 0, .max = CONFIG_DPS_MAX_CURRENT, @@ -188,11 +188,11 @@ ui_number_t dpsmode_power = { .font_size = FONT_METER_LARGE, .alignment = ui_text_right_aligned, .pad_dot = false, - .color = COLOR_WATTAGE, + .color = DPS_COLOR_WATTAGE, .value = 0, .min = 0, .max = 0, // set at init - .si_prefix = si_micro, + .si_prefix = si_micro, // P=IV, where I is in mA and V is mV, so P is uW or 10^-6 .num_digits = 2, .num_decimals = 2, .unit = unit_watt, @@ -300,7 +300,7 @@ ui_screen_t dpsmode_screen = { { .name = "power", .unit = unit_watt, - .prefix = si_milli // or micro? + .prefix = si_micro }, { .name = {'\0'} /** Terminator */ @@ -465,7 +465,7 @@ static void power_changed(ui_number_t *item) * @param item The current item */ static void watthour_changed(ui_number_t *item) { - // + (void)item; } static void timer_changed(ui_time_t *item) { @@ -659,7 +659,7 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { case event_opp: // opp mode if ( ! single_edit_mode && ! select_mode) { - third_item = &dpsmode_power; + third_item = (ui_item_t*)&dpsmode_power; third_invalidate = true; } @@ -669,7 +669,7 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { case event_timer: // timer has counted down to zero if ( ! single_edit_mode && ! select_mode) { - third_item = &dpsmode_timer; + third_item = (ui_item_t*)&dpsmode_timer; third_invalidate = true; } @@ -870,8 +870,6 @@ static void dpsmode_tick(void) int32_t vout_actual = pwrctl_calc_vout(v_out_raw); int32_t cout_actual = pwrctl_calc_iout(i_out_raw); int32_t power_actual = vout_actual * cout_actual; - - // TODO: Issue where focus causes a brief frame where value is incorrect // Voltage setting has focus, update with the desired value and not output value if (dpsmode_voltage.ui.has_focus) { diff --git a/opendps/uui.h b/opendps/uui.h index e67ebede..5f1027bd 100644 --- a/opendps/uui.h +++ b/opendps/uui.h @@ -180,7 +180,7 @@ struct ui_screen { void (*activated)(void); /** Called when the screen is switched to */ void (*deactivated)(void); /** Called when the screen is about to be changed from */ void (*enable)(bool _enable); /** Called when the enable button is pressed */ - bool (*event)(uui_t *ui, event_t event); /** Called when an event occurs (eg. button press). Return false if unhandled so main UI can handle it */ + bool (*event)(uui_t *ui, event_t event, uint8_t data); /** Called when an event occurs (eg. button press). Return false if unhandled so main UI can handle it */ void (*tick)(void); /** Called periodically allowing the UI to do house keeping */ void (*past_save)(past_t *past); void (*past_restore)(past_t *past); From f80cb466331b6e2497c983e19a9ca032639aa37f Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 13 Oct 2019 14:22:29 -0600 Subject: [PATCH 150/175] Fixed invalid event call in uui.c Added documentation on UUI event system --- opendps/uui.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/opendps/uui.c b/opendps/uui.c index d084acd6..51a0c3d8 100644 --- a/opendps/uui.c +++ b/opendps/uui.c @@ -148,7 +148,13 @@ void uui_focus(uui_t *ui, ui_item_t *item) { focus_switch(item); } - +/** + * @brief Handles UI events that are received + * + * @param ui The user interface + * @param event The event to be handled + * @param data Extra event information such as button press long or short + */ void uui_handle_screen_event(uui_t *ui, event_t event, uint8_t data) { assert(ui); @@ -162,18 +168,21 @@ void uui_handle_screen_event(uui_t *ui, event_t event, uint8_t data) } // If the screen handled the event, do nothing. - if (ui->screens[ui->cur_screen]->event && ui->screens[ui->cur_screen]->event(ui, event)) + // Screens can override the default behavior defined below by returning true. + if (ui->screens[ui->cur_screen]->event && ui->screens[ui->cur_screen]->event(ui, event, data)) return; + // Default behavior for certain events defined here. switch(event) { + // SET + Rot rotation will change to the next/previous screen case event_rot_left_set: uui_prev_screen(ui); break; - case event_rot_right_set: uui_next_screen(ui); break; + // Rot events should be passed to focused UI elements case event_rot_left: case event_rot_right: case event_rot_press: @@ -182,12 +191,14 @@ void uui_handle_screen_event(uui_t *ui, event_t event, uint8_t data) } break; + // SET button should focus on the current UI element case event_button_sel: if (item->can_focus) { focus_switch(item); } break; + // M1 should change to the previous UI element case event_button_m1: if (item->has_focus) { ui_item_t *old_item = item; @@ -202,6 +213,7 @@ void uui_handle_screen_event(uui_t *ui, event_t event, uint8_t data) } break; + // M2 should change to the next UI element case event_button_m2: if (item->has_focus) { ui_item_t *old_item = item; @@ -216,13 +228,17 @@ void uui_handle_screen_event(uui_t *ui, event_t event, uint8_t data) } break; + // Events that should cause power to shut off and the screen disabled + // This includes the timer expiring case event_timer: + // The screen sending a shutoff event to trigger a power off case event_shutoff: + // The power button being pressed case event_button_enable: + // Or the over current/voltage/power events triggered by hardware or screen case event_ocp: case event_ovp: case event_opp: - /** If current screen can be enabled */ if (screen->enable) { if (event == event_shutoff || event == event_timer) { @@ -241,6 +257,10 @@ void uui_handle_screen_event(uui_t *ui, event_t event, uint8_t data) opendps_update_power_status(screen->is_enabled); /** @todo: move */ } break; + + // All other unhandled events do nothing. + default: + break; } } From 36216a10a4b94de43a3d937284666248df80f30b Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 13 Oct 2019 15:05:47 -0600 Subject: [PATCH 151/175] Added bool and units to table --- opendps/func_settings.c | 56 ++++++++++++++++++++++++++++++----------- opendps/func_settings.h | 7 ++++++ opendps/uui.h | 2 ++ opendps/uui_number.c | 6 +++++ 4 files changed, 57 insertions(+), 14 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index bc963959..a06f2033 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -61,6 +61,7 @@ // which page we are currently on. static int8_t current_page = 0; static int8_t current_item = 0; +static bool select_mode; /* * This is the implementation of the Settings screen. @@ -81,8 +82,6 @@ static void set_page(int8_t page); static set_param_status_t set_parameter(char *name, char *value); static set_param_status_t get_parameter(char *name, char *value, uint32_t value_len); -static bool select_mode; - /* * Get/Set functions used as callbacks for all editable fields @@ -111,29 +110,42 @@ static int32_t get_brightness(void); static void set_brightness(struct ui_number_t *); static int32_t get_refresh(void); static void set_refresh(struct ui_number_t *item); +static int32_t get_on_locked(void); +static void set_on_locked(struct ui_number_t *item); struct field_item { const char* label; int32_t min; int32_t max; + int8_t digits; + int8_t decimals; + int8_t unit; int32_t (*get)(void); void (*set)(struct ui_number_t *i); }; + +/* + * Fields that can be edited + * Ensure that ITEMS match the number of elements here + */ struct field_item field_items[] = { - {"Scr-LED", 10000, 1000000, &get_brightness, &set_brightness }, - {"Refresh", 100000, 9999999, &get_refresh, &set_refresh }, - {"V ADC K", 0, 9999999, &get_v_adc_k, &set_v_adc_k }, - {"V ADC C", 0, 9999999, &get_v_adc_c, &set_v_adc_c }, - {"V DAC K", 0, 9999999, &get_v_dac_k, &set_v_dac_k }, - {"V DAC C", 0, 9999999, &get_v_dac_c, &set_v_dac_c }, - {"I ADC K", 0, 9999999, &get_a_adc_k, &set_a_adc_k }, - {"I ADC C", 0, 9999999, &get_a_adc_c, &set_a_adc_c }, - {"I DAC K", 0, 9999999, &get_a_dac_k, &set_a_dac_k }, - {"I DAC C", 0, 9999999, &get_a_dac_c, &set_a_dac_c }, - {"Vin ADC C", 0, 9999999, &get_vin_adc_k, &set_vin_adc_k }, - {"Vin ADC K", 0, 9999999, &get_vin_adc_c, &set_vin_adc_c }, +// All values are 10^4 and usess the si_decimilli unit. +// LABEL MIN MAX DIGITS, DEC, UNIT, GET callback SET callback + {"Brightness", 10000, 1000000, 3, 0, unit_none, &get_brightness, &set_brightness }, + {"Refresh", 100000, 9999999, 3, 0, unit_ms, &get_refresh, &set_refresh }, + {"ON Locked", 0, 1000, 1, 0, unit_bool, &get_on_locked, &set_on_locked }, + {"V ADC K", 0, 9999999, 3, 4, unit_none, &get_v_adc_k, &set_v_adc_k }, + {"V ADC C", 0, 9999999, 3, 4, unit_none, &get_v_adc_c, &set_v_adc_c }, + {"V DAC K", 0, 9999999, 3, 4, unit_none, &get_v_dac_k, &set_v_dac_k }, + {"V DAC C", 0, 9999999, 3, 4, unit_none, &get_v_dac_c, &set_v_dac_c }, + {"I ADC K", 0, 9999999, 3, 4, unit_none, &get_a_adc_k, &set_a_adc_k }, + {"I ADC C", 0, 9999999, 3, 4, unit_none, &get_a_adc_c, &set_a_adc_c }, + {"I DAC K", 0, 9999999, 3, 4, unit_none, &get_a_dac_k, &set_a_dac_k }, + {"I DAC C", 0, 9999999, 3, 4, unit_none, &get_a_dac_c, &set_a_dac_c }, + {"Vin ADC C", 0, 9999999, 3, 4, unit_none, &get_vin_adc_k, &set_vin_adc_k }, + {"Vin ADC K", 0, 9999999, 3, 4, unit_none, &get_vin_adc_c, &set_vin_adc_c }, }; /* @@ -455,6 +467,19 @@ static void set_refresh(ui_number_t *item) { } } +static int32_t get_on_locked() { + return settings | SCREEN_LOCKED_WHEN_ON; +} + +static void set_on_locked(struct ui_number_t *item) { + if (item->value == 0) { + settings = settings & ~SCREEN_LOCKED_WHEN_ON; + } else { + settings = settings | SCREEN_LOCKED_WHEN_ON; + } +} + + /** * @brief event handler: We only care about the SET, M1 and M2 buttons @@ -579,6 +604,9 @@ static void set_page(int8_t page) { settings_field[i].min = field_items[page_offset + i].min; settings_field[i].max = field_items[page_offset + i].max; + settings_field[i].num_digits = field_items[page_offset + i].digits; + settings_field[i].num_decimals = field_items[page_offset + i].decimals; + settings_field[i].unit = field_items[page_offset + i].unit; } tft_clear(); diff --git a/opendps/func_settings.h b/opendps/func_settings.h index f4d6eb17..7104aba2 100644 --- a/opendps/func_settings.h +++ b/opendps/func_settings.h @@ -27,6 +27,13 @@ #include "uui.h" +// Settings +int8_t settings = 0; +typedef enum { + SCREEN_LOCKED_WHEN_ON = 1, +}; + + /** * @brief Add the SETTINGS function to the UI * diff --git a/opendps/uui.h b/opendps/uui.h index aeda80ce..9213c799 100644 --- a/opendps/uui.h +++ b/opendps/uui.h @@ -67,6 +67,8 @@ typedef enum { unit_second, unit_hertz, unit_furlong, + unit_ms, + unit_bool, unit_last = 0xff } unit_t; diff --git a/opendps/uui_number.c b/opendps/uui_number.c index 59dab21c..70e1376f 100644 --- a/opendps/uui_number.c +++ b/opendps/uui_number.c @@ -157,12 +157,14 @@ static uint32_t number_draw_width(ui_item_t *_item) /** The unit */ switch(item->unit) { case unit_none: + case unit_bool: break; case unit_volt: case unit_ampere: total_width += max_w; break; case unit_hertz: + case unit_ms: total_width += 2*FONT_FULL_SMALL_MAX_GLYPH_WIDTH; break; default: @@ -297,6 +299,7 @@ static void number_draw(ui_item_t *_item) /** The unit */ switch(item->unit) { case unit_none: + case unit_bool: break; case unit_volt: tft_putch(item->font_size, 'V', xpos, _item->y, max_w, h, color, false); @@ -307,6 +310,9 @@ static void number_draw(ui_item_t *_item) case unit_hertz: tft_puts(FONT_FULL_SMALL, "Hz", xpos, _item->y + h, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 2, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, color, false); break; + case unit_ms: + tft_puts(FONT_FULL_SMALL, "ms", xpos, _item->y + h, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 2, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, color, false); + break; default: assert(0); } From 9608a6ba72f23d1425e176626f1052672ec6c212 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 13 Oct 2019 15:09:23 -0600 Subject: [PATCH 152/175] renamed settings to ui_settings --- opendps/func_settings.c | 6 +++--- opendps/func_settings.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index a06f2033..caf72c05 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -468,14 +468,14 @@ static void set_refresh(ui_number_t *item) { } static int32_t get_on_locked() { - return settings | SCREEN_LOCKED_WHEN_ON; + return ui_settings | SCREEN_LOCKED_WHEN_ON; } static void set_on_locked(struct ui_number_t *item) { if (item->value == 0) { - settings = settings & ~SCREEN_LOCKED_WHEN_ON; + ui_settings = ui_settings & ~SCREEN_LOCKED_WHEN_ON; } else { - settings = settings | SCREEN_LOCKED_WHEN_ON; + ui_settings = ui_settings | SCREEN_LOCKED_WHEN_ON; } } diff --git a/opendps/func_settings.h b/opendps/func_settings.h index 7104aba2..2ffebf03 100644 --- a/opendps/func_settings.h +++ b/opendps/func_settings.h @@ -28,8 +28,8 @@ #include "uui.h" // Settings -int8_t settings = 0; -typedef enum { +int8_t ui_settings = 0; +enum SettingsStates { SCREEN_LOCKED_WHEN_ON = 1, }; From 69b9b40c6bfe70e9258b6e113a2ea20bad564cf7 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 13 Oct 2019 15:11:40 -0600 Subject: [PATCH 153/175] Def --- opendps/func_settings.c | 2 ++ opendps/func_settings.h | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index caf72c05..7b4abeb4 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -63,6 +63,8 @@ static int8_t current_page = 0; static int8_t current_item = 0; static bool select_mode; +int8_t ui_settings = 0; + /* * This is the implementation of the Settings screen. */ diff --git a/opendps/func_settings.h b/opendps/func_settings.h index 2ffebf03..eb9fb1f6 100644 --- a/opendps/func_settings.h +++ b/opendps/func_settings.h @@ -28,7 +28,6 @@ #include "uui.h" // Settings -int8_t ui_settings = 0; enum SettingsStates { SCREEN_LOCKED_WHEN_ON = 1, }; From b8c25832fdd1d56d3c9c9034bc1efde762ad81bb Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 13 Oct 2019 15:25:19 -0600 Subject: [PATCH 154/175] Set cur_digit --- opendps/func_settings.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index 7b4abeb4..2f7fc1ba 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -131,13 +131,18 @@ struct field_item { /* * Fields that can be edited * Ensure that ITEMS match the number of elements here + * + * Note: Min values cannot be negative because uui_number cannot handle negative numbers. + * If you want to enable the possibility for negative numbers, set the min value to 0. + * The sign can be toggled by setting a value to 0 in the UI (shown in RED for negative) + * If you do NOT want the possibility for negative numbers, set the min value to a non-zero value. */ struct field_item field_items[] = { // All values are 10^4 and usess the si_decimilli unit. // LABEL MIN MAX DIGITS, DEC, UNIT, GET callback SET callback {"Brightness", 10000, 1000000, 3, 0, unit_none, &get_brightness, &set_brightness }, - {"Refresh", 100000, 9999999, 3, 0, unit_ms, &get_refresh, &set_refresh }, - {"ON Locked", 0, 1000, 1, 0, unit_bool, &get_on_locked, &set_on_locked }, + {"Refresh", 100000, 9990000, 3, 0, unit_ms, &get_refresh, &set_refresh }, + {"ON Locked", 0, 10000, 1, 0, unit_bool, &get_on_locked, &set_on_locked }, {"V ADC K", 0, 9999999, 3, 4, unit_none, &get_v_adc_k, &set_v_adc_k }, {"V ADC C", 0, 9999999, 3, 4, unit_none, &get_v_adc_c, &set_v_adc_c }, {"V DAC K", 0, 9999999, 3, 4, unit_none, &get_v_dac_k, &set_v_dac_k }, @@ -470,7 +475,10 @@ static void set_refresh(ui_number_t *item) { } static int32_t get_on_locked() { - return ui_settings | SCREEN_LOCKED_WHEN_ON; + if (ui_settings | SCREEN_LOCKED_WHEN_ON) { + return 10000; + } + return 0; } static void set_on_locked(struct ui_number_t *item) { @@ -609,6 +617,8 @@ static void set_page(int8_t page) { settings_field[i].num_digits = field_items[page_offset + i].digits; settings_field[i].num_decimals = field_items[page_offset + i].decimals; settings_field[i].unit = field_items[page_offset + i].unit; + // cur_digit may be wrongg after changing digits and decimals, updating it once more: + settings_field[i].cur_digit = field_items[page_offset + i].digits + field_items[page_offset + i].decimals - 1; } tft_clear(); From 0facb58eb4a983c0d32aef4194d3ebe0d32ef12f Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 13 Oct 2019 15:34:15 -0600 Subject: [PATCH 155/175] Boolean --- opendps/func_settings.c | 3 ++- opendps/uui_number.c | 11 +++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index 2f7fc1ba..8483bec0 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -142,7 +142,8 @@ struct field_item field_items[] = { // LABEL MIN MAX DIGITS, DEC, UNIT, GET callback SET callback {"Brightness", 10000, 1000000, 3, 0, unit_none, &get_brightness, &set_brightness }, {"Refresh", 100000, 9990000, 3, 0, unit_ms, &get_refresh, &set_refresh }, - {"ON Locked", 0, 10000, 1, 0, unit_bool, &get_on_locked, &set_on_locked }, + // lock screen when output enabled + {"LockScrEn", 0, 10000, 1, 0, unit_bool, &get_on_locked, &set_on_locked }, {"V ADC K", 0, 9999999, 3, 4, unit_none, &get_v_adc_k, &set_v_adc_k }, {"V ADC C", 0, 9999999, 3, 4, unit_none, &get_v_adc_c, &set_v_adc_c }, {"V DAC K", 0, 9999999, 3, 4, unit_none, &get_v_dac_k, &set_v_dac_k }, diff --git a/opendps/uui_number.c b/opendps/uui_number.c index 70e1376f..bf7d9177 100644 --- a/opendps/uui_number.c +++ b/opendps/uui_number.c @@ -157,7 +157,6 @@ static uint32_t number_draw_width(ui_item_t *_item) /** The unit */ switch(item->unit) { case unit_none: - case unit_bool: break; case unit_volt: case unit_ampere: @@ -167,6 +166,9 @@ static uint32_t number_draw_width(ui_item_t *_item) case unit_ms: total_width += 2*FONT_FULL_SMALL_MAX_GLYPH_WIDTH; break; + case unit_bool: + total_width += 3*FONT_FULL_SMALL_MAX_GLYPH_WIDTH; + break; default: assert(0); } @@ -299,7 +301,6 @@ static void number_draw(ui_item_t *_item) /** The unit */ switch(item->unit) { case unit_none: - case unit_bool: break; case unit_volt: tft_putch(item->font_size, 'V', xpos, _item->y, max_w, h, color, false); @@ -313,6 +314,12 @@ static void number_draw(ui_item_t *_item) case unit_ms: tft_puts(FONT_FULL_SMALL, "ms", xpos, _item->y + h, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 2, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, color, false); break; + case unit_bool: + if (item->value > 0) + tft_puts(FONT_FULL_SMALL, "ON", xpos, _item->y + h, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 3, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, GREEN, false); + else + tft_puts(FONT_FULL_SMALL, "OFF", xpos, _item->y + h, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 3, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, RED, false); + break; default: assert(0); } From 0e5acfb00e023b28d53eb213e219dce102d1b2d6 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 13 Oct 2019 15:47:38 -0600 Subject: [PATCH 156/175] ON spacing --- opendps/func_settings.c | 59 +++++++++++++++++++++++++++++------------ opendps/uui_number.c | 2 +- 2 files changed, 43 insertions(+), 18 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index 8483bec0..321e28f8 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -42,14 +42,36 @@ #define SCREEN_ID (7) +/* + * The settings screen is layed out as a series of rows of labels and values + * that can be paged using the existing UI subsystem. + * + * Label Value + * ------------------------- + * | Brightness 100% | <- first field / uui_number + * | Refresh Rate 100ms | + * | V ADC K 13.0000 | ... + * | V ADC C 13.0000 | + * | V DAC K 13.0000 | + * | V DAC C 13.0000 | <- sixth field / uui_number + * ------------------------- + * + * When a value is set, it calls the set function callback in order to do something. + * Values cannot be 'negative' because uui_number does not support it. Instead, the + * set callback function will use the field color as the sign. RED values are treated + * as negative numbers while WHITE numbers are positive. + * + */ + + // Number of fields shown per page #define ITEMS_PER_PAGE 6 // Total number of fields that can be edited -#define ITEMS 12 +#define ITEMS 13 // PAGES = ceil(ITEMS / ITEMS_PER_PAGE) -#define PAGES 2 +#define PAGES (ITEMS+(ITEMS_PER_PAGE-1))/ITEMS_PER_PAGE // UI Row height in pixels #define ROW_HEIGHT 17 @@ -139,26 +161,29 @@ struct field_item { */ struct field_item field_items[] = { // All values are 10^4 and usess the si_decimilli unit. -// LABEL MIN MAX DIGITS, DEC, UNIT, GET callback SET callback - {"Brightness", 10000, 1000000, 3, 0, unit_none, &get_brightness, &set_brightness }, - {"Refresh", 100000, 9990000, 3, 0, unit_ms, &get_refresh, &set_refresh }, +// LABEL MIN MAX DIGITS, DEC, UNIT, GET callback SET callback + {"Brightness", 10000, 1000000, 3, 0, unit_none, &get_brightness, &set_brightness }, // TODO: Set this to unit_percent from dpsmode PR + {"Refresh Rate", 100000, 9990000, 3, 0, unit_ms, &get_refresh, &set_refresh }, + // lock screen when output enabled - {"LockScrEn", 0, 10000, 1, 0, unit_bool, &get_on_locked, &set_on_locked }, - {"V ADC K", 0, 9999999, 3, 4, unit_none, &get_v_adc_k, &set_v_adc_k }, - {"V ADC C", 0, 9999999, 3, 4, unit_none, &get_v_adc_c, &set_v_adc_c }, - {"V DAC K", 0, 9999999, 3, 4, unit_none, &get_v_dac_k, &set_v_dac_k }, - {"V DAC C", 0, 9999999, 3, 4, unit_none, &get_v_dac_c, &set_v_dac_c }, - {"I ADC K", 0, 9999999, 3, 4, unit_none, &get_a_adc_k, &set_a_adc_k }, - {"I ADC C", 0, 9999999, 3, 4, unit_none, &get_a_adc_c, &set_a_adc_c }, - {"I DAC K", 0, 9999999, 3, 4, unit_none, &get_a_dac_k, &set_a_dac_k }, - {"I DAC C", 0, 9999999, 3, 4, unit_none, &get_a_dac_c, &set_a_dac_c }, - {"Vin ADC C", 0, 9999999, 3, 4, unit_none, &get_vin_adc_k, &set_vin_adc_k }, - {"Vin ADC K", 0, 9999999, 3, 4, unit_none, &get_vin_adc_c, &set_vin_adc_c }, + {"LockScr-PwrEn", 0, 10000, 1, 0, unit_bool, &get_on_locked, &set_on_locked }, + + // constants + {"V ADC K", 0, 9999999, 3, 4, unit_none, &get_v_adc_k, &set_v_adc_k }, + {"V ADC C", 0, 9999999, 3, 4, unit_none, &get_v_adc_c, &set_v_adc_c }, + {"V DAC K", 0, 9999999, 3, 4, unit_none, &get_v_dac_k, &set_v_dac_k }, + {"V DAC C", 0, 9999999, 3, 4, unit_none, &get_v_dac_c, &set_v_dac_c }, + {"I ADC K", 0, 9999999, 3, 4, unit_none, &get_a_adc_k, &set_a_adc_k }, + {"I ADC C", 0, 9999999, 3, 4, unit_none, &get_a_adc_c, &set_a_adc_c }, + {"I DAC K", 0, 9999999, 3, 4, unit_none, &get_a_dac_k, &set_a_dac_k }, + {"I DAC C", 0, 9999999, 3, 4, unit_none, &get_a_dac_c, &set_a_dac_c }, + {"Vin ADC C", 0, 9999999, 3, 4, unit_none, &get_vin_adc_k, &set_vin_adc_k }, + {"Vin ADC K", 0, 9999999, 3, 4, unit_none, &get_vin_adc_c, &set_vin_adc_c }, }; /* * Field UI elements - * One for each row + * One field for each row */ ui_number_t settings_field[] = { { diff --git a/opendps/uui_number.c b/opendps/uui_number.c index bf7d9177..1f564a6c 100644 --- a/opendps/uui_number.c +++ b/opendps/uui_number.c @@ -316,7 +316,7 @@ static void number_draw(ui_item_t *_item) break; case unit_bool: if (item->value > 0) - tft_puts(FONT_FULL_SMALL, "ON", xpos, _item->y + h, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 3, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, GREEN, false); + tft_puts(FONT_FULL_SMALL, " ON", xpos, _item->y + h, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 3, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, GREEN, false); else tft_puts(FONT_FULL_SMALL, "OFF", xpos, _item->y + h, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 3, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, RED, false); break; From 6358c19a5a2dea07e70d289b7ef22717ece3d536 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 13 Oct 2019 15:55:22 -0600 Subject: [PATCH 157/175] Moved enable lock down to 3rd page --- opendps/func_settings.c | 8 ++++---- opendps/uui_number.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index 321e28f8..05037dc8 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -163,10 +163,7 @@ struct field_item field_items[] = { // All values are 10^4 and usess the si_decimilli unit. // LABEL MIN MAX DIGITS, DEC, UNIT, GET callback SET callback {"Brightness", 10000, 1000000, 3, 0, unit_none, &get_brightness, &set_brightness }, // TODO: Set this to unit_percent from dpsmode PR - {"Refresh Rate", 100000, 9990000, 3, 0, unit_ms, &get_refresh, &set_refresh }, - - // lock screen when output enabled - {"LockScr-PwrEn", 0, 10000, 1, 0, unit_bool, &get_on_locked, &set_on_locked }, + {"Refresh", 100000, 9990000, 3, 0, unit_ms, &get_refresh, &set_refresh }, // constants {"V ADC K", 0, 9999999, 3, 4, unit_none, &get_v_adc_k, &set_v_adc_k }, @@ -179,6 +176,9 @@ struct field_item field_items[] = { {"I DAC C", 0, 9999999, 3, 4, unit_none, &get_a_dac_c, &set_a_dac_c }, {"Vin ADC C", 0, 9999999, 3, 4, unit_none, &get_vin_adc_k, &set_vin_adc_k }, {"Vin ADC K", 0, 9999999, 3, 4, unit_none, &get_vin_adc_c, &set_vin_adc_c }, + + // lock screen when output enabled + {"LockScr-En", 0, 10000, 1, 0, unit_bool, &get_on_locked, &set_on_locked }, }; /* diff --git a/opendps/uui_number.c b/opendps/uui_number.c index 1f564a6c..e8f4c1dd 100644 --- a/opendps/uui_number.c +++ b/opendps/uui_number.c @@ -316,9 +316,9 @@ static void number_draw(ui_item_t *_item) break; case unit_bool: if (item->value > 0) - tft_puts(FONT_FULL_SMALL, " ON", xpos, _item->y + h, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 3, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, GREEN, false); + tft_puts(FONT_FULL_SMALL, " ON ", xpos, _item->y + h, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 3, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, GREEN, false); else - tft_puts(FONT_FULL_SMALL, "OFF", xpos, _item->y + h, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 3, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, RED, false); + tft_puts(FONT_FULL_SMALL, "OFF ", xpos, _item->y + h, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 3, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, RED, false); break; default: assert(0); From b462f6a51c5105cd71955ca171cf43fe80219e78 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 13 Oct 2019 16:02:08 -0600 Subject: [PATCH 158/175] Added field digits, decimals and unit types Added boolean to uui_c Squashed commit of the following: commit 6358c19a5a2dea07e70d289b7ef22717ece3d536 Author: Leo Leung Date: Sun Oct 13 15:55:22 2019 -0600 Moved enable lock down to 3rd page commit 0e5acfb00e023b28d53eb213e219dce102d1b2d6 Author: Leo Leung Date: Sun Oct 13 15:47:38 2019 -0600 ON spacing commit 0facb58eb4a983c0d32aef4194d3ebe0d32ef12f Author: Leo Leung Date: Sun Oct 13 15:34:15 2019 -0600 Boolean commit b8c25832fdd1d56d3c9c9034bc1efde762ad81bb Author: Leo Leung Date: Sun Oct 13 15:25:19 2019 -0600 Set cur_digit commit 69b9b40c6bfe70e9258b6e113a2ea20bad564cf7 Author: Leo Leung Date: Sun Oct 13 15:11:40 2019 -0600 Def commit 9608a6ba72f23d1425e176626f1052672ec6c212 Author: Leo Leung Date: Sun Oct 13 15:09:23 2019 -0600 renamed settings to ui_settings commit 36216a10a4b94de43a3d937284666248df80f30b Author: Leo Leung Date: Sun Oct 13 15:05:47 2019 -0600 Added bool and units to table --- opendps/func_settings.c | 77 ++++++++++++++++++++++++++++++++--------- opendps/uui.h | 2 ++ opendps/uui_number.c | 13 +++++++ 3 files changed, 76 insertions(+), 16 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index bc963959..652c9f9f 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -42,6 +42,28 @@ #define SCREEN_ID (7) +/* + * The settings screen is layed out as a series of rows of labels and values + * that can be paged using the existing UI subsystem. + * + * Label Value + * ------------------------- + * | Brightness 100% | <- first field / uui_number + * | Refresh Rate 100ms | + * | V ADC K 13.0000 | ... + * | V ADC C 13.0000 | + * | V DAC K 13.0000 | + * | V DAC C 13.0000 | <- sixth field / uui_number + * ------------------------- + * + * When a value is set, it calls the set function callback in order to do something. + * Values cannot be 'negative' because uui_number does not support it. Instead, the + * set callback function will use the field color as the sign. RED values are treated + * as negative numbers while WHITE numbers are positive. + * + */ + + // Number of fields shown per page #define ITEMS_PER_PAGE 6 @@ -49,7 +71,7 @@ #define ITEMS 12 // PAGES = ceil(ITEMS / ITEMS_PER_PAGE) -#define PAGES 2 +#define PAGES (ITEMS+(ITEMS_PER_PAGE-1))/ITEMS_PER_PAGE // UI Row height in pixels #define ROW_HEIGHT 17 @@ -61,6 +83,9 @@ // which page we are currently on. static int8_t current_page = 0; static int8_t current_item = 0; +static bool select_mode; + +int8_t ui_settings = 0; /* * This is the implementation of the Settings screen. @@ -81,8 +106,6 @@ static void set_page(int8_t page); static set_param_status_t set_parameter(char *name, char *value); static set_param_status_t get_parameter(char *name, char *value, uint32_t value_len); -static bool select_mode; - /* * Get/Set functions used as callbacks for all editable fields @@ -117,28 +140,45 @@ struct field_item { const char* label; int32_t min; int32_t max; + int8_t digits; + int8_t decimals; + int8_t unit; int32_t (*get)(void); void (*set)(struct ui_number_t *i); }; + +/* + * Fields that can be edited + * Ensure that ITEMS match the number of elements here + * + * Note: Min values cannot be negative because uui_number cannot handle negative numbers. + * If you want to enable the possibility for negative numbers, set the min value to 0. + * The sign can be toggled by setting a value to 0 in the UI (shown in RED for negative) + * If you do NOT want the possibility for negative numbers, set the min value to a non-zero value. + */ struct field_item field_items[] = { - {"Scr-LED", 10000, 1000000, &get_brightness, &set_brightness }, - {"Refresh", 100000, 9999999, &get_refresh, &set_refresh }, - {"V ADC K", 0, 9999999, &get_v_adc_k, &set_v_adc_k }, - {"V ADC C", 0, 9999999, &get_v_adc_c, &set_v_adc_c }, - {"V DAC K", 0, 9999999, &get_v_dac_k, &set_v_dac_k }, - {"V DAC C", 0, 9999999, &get_v_dac_c, &set_v_dac_c }, - {"I ADC K", 0, 9999999, &get_a_adc_k, &set_a_adc_k }, - {"I ADC C", 0, 9999999, &get_a_adc_c, &set_a_adc_c }, - {"I DAC K", 0, 9999999, &get_a_dac_k, &set_a_dac_k }, - {"I DAC C", 0, 9999999, &get_a_dac_c, &set_a_dac_c }, - {"Vin ADC C", 0, 9999999, &get_vin_adc_k, &set_vin_adc_k }, - {"Vin ADC K", 0, 9999999, &get_vin_adc_c, &set_vin_adc_c }, +// All values are 10^4 and usess the si_decimilli unit. +// LABEL MIN MAX DIGITS, DEC, UNIT, GET callback SET callback + {"Brightness", 10000, 1000000, 3, 0, unit_none, &get_brightness, &set_brightness }, // TODO: Set this to unit_percent from dpsmode PR + {"Refresh", 100000, 9990000, 3, 0, unit_ms, &get_refresh, &set_refresh }, + + // constants + {"V ADC K", 0, 9999999, 3, 4, unit_none, &get_v_adc_k, &set_v_adc_k }, + {"V ADC C", 0, 9999999, 3, 4, unit_none, &get_v_adc_c, &set_v_adc_c }, + {"V DAC K", 0, 9999999, 3, 4, unit_none, &get_v_dac_k, &set_v_dac_k }, + {"V DAC C", 0, 9999999, 3, 4, unit_none, &get_v_dac_c, &set_v_dac_c }, + {"I ADC K", 0, 9999999, 3, 4, unit_none, &get_a_adc_k, &set_a_adc_k }, + {"I ADC C", 0, 9999999, 3, 4, unit_none, &get_a_adc_c, &set_a_adc_c }, + {"I DAC K", 0, 9999999, 3, 4, unit_none, &get_a_dac_k, &set_a_dac_k }, + {"I DAC C", 0, 9999999, 3, 4, unit_none, &get_a_dac_c, &set_a_dac_c }, + {"Vin ADC C", 0, 9999999, 3, 4, unit_none, &get_vin_adc_k, &set_vin_adc_k }, + {"Vin ADC K", 0, 9999999, 3, 4, unit_none, &get_vin_adc_c, &set_vin_adc_c }, }; /* * Field UI elements - * One for each row + * One field for each row */ ui_number_t settings_field[] = { { @@ -579,6 +619,11 @@ static void set_page(int8_t page) { settings_field[i].min = field_items[page_offset + i].min; settings_field[i].max = field_items[page_offset + i].max; + settings_field[i].num_digits = field_items[page_offset + i].digits; + settings_field[i].num_decimals = field_items[page_offset + i].decimals; + settings_field[i].unit = field_items[page_offset + i].unit; + // cur_digit may be wrongg after changing digits and decimals, updating it once more: + settings_field[i].cur_digit = field_items[page_offset + i].digits + field_items[page_offset + i].decimals - 1; } tft_clear(); diff --git a/opendps/uui.h b/opendps/uui.h index aeda80ce..9213c799 100644 --- a/opendps/uui.h +++ b/opendps/uui.h @@ -67,6 +67,8 @@ typedef enum { unit_second, unit_hertz, unit_furlong, + unit_ms, + unit_bool, unit_last = 0xff } unit_t; diff --git a/opendps/uui_number.c b/opendps/uui_number.c index 59dab21c..e8f4c1dd 100644 --- a/opendps/uui_number.c +++ b/opendps/uui_number.c @@ -163,8 +163,12 @@ static uint32_t number_draw_width(ui_item_t *_item) total_width += max_w; break; case unit_hertz: + case unit_ms: total_width += 2*FONT_FULL_SMALL_MAX_GLYPH_WIDTH; break; + case unit_bool: + total_width += 3*FONT_FULL_SMALL_MAX_GLYPH_WIDTH; + break; default: assert(0); } @@ -307,6 +311,15 @@ static void number_draw(ui_item_t *_item) case unit_hertz: tft_puts(FONT_FULL_SMALL, "Hz", xpos, _item->y + h, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 2, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, color, false); break; + case unit_ms: + tft_puts(FONT_FULL_SMALL, "ms", xpos, _item->y + h, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 2, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, color, false); + break; + case unit_bool: + if (item->value > 0) + tft_puts(FONT_FULL_SMALL, " ON ", xpos, _item->y + h, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 3, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, GREEN, false); + else + tft_puts(FONT_FULL_SMALL, "OFF ", xpos, _item->y + h, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 3, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, RED, false); + break; default: assert(0); } From 73d3c8cc201438ccc79153815b8cfccb94d0e713 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Wed, 16 Oct 2019 19:00:40 -0600 Subject: [PATCH 159/175] Rewrote the digit drawing algorithm --- opendps/uui_number.c | 59 ++++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/opendps/uui_number.c b/opendps/uui_number.c index 59dab21c..916b9a3a 100644 --- a/opendps/uui_number.c +++ b/opendps/uui_number.c @@ -234,46 +234,47 @@ static void number_draw(ui_item_t *_item) xpos -= number_draw_width(_item); /** Start printing from left to right */ + for (uint8_t cur_digit = 0; cur_digit < item->num_digits - 1; cur_digit++) { + /* Example: + 01000 num_digits = 5 + 01234 cur_digit + 54321 values place + */ - /** Digits before the decimal point */ - for (uint32_t i = item->num_digits - 1; i < item->num_digits; --i) { + // values place + uint8_t place = item->num_digits - cur_digit; + + // this place value (1 = 1, 2 = 10, 3 = 100, etc., for si_prefix = 0) + uint32_t power = my_pow(10, (item->si_prefix * -1) + place - 1); + + // current digit value + uint8_t digit = (item->value / power) % 10; + + // digit selected bool highlight = _item->has_focus && item->cur_digit == cur_digit; - uint8_t digit = item->value / my_pow(10, (item->si_prefix * -1) + i) % 10; - if (!digit /** If current digit is a 0 */ - && !_item->has_focus /** and its not in focus (selected) */ - && cur_digit != item->num_decimals /** to prevent 0.123 becoming .123 */ - && my_pow(10, cur_digit + (item->si_prefix * -1)) > (uint32_t) item->value) /** to prevent 4023 becoming 4 23 */ - { - /** To prevent from printing 00.123 */ - /** Black out any 0 that has previously been printed */ - if (spacing > 1) - { - tft_fill(xpos, _item->y, digit_w, h, BLACK); - tft_rect(xpos-1, _item->y-1, digit_w+1, h+1, BLACK); /** Remove any potential frame highlight */ + // Draw the background only if spacing is > 1 + if (spacing > 1) { + if (highlight) { + tft_rect(xpos-1, _item->y-1, digit_w+1, h+1, WHITE); + } else { + tft_rect(xpos-1, _item->y-1, digit_w+1, h+1, BLACK); } - else - tft_fill(xpos, _item->y, digit_w, h, BLACK); /** Black out any 0 that has previously been printed */ } - else - { - if (spacing > 1) /** Dont frame tiny fonts */ - { - if (highlight) /** Draw an extra pixel wide border around the highlighted item */ - tft_rect(xpos-1, _item->y-1, digit_w+1, h+1, WHITE); - else - tft_rect(xpos-1, _item->y-1, digit_w+1, h+1, BLACK); - } + + // Draw the digit, Only if value >= this place's min value (digit's power) + // this prevents the drawing of leading 0's by skipping values that are smaller than that number's place + if (item->value >= power) { + // ASCII '0' plus digit value for digit ascii offset tft_putch(item->font_size, '0' + digit, xpos, _item->y, digit_w, h, color, highlight); } - cur_digit--; + // next digit position xpos += digit_w + spacing; } - /** Draw the decimal point if there is decimal places */ - if (item->num_decimals) - { + /** Draw the decimal point if there are decimal places */ + if (item->num_decimals) { tft_putch(item->font_size, '.', xpos, _item->y, dot_width, h, color, false); xpos += dot_width + spacing; } From 7119f77d8f39ce93739715357cd113977b15fa99 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 1 Nov 2020 11:38:58 -0700 Subject: [PATCH 160/175] Fixed digit rendering in uui_number.c --- opendps/uui_number.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/opendps/uui_number.c b/opendps/uui_number.c index 75663ac0..bac184d3 100644 --- a/opendps/uui_number.c +++ b/opendps/uui_number.c @@ -243,26 +243,25 @@ static void number_draw(ui_item_t *_item) xpos -= number_draw_width(_item); /** Start printing from left to right */ - for (uint8_t cur_digit = 0; cur_digit < item->num_digits - 1; cur_digit++) { - /* Example: - 01000 num_digits = 5 - 01234 cur_digit - 54321 values place + for (uint8_t place = item->num_digits; place > 0; place--) { + /* Example value of 1000 with 5,2: + 01000 . 00 num_digits = 5, num_decimals = 2 + 54321 values place + 65432 . 10 cur_digit */ - // values place - uint8_t place = item->num_digits - cur_digit; + // current digit + cur_digit = place + item->num_decimals - 1; // this place value (1 = 1, 2 = 10, 3 = 100, etc., for si_prefix = 0) - uint32_t power = my_pow(10, (item->si_prefix * -1) + place - 1); + int32_t power = my_pow(10, (item->si_prefix * -1) + (place - 1)); - // current digit value uint8_t digit = (item->value / power) % 10; // digit selected bool highlight = _item->has_focus && item->cur_digit == cur_digit; - // Draw the background only if spacing is > 1 + // Draw background either black, or a highlighted box if (spacing > 1) { if (highlight) { tft_rect(xpos-1, _item->y-1, digit_w+1, h+1, WHITE); @@ -271,11 +270,15 @@ static void number_draw(ui_item_t *_item) } } - // Draw the digit, Only if value >= this place's min value (digit's power) - // this prevents the drawing of leading 0's by skipping values that are smaller than that number's place - if (item->value >= power) { + // Draw the digit, Only if: + // value >= this place's min value (ie. digit's power) + // in one's place (ensuring 0.xxx has leading 0) + // or item has focus (ensures all digits are drawn when focused) + if (item->value >= power || place == 1 || _item->has_focus) { // ASCII '0' plus digit value for digit ascii offset tft_putch(item->font_size, '0' + digit, xpos, _item->y, digit_w, h, color, highlight); + } else { + tft_fill(xpos, _item->y, digit_w, h, BLACK); } // next digit position @@ -289,6 +292,8 @@ static void number_draw(ui_item_t *_item) } /** Digits after the decimal point */ + cur_digit = item->num_decimals - 1; + for (uint32_t i = 0; i < item->num_decimals; ++i) { bool highlight = _item->has_focus && item->cur_digit == cur_digit; uint8_t digit = item->value / my_pow(10, (item->si_prefix * -1) -1 - i) % 10; From b85615881a02376e9c7a22b3bfc760b17624910c Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Fri, 21 May 2021 06:58:56 +0000 Subject: [PATCH 161/175] func_cv.o removed from default list of objects to link This should only be included if the CV option is enabled. --- opendps/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/opendps/Makefile b/opendps/Makefile index d058d3d1..c57e34c8 100644 --- a/opendps/Makefile +++ b/opendps/Makefile @@ -100,7 +100,6 @@ OBJS = \ uui.o \ uui_number.o \ uui_time.o \ - func_cv.o \ settings_calibration.o \ hw.o \ pwrctl.o \ From ea82e698839d449a2bf8fe577f10756a6e2dbe35 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 22 May 2021 02:45:25 +0000 Subject: [PATCH 162/175] The settings screen in table format with negative number support --- opendps/func_settings.c | 115 ++++++++++++++-------------------------- opendps/uui_number.c | 43 +++++++++++---- 2 files changed, 74 insertions(+), 84 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index 05037dc8..15482f9f 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -65,7 +65,7 @@ // Number of fields shown per page -#define ITEMS_PER_PAGE 6 +#define ITEMS_PER_PAGE 5 // Total number of fields that can be edited #define ITEMS 13 @@ -74,10 +74,10 @@ #define PAGES (ITEMS+(ITEMS_PER_PAGE-1))/ITEMS_PER_PAGE // UI Row height in pixels -#define ROW_HEIGHT 17 +#define ROW_HEIGHT 17 // Field X/Y offsets. Fields are shown on the right-hand side of the screen -#define FIELD_Y_OFFSET 0 +#define FIELD_Y_OFFSET 5 #define FIELD_X_OFFSET 128 // which page we are currently on. @@ -166,16 +166,16 @@ struct field_item field_items[] = { {"Refresh", 100000, 9990000, 3, 0, unit_ms, &get_refresh, &set_refresh }, // constants - {"V ADC K", 0, 9999999, 3, 4, unit_none, &get_v_adc_k, &set_v_adc_k }, - {"V ADC C", 0, 9999999, 3, 4, unit_none, &get_v_adc_c, &set_v_adc_c }, - {"V DAC K", 0, 9999999, 3, 4, unit_none, &get_v_dac_k, &set_v_dac_k }, - {"V DAC C", 0, 9999999, 3, 4, unit_none, &get_v_dac_c, &set_v_dac_c }, - {"I ADC K", 0, 9999999, 3, 4, unit_none, &get_a_adc_k, &set_a_adc_k }, - {"I ADC C", 0, 9999999, 3, 4, unit_none, &get_a_adc_c, &set_a_adc_c }, - {"I DAC K", 0, 9999999, 3, 4, unit_none, &get_a_dac_k, &set_a_dac_k }, - {"I DAC C", 0, 9999999, 3, 4, unit_none, &get_a_dac_c, &set_a_dac_c }, - {"Vin ADC C", 0, 9999999, 3, 4, unit_none, &get_vin_adc_k, &set_vin_adc_k }, - {"Vin ADC K", 0, 9999999, 3, 4, unit_none, &get_vin_adc_c, &set_vin_adc_c }, + {"V ADC K", -9999999, 9999999, 3, 4, unit_none, &get_v_adc_k, &set_v_adc_k }, + {"V ADC C", -9999999, 9999999, 3, 4, unit_none, &get_v_adc_c, &set_v_adc_c }, + {"V DAC K", -9999999, 9999999, 3, 4, unit_none, &get_v_dac_k, &set_v_dac_k }, + {"V DAC C", -9999999, 9999999, 3, 4, unit_none, &get_v_dac_c, &set_v_dac_c }, + {"I ADC K", -9999999, 9999999, 3, 4, unit_none, &get_a_adc_k, &set_a_adc_k }, + {"I ADC C", -9999999, 9999999, 3, 4, unit_none, &get_a_adc_c, &set_a_adc_c }, + {"I DAC K", -9999999, 9999999, 3, 4, unit_none, &get_a_dac_k, &set_a_dac_k }, + {"I DAC C", -9999999, 9999999, 3, 4, unit_none, &get_a_dac_c, &set_a_dac_c }, + {"Vin ADC C", -9999999, 9999999, 3, 4, unit_none, &get_vin_adc_k, &set_vin_adc_k }, + {"Vin ADC K", -9999999, 9999999, 3, 4, unit_none, &get_vin_adc_c, &set_vin_adc_c }, // lock screen when output enabled {"LockScr-En", 0, 10000, 1, 0, unit_bool, &get_on_locked, &set_on_locked }, @@ -186,27 +186,6 @@ struct field_item field_items[] = { * One field for each row */ ui_number_t settings_field[] = { -{ - { - .type = ui_item_number, - .id = 10, - .x = FIELD_X_OFFSET, - .y = FIELD_Y_OFFSET, - .can_focus = true, - }, - .font_size = FONT_FULL_SMALL, - .alignment = ui_text_right_aligned, - .pad_dot = false, - .color = WHITE, - .value = 0, - .min = 0, - .max = 9999999, - .si_prefix = si_decimilli, - .num_digits = 3, - .num_decimals = 4, - .unit = unit_none, - .changed = &field_changed, -}, { { .type = ui_item_number, @@ -338,8 +317,7 @@ ui_screen_t settings_screen = { (ui_item_t*) &settings_field[1], (ui_item_t*) &settings_field[2], (ui_item_t*) &settings_field[3], - (ui_item_t*) &settings_field[4], - (ui_item_t*) &settings_field[5] + (ui_item_t*) &settings_field[4] }, .set_parameter = &set_parameter, .get_parameter = &get_parameter, @@ -392,16 +370,12 @@ static int32_t get_v_adc_k() { } static void set_v_adc_k(ui_number_t *item) { v_adc_k_coef = item->value / 10000.0f; - if (v_adc_k_coef <= 0) item->color = (item->color == RED) ? WHITE : RED; - if (item->color == RED) v_adc_k_coef = - v_adc_k_coef; } static int32_t get_v_adc_c() { return v_adc_c_coef * 10000; } static void set_v_adc_c(ui_number_t *item) { v_adc_c_coef = item->value / 10000.0f; - if (v_adc_c_coef <= 0) item->color = (item->color == RED) ? WHITE : RED; - if (item->color == RED) v_adc_c_coef = - v_adc_c_coef; } @@ -410,16 +384,12 @@ static int32_t get_v_dac_k() { } static void set_v_dac_k(ui_number_t *item) { v_dac_k_coef = item->value / 10000.0f; - if (v_dac_k_coef <= 0) item->color = (item->color == RED) ? WHITE : RED; - if (item->color == RED) v_dac_k_coef = - v_dac_k_coef; } static int32_t get_v_dac_c() { return v_dac_c_coef * 10000; } static void set_v_dac_c(ui_number_t *item) { v_dac_c_coef = item->value / 10000.0f; - if (v_dac_c_coef <= 0) item->color = (item->color == RED) ? WHITE : RED; - if (item->color == RED) v_dac_c_coef = - v_dac_c_coef; } @@ -429,16 +399,12 @@ static int32_t get_a_adc_k() { } static void set_a_adc_k(ui_number_t *item) { a_adc_k_coef = item->value / 10000.0f; - if (a_adc_k_coef <= 0) item->color = (item->color == RED) ? WHITE : RED; - if (item->color == RED) a_adc_k_coef = - a_adc_k_coef; } static int32_t get_a_adc_c() { return a_adc_c_coef * 10000; } static void set_a_adc_c(ui_number_t *item) { a_adc_c_coef = item->value / 10000.0f; - if (a_adc_c_coef <= 0) item->color = (item->color == RED) ? WHITE : RED; - if (item->color == RED) a_adc_c_coef = - a_adc_c_coef; } @@ -447,16 +413,12 @@ static int32_t get_a_dac_k() { } static void set_a_dac_k(ui_number_t *item) { a_dac_k_coef = item->value / 10000.0f; - if (a_dac_k_coef <= 0) item->color = (item->color == RED) ? WHITE : RED; - if (item->color == RED) a_dac_k_coef = - a_dac_k_coef; } static int32_t get_a_dac_c() { return a_dac_c_coef * 10000; } static void set_a_dac_c(ui_number_t *item) { a_dac_c_coef = item->value / 10000.0f; - if (a_dac_c_coef <= 0) item->color = (item->color == RED) ? WHITE : RED; - if (item->color == RED) a_dac_c_coef = - a_dac_c_coef; } @@ -465,16 +427,12 @@ static int32_t get_vin_adc_k() { } static void set_vin_adc_k(ui_number_t *item) { vin_adc_k_coef = item->value / 10000.0f; - if (vin_adc_k_coef <= 0) item->color = (item->color == RED) ? WHITE : RED; - if (item->color == RED) vin_adc_k_coef = - vin_adc_k_coef; } static int32_t get_vin_adc_c() { return vin_adc_c_coef * 10000; } static void set_vin_adc_c(ui_number_t *item) { vin_adc_c_coef = item->value / 10000.0f; - if (vin_adc_k_coef <= 0) item->color = (item->color == RED) ? WHITE : RED; - if (item->color == RED) vin_adc_c_coef = - vin_adc_c_coef; } @@ -527,15 +485,15 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { switch (event) { case event_button_m1: case event_button_m2: - if ( ! select_mode) { - return false; - } // go up if ( event == event_button_m1 ) { + ui_screen_t *screen = ui->screens[ui->cur_screen]; + // not first item, move up one if (current_item > 0) { current_item--; + if ( ! select_mode) screen->cur_item = current_item; return false; } @@ -549,10 +507,13 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { // current_item == 0, and current_page != 0 set_page(current_page - 1); current_item = ITEMS_PER_PAGE - 1; + if ( ! select_mode) screen->cur_item = current_item; return false; // go down } else { + ui_screen_t *screen = ui->screens[ui->cur_screen]; + // not last item, go down if (current_item < ITEMS_PER_PAGE - 1) { // do nothing if we are on the last item already @@ -561,6 +522,7 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { // otherwise, go down one item current_item++; + if ( ! select_mode) screen->cur_item = current_item; return false; } @@ -574,6 +536,7 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { // last item, but not last page set_page(current_page + 1); current_item = 0; + if ( ! select_mode) screen->cur_item = current_item; return false; } @@ -587,6 +550,7 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { } select_mode = ! select_mode; + return false; default: @@ -628,16 +592,7 @@ static void set_page(int8_t page) { // update field value using value from the get function int32_t value = field_items[page_offset + i].get(); - if (value < 0) { - // because uui_number doesn't support signed values - // color represents the sign. This is is gross hack, I know. - settings_field[i].value = -value; - settings_field[i].color = RED; - } else { - settings_field[i].value = value; - settings_field[i].color = WHITE; - } - + settings_field[i].value = value; settings_field[i].min = field_items[page_offset + i].min; settings_field[i].max = field_items[page_offset + i].max; settings_field[i].num_digits = field_items[page_offset + i].digits; @@ -661,19 +616,33 @@ static void settings_tick(void) { for (uint8_t i = 0; i < ITEMS_PER_PAGE; i++) { // if greater than total number of items, clear the area if (page_offset + i >= ITEMS) { - tft_fill(0 /* x */, i * ROW_HEIGHT /* y */, + tft_fill(0 /* x */, FIELD_Y_OFFSET + ((1 + i) * ROW_HEIGHT) /* y, +1 because first row is the header */, TFT_WIDTH, ROW_HEIGHT, BLACK); } else { tft_puts(FONT_FULL_SMALL, field_items[page_offset + i].label, - 0 /* x */, (i * ROW_HEIGHT) + FONT_FULL_SMALL_MAX_GLYPH_HEIGHT /* y */ , + 0 /* x, 1st px for select bar */, FIELD_Y_OFFSET + ((1 + i) * ROW_HEIGHT) + FONT_FULL_SMALL_MAX_GLYPH_HEIGHT /* y */ , TFT_WIDTH/2, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, - WHITE, false); + current_item == i ? ORANGE : WHITE, false); + + // vertical separator |, for each entry + ili9163c_draw_vline(TFT_WIDTH/2 + 3, FIELD_Y_OFFSET + FONT_FULL_SMALL_MAX_GLYPH_HEIGHT + (i * ROW_HEIGHT), + ROW_HEIGHT, + WHITE); settings_field[i].ui.draw(&settings_field[i].ui); } } + + // print the header + tft_puts(FONT_FULL_SMALL, "OpenDPS Settings", 1 /*x*/, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT /*y*/, + FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 16, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, + GREEN, false); + + // header separator _____ + ili9163c_draw_hline(0, FIELD_Y_OFFSET + FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, TFT_WIDTH, WHITE); + } @@ -718,7 +687,6 @@ static void activated() { // Move back to previous page on init. set_page(current_page); current_item = 0; - select_mode = 0; } /** @@ -745,7 +713,6 @@ void func_settings_init(uui_t *ui) { // initialize page and selected items set_page(0); current_item = 0; - select_mode = 0; uui_add_screen(ui, &settings_screen); } diff --git a/opendps/uui_number.c b/opendps/uui_number.c index bac184d3..b5c4dea4 100644 --- a/opendps/uui_number.c +++ b/opendps/uui_number.c @@ -23,6 +23,7 @@ */ #include +#include #include #include "my_assert.h" #include "uui_number.h" @@ -58,8 +59,16 @@ static void number_got_event(ui_item_t *_item, event_t event) bool value_changed = false; switch(event) { case event_rot_left: { - uint32_t diff = my_pow(10, (item->si_prefix * -1) - item->num_decimals + item->cur_digit); - item->value -= diff; + int32_t diff = my_pow(10, (item->si_prefix * -1) - item->num_decimals + item->cur_digit); + + if (item->value > 0 && item->value - diff < 0) { + // roll to negative, maintain value but invert sign + item->value = -item->value; + } else { + // subtract digit value, otherwise + item->value -= diff; + } + if (item->value < item->min) { item->value = item->min; } @@ -68,8 +77,16 @@ static void number_got_event(ui_item_t *_item, event_t event) break; } case event_rot_right: { - uint32_t diff = my_pow(10, (item->si_prefix * -1) - item->num_decimals + item->cur_digit); - item->value += diff; + int32_t diff = my_pow(10, (item->si_prefix * -1) - item->num_decimals + item->cur_digit); + + if (item->value < 0 && item->value + diff > 0) { + // roll to positive, maintain value but invert sign + item->value = -item->value; + } else { + // subtract digit value, otherwise + item->value += diff; + } + if (item->value > item->max) { item->value = item->max; } @@ -237,6 +254,7 @@ static void number_draw(ui_item_t *_item) uint32_t xpos = _item->x; uint16_t color = item->color; uint32_t cur_digit = item->num_digits + item->num_decimals - 1; /** Which digit are we currently drawing? 0 is the right most digit */ + uint32_t first_digit_xpos = 0; /** Adjust drawing position if right aligned */ if (item->alignment == ui_text_right_aligned) @@ -255,8 +273,7 @@ static void number_draw(ui_item_t *_item) // this place value (1 = 1, 2 = 10, 3 = 100, etc., for si_prefix = 0) int32_t power = my_pow(10, (item->si_prefix * -1) + (place - 1)); - - uint8_t digit = (item->value / power) % 10; + uint8_t digit = (abs(item->value) / power) % 10; // digit selected bool highlight = _item->has_focus && item->cur_digit == cur_digit; @@ -274,11 +291,13 @@ static void number_draw(ui_item_t *_item) // value >= this place's min value (ie. digit's power) // in one's place (ensuring 0.xxx has leading 0) // or item has focus (ensures all digits are drawn when focused) - if (item->value >= power || place == 1 || _item->has_focus) { + if (abs(item->value) >= power || place == 1 || _item->has_focus) { // ASCII '0' plus digit value for digit ascii offset tft_putch(item->font_size, '0' + digit, xpos, _item->y, digit_w, h, color, highlight); + if (first_digit_xpos == 0) first_digit_xpos = xpos; } else { - tft_fill(xpos, _item->y, digit_w, h, BLACK); + // x -= 5 and width += 5 to overwrite the negative sign + tft_fill(xpos - 5, _item->y, digit_w + 5, h, BLACK); } // next digit position @@ -296,7 +315,7 @@ static void number_draw(ui_item_t *_item) for (uint32_t i = 0; i < item->num_decimals; ++i) { bool highlight = _item->has_focus && item->cur_digit == cur_digit; - uint8_t digit = item->value / my_pow(10, (item->si_prefix * -1) -1 - i) % 10; + uint8_t digit = abs(item->value) / my_pow(10, (item->si_prefix * -1) -1 - i) % 10; if (spacing > 1) /** Dont frame tiny fonts */ { if (highlight) /** Draw an extra pixel wide border around the highlighted item */ @@ -312,6 +331,10 @@ static void number_draw(ui_item_t *_item) /** The unit */ switch(item->unit) { case unit_none: + // dash for negative, assuming small font? + ili9163c_draw_hline(first_digit_xpos - (max_w / 2), _item->y + (h / 2), + max_w / 2, + item->value < 0 ? WHITE : BLACK); break; case unit_volt: tft_putch(item->font_size, 'V', xpos, _item->y, max_w, h, color, false); @@ -337,7 +360,7 @@ static void number_draw(ui_item_t *_item) break; case unit_bool: if (item->value > 0) - tft_puts(FONT_FULL_SMALL, " ON ", xpos, _item->y + h, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 3, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, GREEN, false); + tft_puts(FONT_FULL_SMALL, "ON ", xpos, _item->y + h, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 3, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, GREEN, false); else tft_puts(FONT_FULL_SMALL, "OFF ", xpos, _item->y + h, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 3, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, RED, false); break; From 14f8568e27e100bb1ca0f38ab9ee2e81e786ce49 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 22 May 2021 04:08:23 +0000 Subject: [PATCH 163/175] Settings screen now uses the gear icon --- opendps/Makefile | 2 +- opendps/func_settings.c | 10 +++++----- opendps/gfx-gear.c | 36 ++++++++++++++++++++++++++++++++++++ opendps/gfx-gear.h | 13 +++++++++++++ opendps/gfx/png/gear.png | Bin 0 -> 168 bytes 5 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 opendps/gfx-gear.c create mode 100644 opendps/gfx-gear.h create mode 100644 opendps/gfx/png/gear.png diff --git a/opendps/Makefile b/opendps/Makefile index 448a3343..343a60c6 100644 --- a/opendps/Makefile +++ b/opendps/Makefile @@ -188,7 +188,7 @@ endif ifeq ($(SETTINGS_ENABLE),1) CFLAGS +=-DCONFIG_SETTINGS_ENABLE - OBJS += func_settings.o + OBJS += func_settings.o gfx-gear.o endif ifeq ($(SPLASH_SCREEN),1) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index 15482f9f..274b0a8e 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -36,7 +36,7 @@ #include "ili9163c.h" #include "font-full_small.h" #include "opendps.h" -#include "gfx-crosshair.h" +#include "gfx-gear.h" #include "pastunits.h" #include "opendps.h" @@ -300,10 +300,10 @@ ui_number_t settings_field[] = { ui_screen_t settings_screen = { .id = SCREEN_ID, .name = "settings", - .icon_data = (uint8_t *) gfx_crosshair, - .icon_data_len = sizeof(gfx_crosshair), - .icon_width = GFX_CROSSHAIR_WIDTH, - .icon_height = GFX_CROSSHAIR_HEIGHT, + .icon_data = (uint8_t *) gfx_gear, + .icon_data_len = sizeof(gfx_gear), + .icon_width = GFX_GEAR_WIDTH, + .icon_height = GFX_GEAR_HEIGHT, .event = &event, .activated = &activated, .deactivated = &deactivated, diff --git a/opendps/gfx-gear.c b/opendps/gfx-gear.c new file mode 100644 index 00000000..789b277a --- /dev/null +++ b/opendps/gfx-gear.c @@ -0,0 +1,36 @@ +/** Gfx generated from `gen_lookup.py -i gfx/png/gear.png -o gear` */ + +#include "gfx-gear.h" + +const uint8_t gfx_gear[480] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; \ No newline at end of file diff --git a/opendps/gfx-gear.h b/opendps/gfx-gear.h new file mode 100644 index 00000000..7d9460f3 --- /dev/null +++ b/opendps/gfx-gear.h @@ -0,0 +1,13 @@ +/** Gfx generated from `gen_lookup.py -i gfx/png/gear.png -o gear` */ + +#ifndef __GFX_GEAR_H__ +#define __GFX_GEAR_H__ + +#include + +#define GFX_GEAR_HEIGHT (15) +#define GFX_GEAR_WIDTH (16) + +extern const uint8_t gfx_gear[480]; + +#endif // __GFX_GEAR_H__ \ No newline at end of file diff --git a/opendps/gfx/png/gear.png b/opendps/gfx/png/gear.png new file mode 100644 index 0000000000000000000000000000000000000000..cc69369131e4ee4fd1beca14114422c278032156 GIT binary patch literal 168 zcmeAS@N?(olHy`uVBq!ia0vp^0zk~q!3-pCt=%sRq$EpRBT9nv(@M${i&7aJQ}UBi z6+Ckj(^G>|6H_V+Po~-c6|n{Qgt-3y{~yQ)8IbR z$ko6q>5#*6K|FMp0?8tH;-^6%xKKy4&-zG$~`Nek%@=F Date: Sat, 22 May 2021 04:09:04 +0000 Subject: [PATCH 164/175] DPS mode screen no longer shows brightness setting Use the settings screen to adjust the brightness instead --- opendps/func_dpsmode.c | 50 ++---------------------------------------- 1 file changed, 2 insertions(+), 48 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index a0dc8f39..803d4e5f 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -58,7 +58,6 @@ * * Power limit (over power protection, 0 to disable) * * Timer * * Watt-hour - * * Brightness */ static void dpsmode_enable(bool _enable); @@ -66,7 +65,6 @@ static void voltage_changed(ui_number_t *item); static void current_changed(ui_number_t *item); static void power_changed(ui_number_t *item); static void watthour_changed(ui_number_t *item); -static void brightness_changed(ui_number_t *item); static void timer_changed(ui_time_t *item); static void dpsmode_tick(void); static void activated(void); @@ -237,28 +235,6 @@ ui_time_t dpsmode_timer = { .changed = &timer_changed, }; -ui_number_t dpsmode_brightness = { - { - .type = ui_item_number, - .id = 15, - .x = XPOS_METER, - .y = YPOS_POWER + 5, // +5 since we are using a smaller font - .can_focus = true, - }, - .font_size = FONT_METER_MEDIUM, - .alignment = ui_text_right_aligned, - .pad_dot = false, - .color = WHITE, - .value = 0, - .min = 1, - .max = 100, - .si_prefix = si_none, // percentage, so 0-100 - .num_digits = 3, - .num_decimals = 0, - .unit = unit_percent, - .changed = &brightness_changed, -}; - /* This is the screen definition */ ui_screen_t dpsmode_screen = { @@ -277,14 +253,13 @@ ui_screen_t dpsmode_screen = { .tick = &dpsmode_tick, .set_parameter = &set_parameter, .get_parameter = &get_parameter, - .num_items = 6, + .num_items = 5, .items = { (ui_item_t*) &dpsmode_voltage, (ui_item_t*) &dpsmode_current, (ui_item_t*) &dpsmode_power, (ui_item_t*) &dpsmode_watthour, (ui_item_t*) &dpsmode_timer, - (ui_item_t*) &dpsmode_brightness, }, .parameters = { { @@ -485,12 +460,6 @@ static void timer_changed(ui_time_t *item) { saved_t = item->value; } -static void brightness_changed(ui_number_t *item) { - // update brightness - // 100% = 128, 0% = 0 - hw_set_backlight(item->value * 1.28f); -} - static bool event(uui_t *ui, event_t event, uint8_t data) { switch(event) { @@ -696,9 +665,6 @@ static void activated(void) { // reset watthour value when we leave the screen. dpsmode_watthour.value = 0; - - // get brightness - dpsmode_brightness.value = hw_get_backlight(); } static void determine_focused_item(uui_t *ui, int8_t direction) { @@ -863,10 +829,6 @@ static void dpsmode_tick(void) // set the maximum power based on max voltage and max amps dpsmode_power.max = dpsmode_voltage.max * CONFIG_DPS_MAX_CURRENT; - // update brightness if 0 (because it's most likely not set) - if (dpsmode_brightness.value == 0) - dpsmode_brightness.value = hw_get_backlight() / 1.28f; - // power enabled if (pwrctl_vout_enabled()) { // get the actual voltage and current being supplied @@ -989,13 +951,6 @@ static void dpsmode_tick(void) clear_third_region(); } - // if drawing brightness, show "Brightness:" before value. - if (third_item == (ui_item_t *)&dpsmode_brightness) { - tft_puts(FONT_FULL_SMALL, "Brightness:", 5, YPOS_POWER + (FONT_FULL_SMALL_MAX_GLYPH_HEIGHT << 1) - 7, - FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 12, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, - WHITE, false); - } - // draw 3rd item ((ui_number_t *)third_item)->ui.draw(& ((ui_number_t *)third_item)->ui); @@ -1071,7 +1026,7 @@ static void draw_bars() { TFT_WIDTH - GFX_OPPBAR_WIDTH, YPOS_POWER + FONT_METER_LARGE_MAX_GLYPH_HEIGHT - GFX_OPPBAR_HEIGHT ); // no timer (or other icons), paint black over it. - else if ( (dpsmode_graphics & CUR_GFX_TM) != 1) + else if ( ! (dpsmode_graphics & CUR_GFX_TM)) tft_fill(TFT_WIDTH - GFX_OPPBAR_WIDTH, YPOS_POWER + FONT_METER_LARGE_MAX_GLYPH_HEIGHT - GFX_OPPBAR_HEIGHT, GFX_OPPBAR_WIDTH, GFX_OPPBAR_HEIGHT, BLACK); @@ -1162,7 +1117,6 @@ void func_dpsmode_init(uui_t *ui) number_init(&dpsmode_power); number_init(&dpsmode_watthour); time_init(&dpsmode_timer); - number_init(&dpsmode_brightness); uui_add_screen(ui, &dpsmode_screen); } From a744f6120d3a20a7a0325b6a31d583e5e835a1dd Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 22 May 2021 06:38:37 +0000 Subject: [PATCH 165/175] Refined UI rendering to avoid redrawing elements unnecessarily. The UI was excessively redrawn when screens change with the call to uui_refresh. This causes UI elements to flicker. Instead, each screen will need to refresh only what is necessary on activation The settings screen no longer flicker when moving through pages as only the table portion is blanked with a tft_fill call rather than tft_clear. --- opendps/func_cc.c | 15 ++++++++++++++- opendps/func_cl.c | 15 ++++++++++++++- opendps/func_cv.c | 16 +++++++++++++++- opendps/func_dpsmode.c | 36 +++++++++++++++++------------------- opendps/func_settings.c | 5 ++++- opendps/uui.c | 3 +-- 6 files changed, 65 insertions(+), 25 deletions(-) diff --git a/opendps/func_cc.c b/opendps/func_cc.c index 41256800..0285b25a 100644 --- a/opendps/func_cc.c +++ b/opendps/func_cc.c @@ -50,6 +50,7 @@ static void cc_enable(bool _enable); static void voltage_changed(ui_number_t *item); static void current_changed(ui_number_t *item); static void cc_tick(void); +static void activated(void); static void deactivated(void); static void past_save(past_t *past); static void past_restore(past_t *past); @@ -119,7 +120,7 @@ ui_screen_t cc_screen = { .icon_data_len = sizeof(gfx_cc), .icon_width = GFX_CC_WIDTH, .icon_height = GFX_CC_HEIGHT, - .activated = NULL, + .activated = &activated, .deactivated = &deactivated, .enable = &cc_enable, .past_save = &past_save, @@ -257,6 +258,18 @@ static void deactivated(void) tft_clear(); } +/** + * @brief Do any required clean up before changing away from this screen + */ +static void activated(void) +{ + ui_screen_t *screen = &cc_screen; + for (uint8_t i = 0; i < screen->num_items; i++) { + screen->items[i]->draw(screen->items[i]); + screen->items[i]->needs_redraw = false; + } +} + /** * @brief Save persistent parameters diff --git a/opendps/func_cl.c b/opendps/func_cl.c index 71a4926a..1f65069a 100644 --- a/opendps/func_cl.c +++ b/opendps/func_cl.c @@ -50,6 +50,7 @@ static void cl_enable(bool _enable); static void voltage_changed(ui_number_t *item); static void current_changed(ui_number_t *item); static void cl_tick(void); +static void activated(void); static void deactivated(void); static void past_save(past_t *past); static void past_restore(past_t *past); @@ -126,7 +127,7 @@ ui_screen_t cl_screen = { .icon_data_len = sizeof(gfx_cl), .icon_width = GFX_CL_WIDTH, .icon_height = GFX_CL_HEIGHT, - .activated = NULL, + .activated = &activated, .deactivated = &deactivated, .enable = &cl_enable, .past_save = &past_save, @@ -281,6 +282,18 @@ static void deactivated(void) tft_clear(); } +/** + * @brief Do any required clean up before changing away from this screen + */ +static void activated(void) +{ + ui_screen_t *screen = &cl_screen; + for (uint8_t i = 0; i < screen->num_items; i++) { + screen->items[i]->draw(screen->items[i]); + screen->items[i]->needs_redraw = false; + } +} + /** * @brief Save persistent parameters * diff --git a/opendps/func_cv.c b/opendps/func_cv.c index b4be9038..631e0977 100644 --- a/opendps/func_cv.c +++ b/opendps/func_cv.c @@ -48,6 +48,7 @@ static void cv_enable(bool _enable); static void voltage_changed(ui_number_t *item); static void current_changed(ui_number_t *item); static void cv_tick(void); +static void activated(void); static void deactivated(void); static void past_save(past_t *past); static void past_restore(past_t *past); @@ -117,7 +118,7 @@ ui_screen_t cv_screen = { .icon_data_len = sizeof(gfx_cv), .icon_width = GFX_CV_WIDTH, .icon_height = GFX_CV_HEIGHT, - .activated = NULL, + .activated = &activated, .deactivated = &deactivated, .enable = &cv_enable, .past_save = &past_save, @@ -256,6 +257,19 @@ static void deactivated(void) tft_clear(); } +/** + * @brief Do any required clean up before changing away from this screen + */ +static void activated(void) +{ + ui_screen_t *screen = &cv_screen; + for (uint8_t i = 0; i < screen->num_items; i++) { + screen->items[i]->draw(screen->items[i]); + screen->items[i]->needs_redraw = false; + } +} + + /** * @brief Save persistent parameters * diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 803d4e5f..ee374c49 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -606,11 +606,6 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { break; case event_rot_press: - // let parent handle event if no valid third item exists - if ( ! third_item) { - return false; - } - // Let parent handle event if we are in single edit mode, or select mode // This is to avoid interfereing with existing edit selection if (single_edit_mode || select_mode) { @@ -657,7 +652,6 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { */ static void activated(void) { clear_bars(true); - clear_third_region(); // reset any odd modes single_edit_mode = false; @@ -665,6 +659,12 @@ static void activated(void) { // reset watthour value when we leave the screen. dpsmode_watthour.value = 0; + + ui_screen_t *screen = &dpsmode_screen; + for (uint8_t i = 0; i < screen->num_items; i++) { + screen->items[i]->needs_redraw = false; + } + } static void determine_focused_item(uui_t *ui, int8_t direction) { @@ -943,21 +943,15 @@ static void dpsmode_tick(void) dpsmode_voltage.ui.draw(&dpsmode_voltage.ui); dpsmode_current.ui.draw(&dpsmode_current.ui); - // draw 3rd row item... - if ( third_item ) { - // blank out the whole 3rd row area - if (third_invalidate) { - third_invalidate = false; - clear_third_region(); - } - - // draw 3rd item - ((ui_number_t *)third_item)->ui.draw(& ((ui_number_t *)third_item)->ui); - - } else { - dpsmode_power.ui.draw(&dpsmode_power.ui); + // blank out the whole 3rd row area + if (third_invalidate) { + third_invalidate = false; + clear_third_region(); } + // draw 3rd row item... + ((ui_number_t *)third_item)->ui.draw(& ((ui_number_t *)third_item)->ui); + // draw bars on right draw_bars(); } @@ -1119,4 +1113,8 @@ void func_dpsmode_init(uui_t *ui) time_init(&dpsmode_timer); uui_add_screen(ui, &dpsmode_screen); + + // init third item to the 3rd item on the screen + ui_screen_t *screen = &dpsmode_screen; + third_item = screen->items[2]; } diff --git a/opendps/func_settings.c b/opendps/func_settings.c index 274b0a8e..e97ed2ab 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -602,7 +602,10 @@ static void set_page(int8_t page) { settings_field[i].cur_digit = field_items[page_offset + i].digits + field_items[page_offset + i].decimals - 1; } - tft_clear(); + // clear the first column on the table + tft_fill(0 /* x */, FIELD_Y_OFFSET + FONT_FULL_SMALL_MAX_GLYPH_HEIGHT + 1/* y */, + TFT_WIDTH, ITEMS_PER_PAGE * ROW_HEIGHT, + BLACK); } diff --git a/opendps/uui.c b/opendps/uui.c index 6429c321..2df96e19 100644 --- a/opendps/uui.c +++ b/opendps/uui.c @@ -111,8 +111,7 @@ void uui_activate(uui_t *ui) break; } } - /** @todo: add activation callback for each screen allowing for updating of U/I settings */ - uui_refresh(ui, true); + tft_blit((uint16_t*) screen->icon_data, screen->icon_width, screen->icon_height, XPOS_ICON, 128-screen->icon_height); if (screen->activated) { screen->activated(); From 97636538a8b03a39bae15b29546c00e0ff87ad51 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sat, 22 May 2021 07:19:09 +0000 Subject: [PATCH 166/175] Reverted dps-model.h values to that from master. --- opendps/dps-model.h | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/opendps/dps-model.h b/opendps/dps-model.h index 3b26b343..54fe4e9c 100644 --- a/opendps/dps-model.h +++ b/opendps/dps-model.h @@ -82,18 +82,14 @@ #define CURRENT_DIGITS 1 #define CURRENT_DECIMALS 3 #define ADC_CHA_IOUT_GOLDEN_VALUE (0x45) - #define A_ADC_K (float) 1.7068604363612f - #define A_ADC_C (float) -127.302771802896f - - - #define A_DAC_K (float) 0.65093572009764f - #define A_DAC_C (float) 271.440195280716f - - #define V_DAC_K (float) 0.076447899114725f - #define V_DAC_C (float) 3.22404026358549f - - #define V_ADC_K (float) 13.0802536979635f - #define V_ADC_C (float) -108.032224145859f + #define A_ADC_K (float)1.713f + #define A_ADC_C (float)-118.51f + #define A_DAC_K (float)0.652f + #define A_DAC_C (float)288.611f + #define V_DAC_K (float)0.072f + #define V_DAC_C (float)1.85f + #define V_ADC_K (float)13.164f + #define V_ADC_C (float)-100.751f #elif defined(DP50V5A) #ifndef CONFIG_DPS_MAX_CURRENT #define CONFIG_DPS_MAX_CURRENT (5000) @@ -101,15 +97,14 @@ #define CURRENT_DIGITS 1 #define CURRENT_DECIMALS 3 #define ADC_CHA_IOUT_GOLDEN_VALUE (0x45) - #define A_DAC_K (float)0.641025641025641f - #define A_DAC_C (float)301.282051282051f - #define A_ADC_K (float)1.72894209590626f - #define A_ADC_C (float)-122.667008351117f - - #define V_DAC_K (float)0.0754503442421956f - #define V_DAC_C (float)1.38640007545034f - #define V_ADC_K (float)13.2447613492391f - #define V_ADC_C (float)-110.983897477628f + #define A_DAC_K (float)0.6402f + #define A_DAC_C (float)299.5518f + #define A_ADC_K (float)1.74096f + #define A_ADC_C (float)-121.3943805f + #define V_DAC_K (float)0.07544f + #define V_DAC_C (float)2.1563f + #define V_ADC_K (float)13.253f + #define V_ADC_C (float)-103.105f #elif defined(DPS3005) #ifndef CONFIG_DPS_MAX_CURRENT #define CONFIG_DPS_MAX_CURRENT (5000) From e5716ef3c3e7a8c841fae1c54aafa1cfae033abd Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 23 May 2021 06:40:40 +0000 Subject: [PATCH 167/175] Added popup message to settings screen Removed the lock screen option which had no effect Configuration reset triggered through the reset option rather than the key combination which is prone to accidental triggering Popup message will show when settings are saved or reset --- opendps/func_settings.c | 245 +++++++++++++++++++++++++++++----------- opendps/func_settings.h | 6 + 2 files changed, 185 insertions(+), 66 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index e97ed2ab..982a0726 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -48,12 +48,12 @@ * * Label Value * ------------------------- + * | OpenDPS Settings | <- header * | Brightness 100% | <- first field / uui_number * | Refresh Rate 100ms | * | V ADC K 13.0000 | ... * | V ADC C 13.0000 | - * | V DAC K 13.0000 | - * | V DAC C 13.0000 | <- sixth field / uui_number + * | V DAC K 13.0000 | <- fifth field / uui_number * ------------------------- * * When a value is set, it calls the set function callback in order to do something. @@ -80,11 +80,21 @@ #define FIELD_Y_OFFSET 5 #define FIELD_X_OFFSET 128 +// popup message duration, in ms +#define POPUP_MESSAGE_TIME 500 + // which page we are currently on. static int8_t current_page = 0; -static int8_t current_item = 0; +static int8_t current_item = 0; // current item on this page (0 - ITEMS_PER_PAGE-1) static bool select_mode; +// keep track of changes and if we are prompting the user to save +static bool changes_made; +static uint64_t popup_message_ticks; // number of ticks to show the saved message overlay +static uint32_t popup_message_duration; +static int8_t popup_message_type; +static event_t event_after_popup; + int8_t ui_settings = 0; /* @@ -106,6 +116,9 @@ static void set_page(int8_t page); static set_param_status_t set_parameter(char *name, char *value); static set_param_status_t get_parameter(char *name, char *value, uint32_t value_len); +static void reset_open_popup(void); +static void show_popup(uint8_t message, event_t event); + /* * Get/Set functions used as callbacks for all editable fields @@ -134,8 +147,8 @@ static int32_t get_brightness(void); static void set_brightness(struct ui_number_t *); static int32_t get_refresh(void); static void set_refresh(struct ui_number_t *item); -static int32_t get_on_locked(void); -static void set_on_locked(struct ui_number_t *item); +static int32_t get_resetcfg(void); +static void set_resetcfg(struct ui_number_t *item); struct field_item { @@ -162,8 +175,8 @@ struct field_item { struct field_item field_items[] = { // All values are 10^4 and usess the si_decimilli unit. // LABEL MIN MAX DIGITS, DEC, UNIT, GET callback SET callback - {"Brightness", 10000, 1000000, 3, 0, unit_none, &get_brightness, &set_brightness }, // TODO: Set this to unit_percent from dpsmode PR - {"Refresh", 100000, 9990000, 3, 0, unit_ms, &get_refresh, &set_refresh }, + {"Brightness", 10000, 1000000, 3, 0, unit_percent, &get_brightness, &set_brightness }, + {"Refresh Int", 100000, 9990000, 3, 0, unit_ms, &get_refresh, &set_refresh }, // constants {"V ADC K", -9999999, 9999999, 3, 4, unit_none, &get_v_adc_k, &set_v_adc_k }, @@ -178,7 +191,7 @@ struct field_item field_items[] = { {"Vin ADC K", -9999999, 9999999, 3, 4, unit_none, &get_vin_adc_c, &set_vin_adc_c }, // lock screen when output enabled - {"LockScr-En", 0, 10000, 1, 0, unit_bool, &get_on_locked, &set_on_locked }, + {"Reset Cfg", 0, 10000, 1, 0, unit_bool, &get_resetcfg, &set_resetcfg }, }; /* @@ -362,6 +375,29 @@ static set_param_status_t get_parameter(char *name, char *value, uint32_t value_ } +/** + * @brief Resets the open popup message + */ +static void reset_open_popup() { + // if (popup_message_ticks > 0) popup_message_ticks = 1; + popup_message_duration = 0; + popup_message_type = POPUP_MESSAGE_NONE; +} + +/** + * @brief Shows a popup message + * + * @param[in] message message type + * @param[in] event event to fire after popup is cleared + */ +static void show_popup(uint8_t message, event_t event) { + popup_message_duration = POPUP_MESSAGE_TIME; + popup_message_ticks = get_ticks(); + popup_message_type = message; + event_after_popup = event; +} + + /* * Get / Set callback functions */ @@ -458,99 +494,134 @@ static void set_refresh(ui_number_t *item) { } } -static int32_t get_on_locked() { - if (ui_settings | SCREEN_LOCKED_WHEN_ON) { - return 10000; - } + +static int32_t get_resetcfg() { return 0; } +static void set_resetcfg(struct ui_number_t *item) { + // non-zero values will trigger a settings reset + if (item->value != 1) { + // reset + settings_reset(); -static void set_on_locked(struct ui_number_t *item) { - if (item->value == 0) { - ui_settings = ui_settings & ~SCREEN_LOCKED_WHEN_ON; - } else { - ui_settings = ui_settings | SCREEN_LOCKED_WHEN_ON; + // update page to update values + set_page(current_page); + + show_popup(POPUP_MESSAGE_RESET, event_none); } } - /** * @brief event handler: We only care about the SET, M1 and M2 buttons * used to keep track of where we are in the menu */ static bool event(uui_t *ui, event_t event, uint8_t data) { (void)ui; + (void)data; + + // reset popup when an event is received + reset_open_popup(); + + ui_screen_t *screen = ui->screens[ui->cur_screen]; + // handle events switch (event) { - case event_button_m1: - case event_button_m2: - // go up - if ( event == event_button_m1 ) { - ui_screen_t *screen = ui->screens[ui->cur_screen]; - - // not first item, move up one - if (current_item > 0) { - current_item--; - if ( ! select_mode) screen->cur_item = current_item; - return false; - } - - // we are left with current_item == 0. - - if (current_page == 0) { - // do nothing for first page/first item - return true; - } + // Override the on/off button as a save button + // Settings screen should not enable power. + case event_button_enable: + if (changes_made) { + // save changes + screen->past_save(ui->past); + + // show popup message + show_popup(POPUP_MESSAGE_SAVED, event_none); + } + + // override default behavior; do nothing + return true; + + // Override the change screen key combination so that when changing + // screens, we will automatically trigger a save along with a popup + // message. + case event_rot_left_set: + case event_rot_right_set: + if (changes_made) { + // save changes + screen->past_save(ui->past); + + // show popup message + show_popup(POPUP_MESSAGE_SAVED, event); + return true; + } - // current_item == 0, and current_page != 0 - set_page(current_page - 1); - current_item = ITEMS_PER_PAGE - 1; + // No changes; default to default behavior + return false; + + // M1 to go up one setting option + case event_button_m1: + // not first item, move up one + if (current_item > 0) { + current_item--; if ( ! select_mode) screen->cur_item = current_item; return false; + } - // go down - } else { - ui_screen_t *screen = ui->screens[ui->cur_screen]; + // Otherwise, first item. Go up one page unless we are on the first page + if (current_page == 0) { + return true; + } - // not last item, go down - if (current_item < ITEMS_PER_PAGE - 1) { - // do nothing if we are on the last item already - if ((current_page * ITEMS_PER_PAGE) + current_item >= ITEMS - 1) - return true; + // go up one page + set_page(current_page - 1); + current_item = ITEMS_PER_PAGE - 1; - // otherwise, go down one item - current_item++; - if ( ! select_mode) screen->cur_item = current_item; - return false; - } + // if in editing mode, keep track of the next item + if ( ! select_mode) screen->cur_item = current_item; - // we are left with current_item == last item + return false; - if (current_page == PAGES - 1) { - // last page. do nothing + // M2 to go down + case event_button_m2: + // not last item, go down + if (current_item < ITEMS_PER_PAGE - 1) { + // do nothing if we are on the last item already + if ((current_page * ITEMS_PER_PAGE) + current_item >= ITEMS - 1) return true; - } - // last item, but not last page - set_page(current_page + 1); - current_item = 0; + // otherwise, go down one item + current_item++; + + // if in editing mode, keep track of the next item if ( ! select_mode) screen->cur_item = current_item; return false; } - case event_button_sel: - // long SET press will reest all values - if (data == press_long) { - settings_reset(); - // update page to update values - set_page(current_page); + // Dealing with the last item. Last page? do nothing + if (current_page == PAGES - 1) { return true; } + // Otherwise, go to next page. + set_page(current_page + 1); + current_item = 0; + + // if in editing mode, keep track of the next item + if ( ! select_mode) screen->cur_item = current_item; + + return false; + + // keep track of whether we are in editing mode + case event_button_sel: select_mode = ! select_mode; + return false; + // We assume that the user made changes if they triggered the + // rotary while in select mode. + case event_rot_left: + case event_rot_right: + if (select_mode) changes_made = true; return false; default: @@ -615,6 +686,43 @@ static void set_page(int8_t page) { static void settings_tick(void) { int8_t page_offset = current_page * ITEMS_PER_PAGE; + uint64_t ticks = get_ticks(); + + // draw popup message + if (popup_message_ticks > 0) { + + if ((ticks - popup_message_ticks) < popup_message_duration) { + if (popup_message_type == POPUP_MESSAGE_NONE) return; + popup_message_type = POPUP_MESSAGE_NONE; + + // show the popup message + tft_fill( 10, (TFT_HEIGHT / 2) - FONT_FULL_SMALL_MAX_GLYPH_HEIGHT - FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, + TFT_WIDTH - 20, (FONT_FULL_SMALL_MAX_GLYPH_HEIGHT * 3), + BLACK); + tft_rect( 10, (TFT_HEIGHT / 2) - FONT_FULL_SMALL_MAX_GLYPH_HEIGHT - FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, + TFT_WIDTH - 20, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT * 3, + LIGHTGREY); + + tft_puts(FONT_FULL_SMALL, (popup_message_type == POPUP_MESSAGE_SAVED) ? "Settings Saved!!" : "Settings Reset!", + 20 /*x*/, (TFT_HEIGHT / 2) /*y*/, + FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 20, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, + GREENYELLOW, false); + + return; + } else { + // reset popup message + popup_message_ticks = 0; + popup_message_duration = 0; + + // reproduce the inital event after showing the message + if (event_after_popup != event_none) { + event_put(event_after_popup, press_short); + } + tft_clear(); + } + } + + // draw each field with its corresponding label for (uint8_t i = 0; i < ITEMS_PER_PAGE; i++) { // if greater than total number of items, clear the area @@ -678,6 +786,7 @@ static void settings_reset() { */ static void past_save(past_t *past) { pwrctl_past_save(past); + changes_made = false; } @@ -690,6 +799,8 @@ static void activated() { // Move back to previous page on init. set_page(current_page); current_item = 0; + popup_message_ticks = 0; + select_mode = false; } /** @@ -716,6 +827,8 @@ void func_settings_init(uui_t *ui) { // initialize page and selected items set_page(0); current_item = 0; + popup_message_ticks = 0; + select_mode = false; uui_add_screen(ui, &settings_screen); } diff --git a/opendps/func_settings.h b/opendps/func_settings.h index eb9fb1f6..6888bc23 100644 --- a/opendps/func_settings.h +++ b/opendps/func_settings.h @@ -32,6 +32,12 @@ enum SettingsStates { SCREEN_LOCKED_WHEN_ON = 1, }; +enum PopupMessage { + POPUP_MESSAGE_NONE = 0, + POPUP_MESSAGE_SAVED = 1, + POPUP_MESSAGE_RESET = 2, +}; + /** * @brief Add the SETTINGS function to the UI From 21f794727835847492e3716bb2f5fbef1876c024 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 23 May 2021 06:43:43 +0000 Subject: [PATCH 168/175] DPS screen will only save presets and last settings when necessary A bunch of events were triggeringg past_save. This change will only trigger a write when power is turned on or when presets are saved to reduce flash wear. --- opendps/func_dpsmode.c | 55 +++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index ee374c49..876b247d 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -461,8 +461,27 @@ static void timer_changed(ui_time_t *item) { } static bool event(uui_t *ui, event_t event, uint8_t data) { + past_t *past = ui->past; + uint32_t length; + int32_t *past_data; switch(event) { + case event_button_enable: + // save settings on power on + if (past_read_unit(past, (SCREEN_ID << 24) | PAST_V, (const void**) &past_data, &length)) { + if (*past_data != saved_v) past_write_unit(past, (SCREEN_ID << 24) | PAST_V, (void*) &saved_v, 4); + } + if (past_read_unit(past, (SCREEN_ID << 24) | PAST_I, (const void**) &past_data, &length)) { + if (*past_data != saved_i) past_write_unit(past, (SCREEN_ID << 24) | PAST_I, (void*) &saved_i, 4); + } + if (past_read_unit(past, (SCREEN_ID << 24) | PAST_P, (const void**) &past_data, &length)) { + if (*past_data != saved_p) past_write_unit(past, (SCREEN_ID << 24) | PAST_P, (void*) &saved_p, 4); + } + if (past_read_unit(past, (SCREEN_ID << 24) | PAST_T, (const void**) &past_data, &length)) { + if (*past_data != saved_t) past_write_unit(past, (SCREEN_ID << 24) | PAST_T, (void*) &saved_t, 4); + } + break; + case event_button_sel_m1: case event_button_sel_m2: // save values to recall @@ -474,6 +493,13 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { recall_t[0] = saved_t; dpsmode_graphics &= ~CUR_GFX_M2_RECALL; dpsmode_graphics |= CUR_GFX_M1_RECALL; + + // save + past_write_unit(past, (SCREEN_ID << 24) | (PAST_V << 2), (void*) &recall_v[0], 4); + past_write_unit(past, (SCREEN_ID << 24) | (PAST_I << 2), (void*) &recall_i[0], 4); + past_write_unit(past, (SCREEN_ID << 24) | (PAST_P << 2), (void*) &recall_p[0], 4); + past_write_unit(past, (SCREEN_ID << 24) | (PAST_T << 2), (void*) &recall_t[0], 4); + } else { // save values to m2, show m2 graphics recall_v[1] = saved_v; @@ -482,6 +508,12 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { recall_t[1] = saved_t; dpsmode_graphics &= ~CUR_GFX_M1_RECALL; dpsmode_graphics |= CUR_GFX_M2_RECALL; + + // save + past_write_unit(past, (SCREEN_ID << 24) | (PAST_V << 4), (void*) &recall_v[1], 4); + past_write_unit(past, (SCREEN_ID << 24) | (PAST_I << 4), (void*) &recall_i[1], 4); + past_write_unit(past, (SCREEN_ID << 24) | (PAST_P << 4), (void*) &recall_p[1], 4); + past_write_unit(past, (SCREEN_ID << 24) | (PAST_T << 4), (void*) &recall_t[1], 4); } // Turn off power @@ -733,28 +765,7 @@ static void deactivated(void) */ static void past_save(past_t *past) { - if ( past_write_unit(past, (SCREEN_ID << 24) | PAST_V, (void*) &saved_v, 4) - && past_write_unit(past, (SCREEN_ID << 24) | PAST_I, (void*) &saved_i, 4) - && past_write_unit(past, (SCREEN_ID << 24) | PAST_P, (void*) &saved_p, 4) - && past_write_unit(past, (SCREEN_ID << 24) | PAST_T, (void*) &saved_t, 4)) { - // write successful - } - - // recall m1 - if ( past_write_unit(past, (SCREEN_ID << 24) | (PAST_V << 2), (void*) &recall_v[0], 4) - && past_write_unit(past, (SCREEN_ID << 24) | (PAST_I << 2), (void*) &recall_i[0], 4) - && past_write_unit(past, (SCREEN_ID << 24) | (PAST_P << 2), (void*) &recall_p[0], 4) - && past_write_unit(past, (SCREEN_ID << 24) | (PAST_T << 2), (void*) &recall_t[0], 4)) { - // write successful - } - - // recall m2 - if ( past_write_unit(past, (SCREEN_ID << 24) | (PAST_V << 4), (void*) &recall_v[1], 4) - && past_write_unit(past, (SCREEN_ID << 24) | (PAST_I << 4), (void*) &recall_i[1], 4) - && past_write_unit(past, (SCREEN_ID << 24) | (PAST_P << 4), (void*) &recall_p[1], 4) - && past_write_unit(past, (SCREEN_ID << 24) | (PAST_T << 4), (void*) &recall_t[1], 4)) { - // write successful - } + (void)past; } /** From e34d702e0695751f581299718de199a39e9925a3 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 23 May 2021 06:54:56 +0000 Subject: [PATCH 169/175] Fixed incorrect popup message when saving settings in settings screen --- opendps/func_settings.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index 982a0726..eb99c335 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -693,7 +693,6 @@ static void settings_tick(void) { if ((ticks - popup_message_ticks) < popup_message_duration) { if (popup_message_type == POPUP_MESSAGE_NONE) return; - popup_message_type = POPUP_MESSAGE_NONE; // show the popup message tft_fill( 10, (TFT_HEIGHT / 2) - FONT_FULL_SMALL_MAX_GLYPH_HEIGHT - FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, @@ -708,6 +707,8 @@ static void settings_tick(void) { FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 20, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, GREENYELLOW, false); + popup_message_type = POPUP_MESSAGE_NONE; + return; } else { // reset popup message From 344f40beb607e44432f7face86fc55ff8274da92 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Sun, 23 May 2021 22:35:15 +0000 Subject: [PATCH 170/175] DPS Mode refinements V/A buttons focuses voltage/current directly. Preset bars are set on screen activation if values match Boolean values rendered by uui_number no longer show numeric values --- opendps/func_dpsmode.c | 145 ++++++++++++++++++++++++---------------- opendps/func_settings.c | 6 +- opendps/uui_number.c | 9 ++- 3 files changed, 97 insertions(+), 63 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 876b247d..7c0ebb2d 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -483,38 +483,39 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { break; case event_button_sel_m1: - case event_button_sel_m2: - // save values to recall - if (event == event_button_sel_m1) { - // save values to m1, show m1 graphics - recall_v[0] = saved_v; - recall_i[0] = saved_i; - recall_p[0] = saved_p; - recall_t[0] = saved_t; - dpsmode_graphics &= ~CUR_GFX_M2_RECALL; - dpsmode_graphics |= CUR_GFX_M1_RECALL; - - // save - past_write_unit(past, (SCREEN_ID << 24) | (PAST_V << 2), (void*) &recall_v[0], 4); - past_write_unit(past, (SCREEN_ID << 24) | (PAST_I << 2), (void*) &recall_i[0], 4); - past_write_unit(past, (SCREEN_ID << 24) | (PAST_P << 2), (void*) &recall_p[0], 4); - past_write_unit(past, (SCREEN_ID << 24) | (PAST_T << 2), (void*) &recall_t[0], 4); + // save values to m1, show m1 graphics + recall_v[0] = saved_v; + recall_i[0] = saved_i; + recall_p[0] = saved_p; + recall_t[0] = saved_t; + dpsmode_graphics &= ~CUR_GFX_M2_RECALL; + dpsmode_graphics |= CUR_GFX_M1_RECALL; + + // save + past_write_unit(past, (SCREEN_ID << 24) | (PAST_V << 2), (void*) &recall_v[0], 4); + past_write_unit(past, (SCREEN_ID << 24) | (PAST_I << 2), (void*) &recall_i[0], 4); + past_write_unit(past, (SCREEN_ID << 24) | (PAST_P << 2), (void*) &recall_p[0], 4); + past_write_unit(past, (SCREEN_ID << 24) | (PAST_T << 2), (void*) &recall_t[0], 4); + + // Turn off power + event_put(event_shutoff, 0); - } else { - // save values to m2, show m2 graphics - recall_v[1] = saved_v; - recall_i[1] = saved_i; - recall_p[1] = saved_p; - recall_t[1] = saved_t; - dpsmode_graphics &= ~CUR_GFX_M1_RECALL; - dpsmode_graphics |= CUR_GFX_M2_RECALL; + return true; - // save - past_write_unit(past, (SCREEN_ID << 24) | (PAST_V << 4), (void*) &recall_v[1], 4); - past_write_unit(past, (SCREEN_ID << 24) | (PAST_I << 4), (void*) &recall_i[1], 4); - past_write_unit(past, (SCREEN_ID << 24) | (PAST_P << 4), (void*) &recall_p[1], 4); - past_write_unit(past, (SCREEN_ID << 24) | (PAST_T << 4), (void*) &recall_t[1], 4); - } + case event_button_sel_m2: + // save values to m2, show m2 graphics + recall_v[1] = saved_v; + recall_i[1] = saved_i; + recall_p[1] = saved_p; + recall_t[1] = saved_t; + dpsmode_graphics &= ~CUR_GFX_M1_RECALL; + dpsmode_graphics |= CUR_GFX_M2_RECALL; + + // save + past_write_unit(past, (SCREEN_ID << 24) | (PAST_V << 4), (void*) &recall_v[1], 4); + past_write_unit(past, (SCREEN_ID << 24) | (PAST_I << 4), (void*) &recall_i[1], 4); + past_write_unit(past, (SCREEN_ID << 24) | (PAST_P << 4), (void*) &recall_p[1], 4); + past_write_unit(past, (SCREEN_ID << 24) | (PAST_T << 4), (void*) &recall_t[1], 4); // Turn off power event_put(event_shutoff, 0); @@ -546,9 +547,9 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { return false; case event_button_m1: - case event_button_m2: + // do recall on press_long event_button_m1 or event_button_m2 - if (event == event_button_m1 && data == press_long) { + if (data == press_long) { saved_v = recall_v[0]; saved_i = recall_i[0]; saved_p = recall_p[0]; @@ -562,8 +563,41 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { dpsmode_graphics |= CUR_GFX_M1_RECALL; return true; } + + if (single_edit_mode) { + // Change focus to voltage if current is selected + if (dpsmode_current.ui.has_focus) { + uui_focus(ui, (ui_item_t*) &dpsmode_current); + uui_focus(ui, (ui_item_t*) &dpsmode_voltage); + } else { + // otherwise, leave single edit mode + if (dpsmode_voltage.ui.has_focus) + uui_focus(ui, (ui_item_t*) &dpsmode_voltage); + single_edit_mode = false; + } + + return true; + } + + // if in normal select mode, let parent handle it + if (select_mode) { + // third item focused may have changed + determine_focused_item(ui, -1); + return false; + } + + // focus on voltage if not already focused + if ( ! dpsmode_voltage.ui.has_focus) + uui_focus(ui, (ui_item_t*) &dpsmode_voltage); - if (event == event_button_m2 && data == press_long) { + // otherwise, enter single edit mode + single_edit_mode = true; + + // we handled it, parent should do nothing + return true; + + case event_button_m2: + if (data == press_long) { saved_v = recall_v[1]; saved_i = recall_i[1]; saved_p = recall_p[1]; @@ -578,43 +612,32 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { return true; } - // leave single edit mode on any button press if (single_edit_mode) { - single_edit_mode = false; - - // toggle focus on anything that is in focus (to unfocus) - if (dpsmode_voltage.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_voltage); - if (dpsmode_current.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_current); + // Change focus to current if voltage is selected + if (dpsmode_voltage.ui.has_focus) { + uui_focus(ui, (ui_item_t*) &dpsmode_voltage); + uui_focus(ui, (ui_item_t*) &dpsmode_current); + } else { + // otherwise, leave single edit mode + if (dpsmode_current.ui.has_focus) + uui_focus(ui, (ui_item_t*) &dpsmode_current); + single_edit_mode = false; + } return true; } - // for either m1/m2 buttons: - if (event == event_button_m1) { - // if in normal select mode, let parent handle it - if (select_mode) { - // third item focused may have changed - determine_focused_item(ui, -1); - - return false; - } - - // focus on voltage if not already focused - if ( ! dpsmode_voltage.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_voltage); + if (select_mode) { + determine_focused_item(ui, 1); + return false; } - if (event == event_button_m2) { - if (select_mode) { - determine_focused_item(ui, 1); - return false; - } - if ( ! dpsmode_current.ui.has_focus) uui_focus(ui, (ui_item_t*) &dpsmode_current); - } + if ( ! dpsmode_current.ui.has_focus) + uui_focus(ui, (ui_item_t*) &dpsmode_current); // otherwise, enter single edit mode single_edit_mode = true; - // we handled it, parent should do nothing return true; case event_rot_left_down: @@ -685,6 +708,10 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { static void activated(void) { clear_bars(true); + // determine if M1/M2 settings match and enable those bars + if (recall_v[0] == saved_v && recall_i[0] == saved_i && recall_p[0] == saved_p && recall_t[0] == saved_t) dpsmode_graphics |= CUR_GFX_M1_RECALL; + if (recall_v[1] == saved_v && recall_i[1] == saved_i && recall_p[1] == saved_p && recall_t[1] == saved_t) dpsmode_graphics |= CUR_GFX_M2_RECALL; + // reset any odd modes single_edit_mode = false; select_mode = false; diff --git a/opendps/func_settings.c b/opendps/func_settings.c index eb99c335..e2de3863 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -175,8 +175,8 @@ struct field_item { struct field_item field_items[] = { // All values are 10^4 and usess the si_decimilli unit. // LABEL MIN MAX DIGITS, DEC, UNIT, GET callback SET callback - {"Brightness", 10000, 1000000, 3, 0, unit_percent, &get_brightness, &set_brightness }, - {"Refresh Int", 100000, 9990000, 3, 0, unit_ms, &get_refresh, &set_refresh }, + {"Brightness", 10000, 1000000, 3, 0, unit_percent, &get_brightness, &set_brightness }, + {"Refresh", 100000, 50000000, 4, 0, unit_ms, &get_refresh, &set_refresh }, // constants {"V ADC K", -9999999, 9999999, 3, 4, unit_none, &get_v_adc_k, &set_v_adc_k }, @@ -191,7 +191,7 @@ struct field_item field_items[] = { {"Vin ADC K", -9999999, 9999999, 3, 4, unit_none, &get_vin_adc_c, &set_vin_adc_c }, // lock screen when output enabled - {"Reset Cfg", 0, 10000, 1, 0, unit_bool, &get_resetcfg, &set_resetcfg }, + {"Reset Cfg", 0, 10000, 1, 0, unit_bool, &get_resetcfg, &set_resetcfg }, }; /* diff --git a/opendps/uui_number.c b/opendps/uui_number.c index b5c4dea4..0fa86007 100644 --- a/opendps/uui_number.c +++ b/opendps/uui_number.c @@ -260,6 +260,11 @@ static void number_draw(ui_item_t *_item) if (item->alignment == ui_text_right_aligned) xpos -= number_draw_width(_item); + + if (item->unit == unit_bool) { + tft_rect(xpos-1, _item->y-1, digit_w * 4, h+1, _item->has_focus ? WHITE : BLACK); + } else { + /** Start printing from left to right */ for (uint8_t place = item->num_digits; place > 0; place--) { /* Example value of 1000 with 5,2: @@ -304,6 +309,8 @@ static void number_draw(ui_item_t *_item) xpos += digit_w + spacing; } + } + /** Draw the decimal point if there are decimal places */ if (item->num_decimals) { tft_putch(item->font_size, '.', xpos, _item->y, dot_width, h, color, false); @@ -360,7 +367,7 @@ static void number_draw(ui_item_t *_item) break; case unit_bool: if (item->value > 0) - tft_puts(FONT_FULL_SMALL, "ON ", xpos, _item->y + h, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 3, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, GREEN, false); + tft_puts(FONT_FULL_SMALL, "ON ", xpos, _item->y + h, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 3, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, GREEN, false); else tft_puts(FONT_FULL_SMALL, "OFF ", xpos, _item->y + h, FONT_FULL_SMALL_MAX_GLYPH_WIDTH * 3, FONT_FULL_SMALL_MAX_GLYPH_HEIGHT, RED, false); break; From d52b0f2ac0da32e1fde9f0d32029a4c764806196 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Mon, 24 May 2021 04:05:32 +0000 Subject: [PATCH 171/175] Fixed incorrect past save IDs in DPS mode. This issue resulted in recalls failing after a reset. --- opendps/func_dpsmode.c | 56 +++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 31 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 7c0ebb2d..06c6bf8f 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -480,6 +480,7 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { if (past_read_unit(past, (SCREEN_ID << 24) | PAST_T, (const void**) &past_data, &length)) { if (*past_data != saved_t) past_write_unit(past, (SCREEN_ID << 24) | PAST_T, (void*) &saved_t, 4); } + break; case event_button_sel_m1: @@ -492,10 +493,10 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { dpsmode_graphics |= CUR_GFX_M1_RECALL; // save - past_write_unit(past, (SCREEN_ID << 24) | (PAST_V << 2), (void*) &recall_v[0], 4); - past_write_unit(past, (SCREEN_ID << 24) | (PAST_I << 2), (void*) &recall_i[0], 4); - past_write_unit(past, (SCREEN_ID << 24) | (PAST_P << 2), (void*) &recall_p[0], 4); - past_write_unit(past, (SCREEN_ID << 24) | (PAST_T << 2), (void*) &recall_t[0], 4); + past_write_unit(past, ((SCREEN_ID << 24) | PAST_V) + 4, (void*) &recall_v[0], 4); + past_write_unit(past, ((SCREEN_ID << 24) | PAST_I) + 4, (void*) &recall_i[0], 4); + past_write_unit(past, ((SCREEN_ID << 24) | PAST_P) + 4, (void*) &recall_p[0], 4); + past_write_unit(past, ((SCREEN_ID << 24) | PAST_T) + 4, (void*) &recall_t[0], 4); // Turn off power event_put(event_shutoff, 0); @@ -512,10 +513,10 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { dpsmode_graphics |= CUR_GFX_M2_RECALL; // save - past_write_unit(past, (SCREEN_ID << 24) | (PAST_V << 4), (void*) &recall_v[1], 4); - past_write_unit(past, (SCREEN_ID << 24) | (PAST_I << 4), (void*) &recall_i[1], 4); - past_write_unit(past, (SCREEN_ID << 24) | (PAST_P << 4), (void*) &recall_p[1], 4); - past_write_unit(past, (SCREEN_ID << 24) | (PAST_T << 4), (void*) &recall_t[1], 4); + past_write_unit(past, ((SCREEN_ID << 24) | PAST_V) + 8, (void*) &recall_v[1], 4); + past_write_unit(past, ((SCREEN_ID << 24) | PAST_I) + 8, (void*) &recall_i[1], 4); + past_write_unit(past, ((SCREEN_ID << 24) | PAST_P) + 8, (void*) &recall_p[1], 4); + past_write_unit(past, ((SCREEN_ID << 24) | PAST_T) + 8, (void*) &recall_t[1], 4); // Turn off power event_put(event_shutoff, 0); @@ -558,9 +559,6 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { // Turn off power event_put(event_shutoff, 0); - // show the M1 recall graphics - dpsmode_graphics &= ~CUR_GFX_M2_RECALL; - dpsmode_graphics |= CUR_GFX_M1_RECALL; return true; } @@ -606,9 +604,6 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { // Turn off power event_put(event_shutoff, 0); - // show the M2 recall graphics - dpsmode_graphics &= ~CUR_GFX_M1_RECALL; - dpsmode_graphics |= CUR_GFX_M2_RECALL; return true; } @@ -708,10 +703,6 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { static void activated(void) { clear_bars(true); - // determine if M1/M2 settings match and enable those bars - if (recall_v[0] == saved_v && recall_i[0] == saved_i && recall_p[0] == saved_p && recall_t[0] == saved_t) dpsmode_graphics |= CUR_GFX_M1_RECALL; - if (recall_v[1] == saved_v && recall_i[1] == saved_i && recall_p[1] == saved_p && recall_t[1] == saved_t) dpsmode_graphics |= CUR_GFX_M2_RECALL; - // reset any odd modes single_edit_mode = false; select_mode = false; @@ -818,29 +809,29 @@ static void past_restore(past_t *past) saved_t = dpsmode_timer.value = *p; } - if (past_read_unit(past, (SCREEN_ID << 24) | (PAST_V << 2), (const void**) &p, &length)) { + if (past_read_unit(past, ((SCREEN_ID << 24) | PAST_V) + 4, (const void**) &p, &length)) { recall_v[0] = *p; } - if (past_read_unit(past, (SCREEN_ID << 24) | (PAST_I << 2), (const void**) &p, &length)) { + if (past_read_unit(past, ((SCREEN_ID << 24) | PAST_I) + 4, (const void**) &p, &length)) { recall_i[0] = *p; } - if (past_read_unit(past, (SCREEN_ID << 24) | (PAST_P << 2), (const void**) &p, &length)) { + if (past_read_unit(past, ((SCREEN_ID << 24) | PAST_P) + 4, (const void**) &p, &length)) { recall_p[0] = *p; } - if (past_read_unit(past, (SCREEN_ID << 24) | (PAST_T << 2), (const void**) &p, &length)) { + if (past_read_unit(past, ((SCREEN_ID << 24) | PAST_T) + 4, (const void**) &p, &length)) { recall_t[0] = *p; } - if (past_read_unit(past, (SCREEN_ID << 24) | (PAST_V << 4), (const void**) &p, &length)) { + if (past_read_unit(past, ((SCREEN_ID << 24) | PAST_V) + 8, (const void**) &p, &length)) { recall_v[1] = *p; } - if (past_read_unit(past, (SCREEN_ID << 24) | (PAST_I << 4), (const void**) &p, &length)) { + if (past_read_unit(past, ((SCREEN_ID << 24) | PAST_I) + 8, (const void**) &p, &length)) { recall_i[1] = *p; } - if (past_read_unit(past, (SCREEN_ID << 24) | (PAST_P << 4), (const void**) &p, &length)) { + if (past_read_unit(past, ((SCREEN_ID << 24) | PAST_P) + 8, (const void**) &p, &length)) { recall_p[1] = *p; } - if (past_read_unit(past, (SCREEN_ID << 24) | (PAST_T << 4), (const void**) &p, &length)) { + if (past_read_unit(past, ((SCREEN_ID << 24) | PAST_T) + 8, (const void**) &p, &length)) { recall_t[1] = *p; } @@ -1109,13 +1100,16 @@ static void clear_bars(bool all) { if (all) { // clears opp as well as the others dpsmode_graphics &= ~0x3ff; // exclude m1/m2, so not CUR_GFX_NOT_DRAWN; - return; + } else { + // clear just cc/cv/pp otherwise + dpsmode_graphics = dpsmode_graphics & ~CUR_GFX_CC; + dpsmode_graphics = dpsmode_graphics & ~CUR_GFX_CV; + dpsmode_graphics = dpsmode_graphics & ~CUR_GFX_PP; } - // clear just cc/cv/pp otherwise - dpsmode_graphics = dpsmode_graphics & ~CUR_GFX_CC; - dpsmode_graphics = dpsmode_graphics & ~CUR_GFX_CV; - dpsmode_graphics = dpsmode_graphics & ~CUR_GFX_PP; + // determine if M1/M2 settings match and enable those bars + if (recall_v[0] == saved_v && recall_i[0] == saved_i && recall_p[0] == saved_p && recall_t[0] == saved_t) dpsmode_graphics |= CUR_GFX_M1_RECALL; + if (recall_v[1] == saved_v && recall_i[1] == saved_i && recall_p[1] == saved_p && recall_t[1] == saved_t) dpsmode_graphics |= CUR_GFX_M2_RECALL; } From 53d51b97007c3fa27f15bbfcfa34bda955ff5078 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Wed, 2 Jun 2021 00:15:16 +0000 Subject: [PATCH 172/175] Added init state --- opendps/func_dpsmode.c | 35 ++++++++++++++++++++++++++--------- opendps/func_dpsmode.h | 10 ++++++++++ opendps/func_settings.c | 19 +++++++++++++++++-- opendps/func_settings.h | 2 ++ 4 files changed, 55 insertions(+), 11 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 06c6bf8f..0dc1e394 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -70,7 +70,6 @@ static void dpsmode_tick(void); static void activated(void); static void deactivated(void); static bool event(uui_t *ui, event_t event, uint8_t data); -static void past_save(past_t *past); static void past_restore(past_t *past); static set_param_status_t set_parameter(char *name, char *value); static set_param_status_t get_parameter(char *name, char *value, uint32_t value_len); @@ -100,6 +99,10 @@ static int8_t third_row = 0; ui_item_t *third_item; static bool third_invalidate; + +// config +bool dpsmode_cfg_initstate = false; + enum { CUR_GFX_NOT_DRAWN = 0, CUR_GFX_CV = 1, @@ -117,6 +120,7 @@ enum { #define PAST_I (1) #define PAST_P (2) #define PAST_T (3) +#define PAST_CFG (4) #define XPOS_CCCV (25) #define XPOS_METER (117) @@ -248,7 +252,7 @@ ui_screen_t dpsmode_screen = { .activated = &activated, .deactivated = &deactivated, .enable = &dpsmode_enable, - .past_save = &past_save, + .past_save = NULL, .past_restore = &past_restore, .tick = &dpsmode_tick, .set_parameter = &set_parameter, @@ -715,6 +719,10 @@ static void activated(void) { screen->items[i]->needs_redraw = false; } + // init state on? + if (dpsmode_cfg_initstate) { + dpsmode_enable(true); + } } static void determine_focused_item(uui_t *ui, int8_t direction) { @@ -776,15 +784,17 @@ static void deactivated(void) tft_clear(); } + /** - * @brief Save persistent parameters - * - * @param past The past + * @brief Saves dpsmode configs */ -static void past_save(past_t *past) -{ - (void)past; -} +void dpsmode_past_save(past_t *past) { + uint32_t config = 0; + + config |= dpsmode_cfg_initstate ? 1 : 0; + + past_write_unit(past, (SCREEN_ID << 24) | PAST_CFG, (void*) &config, 4); +} /** * @brief Restore persistent parameters @@ -835,6 +845,13 @@ static void past_restore(past_t *past) recall_t[1] = *p; } + // load configs, referenced by the settings screen + if (past_read_unit(past, (SCREEN_ID << 24) | PAST_CFG, (const void**) &p, &length)) { + uint32_t configs = *p; + dpsmode_cfg_initstate = configs & 0x1; + } + + } /** diff --git a/opendps/func_dpsmode.h b/opendps/func_dpsmode.h index 7f0c29b3..a4e5cb51 100644 --- a/opendps/func_dpsmode.h +++ b/opendps/func_dpsmode.h @@ -28,6 +28,7 @@ #include "uui.h" + /** * @brief Add the CV function to the UI * @@ -35,4 +36,13 @@ */ void func_dpsmode_init(uui_t *ui); + + +/** + * @brief Saves past data + * @retval none + */ +void dpsmode_past_save(past_t *past); + + #endif // __FUNC_DPSMODE_H__ diff --git a/opendps/func_settings.c b/opendps/func_settings.c index e2de3863..fa6e8762 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -95,7 +95,7 @@ static uint32_t popup_message_duration; static int8_t popup_message_type; static event_t event_after_popup; -int8_t ui_settings = 0; +int8_t dps_settings = 0; /* * This is the implementation of the Settings screen. @@ -149,6 +149,8 @@ static int32_t get_refresh(void); static void set_refresh(struct ui_number_t *item); static int32_t get_resetcfg(void); static void set_resetcfg(struct ui_number_t *item); +static int32_t get_initstate(void); +static void set_initstate(struct ui_number_t *item); struct field_item { @@ -190,7 +192,8 @@ struct field_item field_items[] = { {"Vin ADC C", -9999999, 9999999, 3, 4, unit_none, &get_vin_adc_k, &set_vin_adc_k }, {"Vin ADC K", -9999999, 9999999, 3, 4, unit_none, &get_vin_adc_c, &set_vin_adc_c }, - // lock screen when output enabled + // Initial output state + {"Init State", 0, 10000, 1, 0, unit_bool, &get_initstate, &set_initstate }, {"Reset Cfg", 0, 10000, 1, 0, unit_bool, &get_resetcfg, &set_resetcfg }, }; @@ -511,6 +514,13 @@ static void set_resetcfg(struct ui_number_t *item) { } } +static int32_t get_initstate() { + return dpsmode_cfg_initstate ? 1 : 0; +} +static void set_initstate(struct ui_number_t *item) { + dpsmode_cfg_initstate = (item->value == 1); +} + /** * @brief event handler: We only care about the SET, M1 and M2 buttons @@ -779,6 +789,9 @@ static void settings_reset() { // reset interval and brightness settings opendps_screen_update_ms = 250; hw_set_backlight(128); + + // dpsmode initial state. (PSU output is off by default) + dpsmode_cfg_initstate = false; } @@ -787,6 +800,8 @@ static void settings_reset() { */ static void past_save(past_t *past) { pwrctl_past_save(past); + dpsmode_past_save(past); + changes_made = false; } diff --git a/opendps/func_settings.h b/opendps/func_settings.h index 6888bc23..d7119055 100644 --- a/opendps/func_settings.h +++ b/opendps/func_settings.h @@ -27,6 +27,8 @@ #include "uui.h" +extern bool dpsmode_cfg_initstate; + // Settings enum SettingsStates { SCREEN_LOCKED_WHEN_ON = 1, From 13dae83e1728ff8463b5c20424a25eb4692b5348 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Fri, 4 Jun 2021 05:42:04 +0000 Subject: [PATCH 173/175] Added a low input voltage warning If insufficient voltage is provided for the set voltage, a warning bar will be displayed next to the voltage value. This will override the constant voltage / constant current mode as it stops functioning properly in this state. --- opendps/func_dpsmode.c | 39 ++++++++++++++++++++++++++++++++------- opendps/func_settings.c | 8 ++++---- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 0dc1e394..8674eb23 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -105,11 +105,12 @@ bool dpsmode_cfg_initstate = false; enum { CUR_GFX_NOT_DRAWN = 0, - CUR_GFX_CV = 1, - CUR_GFX_CC = 2, - CUR_GFX_PP = 4, - CUR_GFX_OPP = 8, - CUR_GFX_TM = 16, + CUR_GFX_CV = 1, // constant voltage + CUR_GFX_CC = 2, // constant current + CUR_GFX_PP = 4, // power + CUR_GFX_OPP = 8, // over power protection + CUR_GFX_TM = 16, // timer + CUR_GFX_LOWVIN = 32, // low input voltage CUR_GFX_M1_RECALL = 1024, CUR_GFX_M2_RECALL = 2048, @@ -722,6 +723,9 @@ static void activated(void) { // init state on? if (dpsmode_cfg_initstate) { dpsmode_enable(true); + screen->is_enabled = true; + screen->enable(screen->is_enabled); + opendps_update_power_status(screen->is_enabled); } } @@ -910,18 +914,27 @@ static void dpsmode_tick(void) } /** Determine if we are in CV or CC mode and display it */ + int32_t vin = pwrctl_calc_vin(v_in_raw); /** @todo: subtract for LDO */ int32_t vout_diff = abs(saved_v - vout_actual); int32_t cout_diff = abs(saved_i - cout_actual); - if (cout_diff < vout_diff) { + if (saved_v > vin) { + // we are limited by low input voltage + dpsmode_graphics |= CUR_GFX_LOWVIN; + dpsmode_graphics &= ~CUR_GFX_CV; + dpsmode_graphics &= ~CUR_GFX_CC; + + } else if (cout_diff < vout_diff) { // current diff smaller than voltage diff (constant current) dpsmode_graphics |= CUR_GFX_CC; dpsmode_graphics &= ~CUR_GFX_CV; + dpsmode_graphics &= ~CUR_GFX_LOWVIN; } else { // current diff larger than voltage diff (constant voltage) dpsmode_graphics |= CUR_GFX_CV; dpsmode_graphics &= ~CUR_GFX_CC; + dpsmode_graphics &= ~CUR_GFX_LOWVIN; } @@ -1035,7 +1048,7 @@ static void draw_bars() { GFX_CVBAR_WIDTH, GFX_CVBAR_HEIGHT, TFT_WIDTH - GFX_CVBAR_WIDTH, YPOS_VOLTAGE + FONT_METER_LARGE_MAX_GLYPH_HEIGHT - GFX_CVBAR_HEIGHT ); - } else { + } else if ( ! (dpsmode_graphics & (CUR_GFX_LOWVIN|CUR_GFX_CV))) { tft_fill(TFT_WIDTH - GFX_CVBAR_WIDTH, YPOS_VOLTAGE + FONT_METER_LARGE_MAX_GLYPH_HEIGHT - GFX_CVBAR_HEIGHT, GFX_CVBAR_WIDTH, GFX_CVBAR_HEIGHT, BLACK); @@ -1081,6 +1094,18 @@ static void draw_bars() { YPOS_POWER + FONT_METER_LARGE_MAX_GLYPH_HEIGHT - GFX_PPBAR_HEIGHT ); } + // draw low voltage warning at the constant voltage area + if (dpsmode_graphics & CUR_GFX_LOWVIN) { + tft_blit((uint16_t*) gfx_ppbar, + GFX_PPBAR_WIDTH, GFX_PPBAR_HEIGHT, + TFT_WIDTH - GFX_PPBAR_WIDTH, + YPOS_VOLTAGE + FONT_METER_LARGE_MAX_GLYPH_HEIGHT - GFX_PPBAR_HEIGHT ); + } else if ( ! (dpsmode_graphics & (CUR_GFX_LOWVIN|CUR_GFX_CV))) { + tft_fill(TFT_WIDTH - GFX_PPBAR_WIDTH, YPOS_VOLTAGE + FONT_METER_LARGE_MAX_GLYPH_HEIGHT - GFX_PPBAR_HEIGHT, + GFX_PPBAR_WIDTH, GFX_PPBAR_HEIGHT, + BLACK); + } + // no graphics at 3rd location, clear it. if ( ! (dpsmode_graphics & CUR_GFX_OPP || dpsmode_graphics & CUR_GFX_PP || dpsmode_graphics & CUR_GFX_TM)) { diff --git a/opendps/func_settings.c b/opendps/func_settings.c index fa6e8762..184083c2 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -68,7 +68,7 @@ #define ITEMS_PER_PAGE 5 // Total number of fields that can be edited -#define ITEMS 13 +#define ITEMS 14 // PAGES = ceil(ITEMS / ITEMS_PER_PAGE) #define PAGES (ITEMS+(ITEMS_PER_PAGE-1))/ITEMS_PER_PAGE @@ -193,7 +193,7 @@ struct field_item field_items[] = { {"Vin ADC K", -9999999, 9999999, 3, 4, unit_none, &get_vin_adc_c, &set_vin_adc_c }, // Initial output state - {"Init State", 0, 10000, 1, 0, unit_bool, &get_initstate, &set_initstate }, + {"PwrOnState", 0, 1, 1, 0, unit_bool, &get_initstate, &set_initstate }, {"Reset Cfg", 0, 10000, 1, 0, unit_bool, &get_resetcfg, &set_resetcfg }, }; @@ -515,10 +515,10 @@ static void set_resetcfg(struct ui_number_t *item) { } static int32_t get_initstate() { - return dpsmode_cfg_initstate ? 1 : 0; + return dpsmode_cfg_initstate & 0x01; } static void set_initstate(struct ui_number_t *item) { - dpsmode_cfg_initstate = (item->value == 1); + dpsmode_cfg_initstate = item->value & 0x01; } From b36c8838fda2fe67b8ccd84e53f0777715ecbdf2 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Wed, 9 Jun 2021 06:01:17 +0000 Subject: [PATCH 174/175] Ensure that DPS Mode screen will save values even when reading fails Possibly when nothing is initialized, past read will fail which causes the logic to not write the new value. I confirmed this behavior by erasing the flash and then attempting to save the last power setting which failed. --- opendps/func_dpsmode.c | 21 +++++++++++++++++++-- opendps/func_settings.c | 1 + 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/opendps/func_dpsmode.c b/opendps/func_dpsmode.c index 8674eb23..c9c0a9ed 100644 --- a/opendps/func_dpsmode.c +++ b/opendps/func_dpsmode.c @@ -475,15 +475,26 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { // save settings on power on if (past_read_unit(past, (SCREEN_ID << 24) | PAST_V, (const void**) &past_data, &length)) { if (*past_data != saved_v) past_write_unit(past, (SCREEN_ID << 24) | PAST_V, (void*) &saved_v, 4); + } else { + past_write_unit(past, (SCREEN_ID << 24) | PAST_V, (void*) &saved_v, 4); } + if (past_read_unit(past, (SCREEN_ID << 24) | PAST_I, (const void**) &past_data, &length)) { if (*past_data != saved_i) past_write_unit(past, (SCREEN_ID << 24) | PAST_I, (void*) &saved_i, 4); + } else { + past_write_unit(past, (SCREEN_ID << 24) | PAST_I, (void*) &saved_i, 4); } + if (past_read_unit(past, (SCREEN_ID << 24) | PAST_P, (const void**) &past_data, &length)) { if (*past_data != saved_p) past_write_unit(past, (SCREEN_ID << 24) | PAST_P, (void*) &saved_p, 4); + } else { + past_write_unit(past, (SCREEN_ID << 24) | PAST_P, (void*) &saved_p, 4); } + if (past_read_unit(past, (SCREEN_ID << 24) | PAST_T, (const void**) &past_data, &length)) { if (*past_data != saved_t) past_write_unit(past, (SCREEN_ID << 24) | PAST_T, (void*) &saved_t, 4); + } else { + past_write_unit(past, (SCREEN_ID << 24) | PAST_T, (void*) &saved_t, 4); } break; @@ -561,6 +572,9 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { saved_p = recall_p[0]; saved_t = recall_t[0]; + dpsmode_graphics &= ~CUR_GFX_M2_RECALL; + dpsmode_graphics |= CUR_GFX_M1_RECALL; + // Turn off power event_put(event_shutoff, 0); @@ -606,6 +620,9 @@ static bool event(uui_t *ui, event_t event, uint8_t data) { saved_p = recall_p[1]; saved_t = recall_t[1]; + dpsmode_graphics &= ~CUR_GFX_M1_RECALL; + dpsmode_graphics |= CUR_GFX_M2_RECALL; + // Turn off power event_put(event_shutoff, 0); @@ -1150,8 +1167,8 @@ static void clear_bars(bool all) { } // determine if M1/M2 settings match and enable those bars - if (recall_v[0] == saved_v && recall_i[0] == saved_i && recall_p[0] == saved_p && recall_t[0] == saved_t) dpsmode_graphics |= CUR_GFX_M1_RECALL; - if (recall_v[1] == saved_v && recall_i[1] == saved_i && recall_p[1] == saved_p && recall_t[1] == saved_t) dpsmode_graphics |= CUR_GFX_M2_RECALL; + if (recall_v[0] == saved_v && recall_i[0] == saved_i && recall_p[0] == saved_p && recall_t[0] == saved_t && saved_v != 0 && saved_i != 0) dpsmode_graphics |= CUR_GFX_M1_RECALL; + if (recall_v[1] == saved_v && recall_i[1] == saved_i && recall_p[1] == saved_p && recall_t[1] == saved_t && saved_v != 0 && saved_i != 0) dpsmode_graphics |= CUR_GFX_M2_RECALL; } diff --git a/opendps/func_settings.c b/opendps/func_settings.c index 184083c2..192e1f28 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -28,6 +28,7 @@ #include #include "hw.h" #include "func_settings.h" +#include "func_dpsmode.h" #include "uui.h" #include "uui_number.h" #include "dbg_printf.h" From 6d1ac51aef3da600f5e6138a80a0ac1dad9dc504 Mon Sep 17 00:00:00 2001 From: Leo Leung Date: Thu, 10 Jun 2021 05:05:28 +0000 Subject: [PATCH 175/175] Corrected incorrect C/K Vin setting labels --- opendps/func_settings.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opendps/func_settings.c b/opendps/func_settings.c index 192e1f28..ec991285 100644 --- a/opendps/func_settings.c +++ b/opendps/func_settings.c @@ -190,8 +190,8 @@ struct field_item field_items[] = { {"I ADC C", -9999999, 9999999, 3, 4, unit_none, &get_a_adc_c, &set_a_adc_c }, {"I DAC K", -9999999, 9999999, 3, 4, unit_none, &get_a_dac_k, &set_a_dac_k }, {"I DAC C", -9999999, 9999999, 3, 4, unit_none, &get_a_dac_c, &set_a_dac_c }, - {"Vin ADC C", -9999999, 9999999, 3, 4, unit_none, &get_vin_adc_k, &set_vin_adc_k }, - {"Vin ADC K", -9999999, 9999999, 3, 4, unit_none, &get_vin_adc_c, &set_vin_adc_c }, + {"Vin ADC K", -9999999, 9999999, 3, 4, unit_none, &get_vin_adc_k, &set_vin_adc_k }, + {"Vin ADC C", -9999999, 9999999, 3, 4, unit_none, &get_vin_adc_c, &set_vin_adc_c }, // Initial output state {"PwrOnState", 0, 1, 1, 0, unit_bool, &get_initstate, &set_initstate },

FY(xiVAgs;GwiWXnFO;GqFCjMwX(* zA7zwz#KA0ka8Y&lH>#! zPGG(yse<^6-I!Kj;Gyb32Zr7oJmwt-kLARECcdR3A1h{v+t^!|`wsjH;Oq(+8hTy_ z)-$5NQrAy+RT*m!4KrWp0w<3P=CDxvSamZC2F=fgFfPgvJzg2oUwHyL>`mS; zA~ZBY;DJ-gsR_}|hThLQ37woLI zZ0u|0(|e|kIqmKxd3j4%tt-3{cYUg-DU6{@=|Tz?;(~et3mZ)w28w7%Q-ap#wfqO6 z$M=ME>taNN84O~J1yh$K&VxKfQv(EBOnZ?u3r8WQ1Lkb3bDCJE>td+Bw}4OQ1@~4P zVoh#OWD`OzpHJg=q@8D9wxswoGSL31kLKJP;|Q2uGCjZ%b1xq{%;6YD@4=~VrBLc% zR>Id57q0;$S&Pg=C-SuV3Qvi1g!SnY=7=Nr2oE`o+M+k&nZcr93IYNTGjFmDWq>HE z@t>287VY6yUdf$m3e!t*%+{i46P_IN_tSqL^W+3RY;Yboh*ukKh*u3fZ}2ePV7>VL z{rAN0K)QIp_dfGhKTaHxq?nRMB<>Zzk69Hx-hc94ll{j>uhO?4*KbIA`jCF(GMC$G zU%w$@lI=Kv_Pm zy@(fq?26Q49>uVEw2v$c?TMspNhd9e)spHRZsRN3YM^jUFkvscdX_lp*q#6#18ZY!cL!;Ac5OC-t zVPj4A%JG`!b*C3>!7Kv3&VYT6_TftdsS_}bL1xH~0NF!)Ky)SgPapkQGNecOQdm4B zicYAF+gNya#bAsxfX>`zj=7XdvBbn!rZmrM+PJ5f$23YZ(6f-s z04u#?=07&#_Cd^7p+jJ1Dy5Ft1v zWKIizBRz>$M|zV}V)MBg(#Dc>^LWbR5lIo#r%juV4-^qE9pr(v5?>Su)szHbYUoTv z%mhZ0Ao9R60IE6;$dh9Ht1Dth097d#d+T&-i;DqB5kv6xLY>mD?tF1EtrL(_UC%WT z0{{svR!dh%>wlO)6+0v@FT$f+C&QD)kYX0Zs@h78(keh1q98rN4n^8|vX*PgOHyF+ zC41D=Jsx{I(!0~%yDhCduC>;)!_h5=y}WK6FK_Z?gFBW8U$;)m#!Dar`a?PiB6&6_ zfY89vc1r*e~HuyEVE%P53IhAo>e&T=#=G*0Ug5{d-o{ z7x=_)&Tqf6SiWM(^4Xd!*cI9!FZfJg3lBv{f(?`fL|7P#=#|vhu=hlx*d)B{LC=70enk^)I`28- z(hL;8wutl02;}Pl?heCPp?F0aD#g2yF1zZ!dP@FQ^K`)N0U*#!8IYtw;*d@2fI}Ol z>^0a;^5Db|M=siFveV!RiXgaJBfhl5A`v5?C(Mb}Z72=9h$8_3GaT^%u-2+Kwc!y; zLN-&B^M%Ukr@oy%I-!rbU7#sxbdt_sf2n%nxrAt0Hq>4on%X8iIWQzJ+vaGSZ5nZ^ zRHsXRAb0lVgm506Epr|&o4Oj_6(Tj)Zjfi&LQJww*QSje9hll6J5qyX`~?~eF{Mcr z>r6=%UAt!ohJ@#I?bo!bPj@*c)m~`|Nv$j$nl(mtjJCH42@DLMEUF!CW4hXg2I`6$ z60)PC17#BuiOvb^7*b&yBfx519TC${7t_x~Y+V3Hd!3U%0Df^`K+k~QXh2mW=SVQ5 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