From c3aead8a0632e9bbad28f0f57e4dedba9f922941 Mon Sep 17 00:00:00 2001 From: Richard Taylor Date: Tue, 25 May 2021 08:18:11 +0100 Subject: [PATCH 01/11] Fix LCD freezing on DPS5020 models. --- opendps/hw.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opendps/hw.h b/opendps/hw.h index 92447cb1..85650597 100644 --- a/opendps/hw.h +++ b/opendps/hw.h @@ -37,7 +37,7 @@ #define TFT_RST_PIN GPIO12 #define TFT_A0_PORT GPIOB #define TFT_A0_PIN GPIO14 -#ifdef DPS5015 +#if(defined DPS5015) || defined(DPS5020) #define TFT_CSN_PORT GPIOA #define TFT_CSN_PIN GPIO8 #endif From 548a4c5877ec9effe10e73210923ceedcbfd65ee Mon Sep 17 00:00:00 2001 From: Richard Taylor Date: Tue, 25 May 2021 08:27:49 +0100 Subject: [PATCH 02/11] Reduce jitter in ADC values / readings. Apply oversampling to the ADC values to reduce jitter (OVP / OCP) and LCD readings. --- opendps/hw.c | 85 +++++++++++++++++++++++----------------------------- 1 file changed, 37 insertions(+), 48 deletions(-) diff --git a/opendps/hw.c b/opendps/hw.c index 0b91ac70..d3f103c2 100644 --- a/opendps/hw.c +++ b/opendps/hw.c @@ -64,9 +64,12 @@ volatile uint16_t cur_time_hiw; #endif static volatile uint16_t i_out_adc; +static volatile uint32_t i_out_adc_ovs; static volatile uint16_t i_out_trig_adc; static volatile uint16_t v_in_adc; +static volatile uint32_t v_in_adc_ovs; static volatile uint16_t v_out_adc; +static volatile uint32_t v_out_adc_ovs; static volatile uint16_t v_out_trig_adc; static volatile uint64_t last_button_down; @@ -101,17 +104,10 @@ static volatile bool m1_and_m2_pressed = false; */ #define STARTUP_SKIP_COUNT (40) -/** Once we are checking for OCP, we need 20 over currents in a row to trigger - * OCP. This is due to spikes in the ADC readings. - * @todo Investigate if the spikes are real or is a DPS issue - */ -#define OCP_FILTER_COUNT (20) -/** Once we are checking for OVP, we need 20 over voltages in a row to trigger - * OVP. This is due to spikes in the ADC readings. - * @todo Investigate if the spikes are real or is a DPS issue - */ -#define OVP_FILTER_COUNT (20) +/** Apply ADC oversampling to reduce jitter in values */ +#define ADC_OVERSAMPLE_BITS (8) + #ifdef CONFIG_ADC_BENCHMARK static uint64_t adc_tick_start; @@ -291,20 +287,9 @@ bool hw_sel_button_pressed(void) */ static void handle_ocp(uint16_t raw) { - static uint32_t ocp_count = 0; - static uint32_t last_tick_counter = 0; - if (last_tick_counter+1 == adc_counter) { - ocp_count++; - last_tick_counter++; - if (ocp_count == OCP_FILTER_COUNT) { - i_out_trig_adc = raw; - pwrctl_enable_vout(false); - event_put(event_ocp, 0); - } - } else { - ocp_count = 0; - last_tick_counter = adc_counter; - } + i_out_trig_adc = raw; + pwrctl_enable_vout(false); + event_put(event_ocp, 0); } /** @@ -313,20 +298,9 @@ static void handle_ocp(uint16_t raw) */ static void handle_ovp(uint16_t raw) { - static uint32_t ovp_count = 0; - static uint32_t last_tick_counter = 0; - if (last_tick_counter+1 == adc_counter) { - ovp_count++; - last_tick_counter++; - if (ovp_count == OVP_FILTER_COUNT) { - v_out_trig_adc = raw; - pwrctl_enable_vout(false); - event_put(event_ovp, 0); - } - } else { - ovp_count = 0; - last_tick_counter = adc_counter; - } + v_out_trig_adc = raw; + pwrctl_enable_vout(false); + event_put(event_ovp, 0); } /** @@ -360,21 +334,36 @@ void adc1_2_isr(void) if (pwrctl_i_limit_raw) { if (adc_counter >= STARTUP_SKIP_COUNT) { i += adc_i_offset; - if (i > pwrctl_i_limit_raw && pwrctl_vout_enabled()) { /** OCP! */ - handle_ocp(i); - } - i_out_adc = i; + + i_out_adc_ovs -= i_out_adc_ovs >> ADC_OVERSAMPLE_BITS; + i_out_adc_ovs += i; + i_out_adc = i_out_adc_ovs >> ADC_OVERSAMPLE_BITS; } } - v_in_adc = adc_read_injected(ADC1, adc_cha_v_in + 1); // Yes, this is correct - v_out_adc = adc_read_injected(ADC1, adc_cha_v_out + 1); // Yes, this is correct + uint32_t v_in = adc_read_injected(ADC1, adc_cha_v_in + 1); // Yes, this is correct + uint32_t v_out = adc_read_injected(ADC1, adc_cha_v_out + 1); // Yes, this is correct + + v_in_adc_ovs -= v_in_adc_ovs >> ADC_OVERSAMPLE_BITS; + v_in_adc_ovs += v_in; + v_in_adc = v_in_adc_ovs >> ADC_OVERSAMPLE_BITS; - /** Check to see if an over voltage limit has been triggered */ - if (pwrctl_v_limit_raw) { - if (v_out_adc > pwrctl_v_limit_raw && pwrctl_vout_enabled()) { /** OVP! */ - handle_ovp(v_out_adc); + v_out_adc_ovs -= v_out_adc_ovs >> ADC_OVERSAMPLE_BITS; + v_out_adc_ovs += v_out; + v_out_adc = v_out_adc_ovs >> ADC_OVERSAMPLE_BITS; + + if (pwrctl_vout_enabled()) { + /** Check to see if an over voltage limit has been triggered */ + if (pwrctl_v_limit_raw) { + if (v_out_adc > pwrctl_v_limit_raw) { /** OVP! */ + handle_ovp(v_out_adc); + } } + + /** Check to see if an over current limit has been triggered */ + if (i_out_adc > pwrctl_i_limit_raw) { /** OCP! */ + handle_ocp(i); + } } #ifdef CONFIG_FUNCGEN_ENABLE From 77a1b932d26939c2e357f70cc68c8a74461032dd Mon Sep 17 00:00:00 2001 From: Richard Taylor Date: Tue, 25 May 2021 19:11:54 +0100 Subject: [PATCH 03/11] Add limit checking to fast loop. Turn output off if v_in drops below threshold for current output voltage. Control the fan automatically on DPS5020 to mimic original firmware. --- opendps/hw.c | 4 +--- opendps/pwrctl.c | 40 +++++++++++++++++++++++++++++++++++----- opendps/pwrctl.h | 14 ++++++++++---- 3 files changed, 46 insertions(+), 12 deletions(-) diff --git a/opendps/hw.c b/opendps/hw.c index d3f103c2..98cec3d8 100644 --- a/opendps/hw.c +++ b/opendps/hw.c @@ -104,11 +104,9 @@ static volatile bool m1_and_m2_pressed = false; */ #define STARTUP_SKIP_COUNT (40) - /** Apply ADC oversampling to reduce jitter in values */ #define ADC_OVERSAMPLE_BITS (8) - #ifdef CONFIG_ADC_BENCHMARK static uint64_t adc_tick_start; #endif // CONFIG_ADC_BENCHMARK @@ -361,7 +359,7 @@ void adc1_2_isr(void) } /** Check to see if an over current limit has been triggered */ - if (i_out_adc > pwrctl_i_limit_raw) { /** OCP! */ + if (i_out_adc > pwrctl_i_limit_raw || !pwrctl_check_limits()) { /** OCP! */ handle_ocp(i); } } diff --git a/opendps/pwrctl.c b/opendps/pwrctl.c index fc902089..0120ae6e 100644 --- a/opendps/pwrctl.c +++ b/opendps/pwrctl.c @@ -25,6 +25,7 @@ #include "pwrctl.h" #include "dps-model.h" #include "pastunits.h" +#include "hw.h" #include #include @@ -33,7 +34,7 @@ * https://docs.google.com/spreadsheets/d/1AhGsU_gvZjqZyr2ZYrnkz6BeUqMquzh9UNYoTqy_Zp4/edit?usp=sharing */ -static uint32_t i_out, v_out, i_limit, v_limit; +static uint32_t i_out, v_out, i_limit, v_limit, vin_limit; static bool v_out_enabled; float a_adc_k_coef = A_ADC_K; @@ -106,6 +107,10 @@ bool pwrctl_set_vout(uint32_t value_mv) { /** @todo Check with max Vout, currently filtered by ui.c */ v_out = value_mv; + + /** Set the vin limit so we turn off if the input voltage drops too low */ + vin_limit = v_out * VIN_VOUT_RATIO + 0.5f; + if (v_out_enabled) { /** Needed for the DPS5005 "communications version" (the one with BT/USB) */ DAC_DHR12R1 = pwrctl_calc_vout_dac(v_out); @@ -202,8 +207,6 @@ void pwrctl_enable_vout(bool enable) { v_out_enabled = enable; if (v_out_enabled) { - (void) pwrctl_set_vout(v_out); - (void) pwrctl_set_iout(i_out); #if defined(DPS5015) || defined(DPS5020) //gpio_clear(GPIOA, GPIO9); // this is power control on '5015 gpio_set(GPIOB, GPIO11); // B11 is fan control on '5015 @@ -219,11 +222,38 @@ void pwrctl_enable_vout(bool enable) #else gpio_set(GPIOB, GPIO11); // B11 is power control on '5005 #endif - (void) pwrctl_set_vout(v_out); - (void) pwrctl_set_iout(i_out); } + + (void) pwrctl_set_vout(v_out); + (void) pwrctl_set_iout(i_out); } +/** + * @brief Check that we are operating within set limits + * @retval Bool: Handled / Not Handled (i.e. power off) + */ +bool pwrctl_check_limits(void) +{ + bool ret = true; + uint16_t i_out_raw, v_in_raw, v_out_raw; + hw_get_adc_values(&i_out_raw, &v_in_raw, &v_out_raw); + + if (pwrctl_calc_vin(v_in_raw) < vin_limit) { + pwrctl_enable_vout(false); + ret = false; + } + +#if defined(DPS5015) || defined(DPS5020) + /** Control the fan for DPS5020 (stock firmware enables fan above 10A) */ + if (pwrctl_calc_iout(i_out_raw) > 5000) + gpio_set(GPIOB, GPIO11); + else + gpio_clear(GPIOB, GPIO11); +#endif + + return ret; + } + /** * @brief Return power output status * @retval true if power output is enabled diff --git a/opendps/pwrctl.h b/opendps/pwrctl.h index 43f51ebb..5f2d83b6 100644 --- a/opendps/pwrctl.h +++ b/opendps/pwrctl.h @@ -49,14 +49,14 @@ extern float vin_adc_c_coef; void pwrctl_init(past_t *past); /** - * @brief Set voltage output + * @brief Set voltage output (HW controlled) * @param value_mv voltage in millivolt * @retval true requested voltage was within specs */ bool pwrctl_set_vout(uint32_t value_mv); /** - * @brief Set current output + * @brief Set current output (HW controlled) * @param value_ma current in milli ampere * @retval true requested current was within specs */ @@ -75,7 +75,7 @@ uint32_t pwrctl_get_iout(void); uint32_t pwrctl_get_vout(void); /** - * @brief Set current limit + * @brief Set current limit (SW limit used for OCP) * @param value_ma limit in milliampere * @retval true requested current was within specs */ @@ -88,7 +88,7 @@ bool pwrctl_set_ilimit(uint32_t value_ma); uint32_t pwrctl_get_ilimit(void); /** - * @brief Set voltage limit + * @brief Set voltage limit (SW limit used for OVP) * @param value_mv limit in millivolts * @retval true requested voltage was within specs */ @@ -107,6 +107,12 @@ uint32_t pwrctl_get_vlimit(void); */ void pwrctl_enable_vout(bool enable); +/** + * @brief Check that we are operating within set limits + * @retval Bool: Handled / Not Handled (i.e. power off) + */ +bool pwrctl_check_limits(void); + /** * @brief Return power output status * @retval true if power output is enabled From dd035a2b551d2e768081ed781d60df0f2eae901e Mon Sep 17 00:00:00 2001 From: Richard Taylor Date: Tue, 25 May 2021 19:24:42 +0100 Subject: [PATCH 04/11] Add 'W' character to font sets. --- opendps/font-meter_large.c | 27 +++++++++++++++++++++++---- opendps/font-meter_large.h | 6 +++--- opendps/font-meter_medium.c | 14 ++++++++++---- opendps/font-meter_medium.h | 6 +++--- opendps/font-meter_small.c | 12 ++++++++---- opendps/font-meter_small.h | 6 +++--- opendps/gen_lookup.py | 8 ++++---- opendps/uui_number.c | 4 ++++ 8 files changed, 58 insertions(+), 25 deletions(-) diff --git a/opendps/font-meter_large.c b/opendps/font-meter_large.c index 6d18533d..4e83ab30 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 = 35; -const uint8_t font_meter_large_pixdata[1745] = { +const uint8_t font_meter_large_pixdata[2025] = { /* '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, @@ -132,6 +132,25 @@ const uint8_t font_meter_large_pixdata[1745] = { 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, + /* 'W', offset=1745 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xfe, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0x02, 0x00, 0xf0, 0x1f, 0x00, 0x40, 0xff, + 0xfd, 0x03, 0x00, 0xf4, 0x2f, 0x00, 0x40, 0xbf, 0xfd, 0x03, 0x00, 0xf4, 0x3f, 0x00, 0x40, 0xbf, + 0xfc, 0x03, 0x00, 0xf8, 0x3f, 0x00, 0x80, 0x7f, 0xfc, 0x03, 0x00, 0xfc, 0x7f, 0x00, 0x80, 0x7f, + 0xfc, 0x03, 0x00, 0xfc, 0xbf, 0x00, 0xc0, 0x3f, 0xf8, 0x07, 0x00, 0xfd, 0xfe, 0x00, 0xc0, 0x3f, + 0xf8, 0x07, 0x00, 0xbe, 0xfd, 0x00, 0xc0, 0x3f, 0xf4, 0x0b, 0x00, 0xbf, 0xfc, 0x01, 0xc0, 0x2f, + 0xf4, 0x0f, 0x00, 0x7f, 0xfc, 0x02, 0xd0, 0x2f, 0xf0, 0x0f, 0x40, 0x3f, 0xfc, 0x03, 0xd0, 0x1f, + 0xf0, 0x0f, 0x80, 0x3f, 0xf8, 0x03, 0xe0, 0x0f, 0xf0, 0x0f, 0xc0, 0x2f, 0xf4, 0x07, 0xe0, 0x0f, + 0xe0, 0x1f, 0xc0, 0x1f, 0xf0, 0x0b, 0xf0, 0x0f, 0xd0, 0x1f, 0xd0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0b, + 0xd0, 0x2f, 0xe0, 0x0f, 0xe0, 0x0f, 0xf0, 0x0b, 0xc0, 0x3f, 0xf0, 0x0b, 0xd0, 0x1f, 0xf4, 0x07, + 0xc0, 0x3f, 0xf0, 0x07, 0xc0, 0x2f, 0xf4, 0x03, 0x80, 0x3f, 0xf4, 0x03, 0x80, 0x3f, 0xf8, 0x03, + 0x80, 0x7f, 0xf8, 0x02, 0x40, 0x3f, 0xfc, 0x03, 0x40, 0x7f, 0xfc, 0x01, 0x00, 0x7f, 0xfc, 0x02, + 0x00, 0xbf, 0xfd, 0x00, 0x00, 0xbf, 0xfc, 0x01, 0x00, 0xff, 0xfe, 0x00, 0x00, 0xfe, 0xfd, 0x00, + 0x00, 0xfe, 0xbf, 0x00, 0x00, 0xfd, 0xff, 0x00, 0x00, 0xfd, 0x7f, 0x00, 0x00, 0xfc, 0xbf, 0x00, + 0x00, 0xfc, 0x3f, 0x00, 0x00, 0xf8, 0xbf, 0x00, 0x00, 0xfc, 0x2f, 0x00, 0x00, 0xf4, 0x7f, 0x00, + 0x00, 0xfc, 0x1f, 0x00, 0x00, 0xf0, 0x3f, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xf0, 0x3f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; const uint8_t font_meter_large_widths[96] = { @@ -141,7 +160,7 @@ const uint8_t font_meter_large_widths[96] = { 16u, 15u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 22u, 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, 22u, 32u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, @@ -156,7 +175,7 @@ const uint8_t font_meter_large_sizes[96] = { 140u, 132u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 193u, 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, 193u, 280u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, @@ -171,7 +190,7 @@ const uint16_t font_meter_large_offsets[96] = { 1043u, 1183u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 1552u, 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, 1359u, 1745u, 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 5a145c45..12fa454f 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 (35) -#define FONT_METER_LARGE_MAX_GLYPH_WIDTH (22) +#define FONT_METER_LARGE_MAX_GLYPH_WIDTH (32) #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_SPACING (6) #define FONT_METER_LARGE_SPACE_WIDTH (9) 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[2025]; #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 4b53740e..c632e601 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 = 17; -const uint8_t font_meter_medium_pixdata[444] = { +const uint8_t font_meter_medium_pixdata[512] = { /* '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, @@ -54,6 +54,12 @@ const uint8_t font_meter_medium_pixdata[444] = { 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, + /* 'W', offset=444 */ + 0x0f, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0xf0, 0x1e, 0xc0, 0x07, 0xf0, 0x1e, 0xd0, 0x07, 0xf0, + 0x2d, 0xd0, 0x0b, 0xb4, 0x2d, 0xe0, 0x0f, 0x74, 0x3c, 0xb0, 0x0e, 0x78, 0x3c, 0x70, 0x1d, 0x38, + 0x3c, 0x74, 0x2c, 0x3c, 0x38, 0x38, 0x3c, 0x3c, 0x78, 0x3c, 0x38, 0x2c, 0xb4, 0x2c, 0x74, 0x2d, + 0xb0, 0x0d, 0xb0, 0x1d, 0xf0, 0x0e, 0xf0, 0x0e, 0xf0, 0x0b, 0xe0, 0x0f, 0xe0, 0x07, 0xd0, 0x0b, + 0xd0, 0x03, 0xc0, 0x07, }; const uint8_t font_meter_medium_widths[96] = { @@ -63,7 +69,7 @@ const uint8_t font_meter_medium_widths[96] = { 8u, 8u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 12u, 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, 11u, 16u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, @@ -78,7 +84,7 @@ const uint8_t font_meter_medium_sizes[96] = { 34u, 34u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 51u, 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, 47u, 68u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, @@ -93,7 +99,7 @@ const uint16_t font_meter_medium_offsets[96] = { 265u, 299u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 393u, 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, 346u, 444u, 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 896fd21c..23379886 100644 --- a/opendps/font-meter_medium.h +++ b/opendps/font-meter_medium.h @@ -6,16 +6,16 @@ #include #define FONT_METER_MEDIUM_MAX_GLYPH_HEIGHT (17) -#define FONT_METER_MEDIUM_MAX_GLYPH_WIDTH (12) +#define FONT_METER_MEDIUM_MAX_GLYPH_WIDTH (16) #define FONT_METER_MEDIUM_MAX_DIGIT_WIDTH (9) #define FONT_METER_MEDIUM_DOT_WIDTH (3) -#define FONT_METER_MEDIUM_SPACING (2) +#define FONT_METER_MEDIUM_SPACING (3) #define FONT_METER_MEDIUM_SPACE_WIDTH (5) 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[512]; #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 abfd791e..cc6cd9a0 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[234] = { +const uint8_t font_meter_small_pixdata[270] = { /* '0', offset=0 */ 0xf8, 0xd1, 0x34, 0x0f, 0xb7, 0xb0, 0x0b, 0xbb, 0xf0, 0x0b, 0xbf, 0xb0, 0x0b, 0xfb, 0x70, 0x4d, 0x83, 0x1f, @@ -41,6 +41,10 @@ const uint8_t font_meter_small_pixdata[234] = { /* '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, + /* 'W', offset=234 */ + 0x07, 0x00, 0xf0, 0x0b, 0x2c, 0xb0, 0x0b, 0x3d, 0xb0, 0x0b, 0x3e, 0x70, 0x0e, 0x77, 0x70, 0x0e, + 0xa7, 0x34, 0x4d, 0xd3, 0x38, 0x9c, 0xc2, 0x28, 0xdc, 0xc1, 0x2d, 0xf8, 0x80, 0x1f, 0xf4, 0x40, + 0x0f, 0xb4, 0x00, 0x0f, }; const uint8_t font_meter_small_widths[96] = { @@ -50,7 +54,7 @@ const uint8_t font_meter_small_widths[96] = { 6u, 6u, 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, 12u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, @@ -65,7 +69,7 @@ const uint8_t font_meter_small_sizes[96] = { 18u, 18u, 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, 36u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, @@ -80,7 +84,7 @@ const uint16_t font_meter_small_offsets[96] = { 138u, 156u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 207u, 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, 180u, 234u, 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 cbe6a11f..64cea40f 100644 --- a/opendps/font-meter_small.h +++ b/opendps/font-meter_small.h @@ -6,16 +6,16 @@ #include #define FONT_METER_SMALL_MAX_GLYPH_HEIGHT (12) -#define FONT_METER_SMALL_MAX_GLYPH_WIDTH (9) +#define FONT_METER_SMALL_MAX_GLYPH_WIDTH (12) #define FONT_METER_SMALL_MAX_DIGIT_WIDTH (6) #define FONT_METER_SMALL_DOT_WIDTH (2) -#define FONT_METER_SMALL_SPACING (1) +#define FONT_METER_SMALL_SPACING (2) #define FONT_METER_SMALL_SPACE_WIDTH (4) 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[270]; #endif // __FONT_METER_SMALL_H__ \ No newline at end of file diff --git a/opendps/gen_lookup.py b/opendps/gen_lookup.py index 48fcaccd..24dcd590 100644 --- a/opendps/gen_lookup.py +++ b/opendps/gen_lookup.py @@ -56,7 +56,7 @@ def image_to_bgr565(im): Generate the lookup table for bytes consisting of packed 2bpp pixels """ def generate_pixel_lookup_table(output_filename): - print "Generating lookup table for pixels as %s.c/.h" % (output_filename) + print("Generating lookup table for pixels as %s.c/.h", output_filename) source_filename = "%s.c" % (output_filename) header_filename = "%s.h" % (output_filename) @@ -155,7 +155,7 @@ def get_space_width(font_fname, font_size): Convert the specified font to a pair of .c/.h C language lookup tables in mono 2bpp format """ def convert_font_to_c(font_fname, characters, font_size, font_spacing, output_filename): - print "Converting %s %dpt to font-%s.c/h" % (font_fname, font_size, output_filename) + print("Converting %s %dpt to font-%s.c/h", font_fname, font_size, output_filename) character_images = generate_font_images(font_fname, characters, font_size) (_, character_heights) = character_images[0].size @@ -294,7 +294,7 @@ def convert_font_to_c(font_fname, characters, font_size, font_spacing, output_fi Convert the specified font to a pair of .c/.h C language lookup tables in BGR565 format """ def convert_graphic_to_c(graphic_fname, output_filename): - print "Converting %s to gfx-%s.c/h" % (graphic_fname, output_filename) + print("Converting %s to gfx-%s.c/h", graphic_fname, output_filename) graphic_image = Image.open(graphic_fname) @@ -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/uui_number.c b/opendps/uui_number.c index d91908ce..1c433ce7 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: @@ -312,6 +313,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 7b574b6c5a90d478cb9bd4e00f38777f458af5e7 Mon Sep 17 00:00:00 2001 From: Richard Taylor Date: Tue, 25 May 2021 19:25:37 +0100 Subject: [PATCH 05/11] Fix assert code in CONFIG_RELEASE mode. --- opendps/my_assert.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opendps/my_assert.h b/opendps/my_assert.h index 1749bfc3..80780308 100644 --- a/opendps/my_assert.h +++ b/opendps/my_assert.h @@ -29,7 +29,7 @@ #include "dbg_printf.h" #ifdef CONFIG_RELEASE - #define assert(x) scb_reset_system() + #define assert(x) if (!(x)) { scb_reset_system(); } #else // CONFIG_RELEASE #define assert(x) if (!(x)) { dbg_printf("Assertion %s failed on line %d of %s\n", #x, __LINE__, __FILE__); while(1); } #endif // CONFIG_RELEASE From 427e623428614f8c2e773f3d974b2e574b37c15d Mon Sep 17 00:00:00 2001 From: Richard Taylor Date: Tue, 25 May 2021 19:32:12 +0100 Subject: [PATCH 06/11] Add Watts display and implement original CC/CV behaviour. This replaces CC / CV / CL with a CCCV screen. The use of a SW i_limit is replaced with the HW DAC for limiting current. This makes the unit behave much like the original, without the SW limit cutting power. The SW limit is now set to the maximum output current supported by the DPS model. --- opendps/Makefile | 45 +--- opendps/dps-model.h | 4 +- opendps/font-meter_large.c | 286 +++++++++----------- opendps/font-meter_large.h | 14 +- opendps/func_cc.c | 358 ------------------------- opendps/func_cc.h | 37 --- opendps/{func_cv.c => func_cccv.c} | 187 +++++++------ opendps/{func_cv.h => func_cccv.h} | 10 +- opendps/func_cl.c | 406 ----------------------------- opendps/func_cl.h | 37 --- opendps/gfx-cccv.c | 85 ++++++ opendps/gfx-cccv.h | 13 + opendps/opendps.c | 34 +-- opendps/uui.h | 11 +- opendps/uui_number.c | 2 + 15 files changed, 379 insertions(+), 1150 deletions(-) delete mode 100644 opendps/func_cc.c delete mode 100644 opendps/func_cc.h rename opendps/{func_cv.c => func_cccv.c} (68%) rename opendps/{func_cv.h => func_cccv.h} (88%) delete mode 100644 opendps/func_cl.c delete mode 100644 opendps/func_cl.h create mode 100644 opendps/gfx-cccv.c create mode 100644 opendps/gfx-cccv.h diff --git a/opendps/Makefile b/opendps/Makefile index 1ee30863..dc4fce47 100644 --- a/opendps/Makefile +++ b/opendps/Makefile @@ -34,7 +34,7 @@ WDOG ?= 1 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 ?= 40 FULL_FONT_FILE ?= gfx/ProggyClean.ttf FULL_FONT_SMALL_SIZE ?= 16 @@ -49,14 +49,8 @@ COLOR_INPUT ?= WHITE # Optional tinting for UI elements TINT ?= ffffff -# Enable CC mode -CC_ENABLE ?= 1 - -# Enable CV mode -CV_ENABLE ?= 1 - -# Enable cl mode -CL_ENABLE ?= 1 +# Enable CC/CV mode +CCCV_ENABLE ?= 1 # Enable function generator mode FUNCGEN_ENABLE ?= 1 @@ -110,10 +104,7 @@ OBJS = \ font-meter_small.o \ font-meter_medium.o \ font-meter_large.o \ - gfx-cc.o \ gfx-crosshair.o \ - gfx-cv.o \ - gfx-cl.o \ gfx-padlock.o \ gfx-thermometer.o \ gfx-wifi.o \ @@ -124,8 +115,10 @@ ifdef MAX_CURRENT endif ifeq ($(DEBUG),1) - CFLAGS +=-DCONFIG_DEBUG + CFLAGS +=-DCONFIG_DEBUG -g -O1 OBJS += dbg_printf.o +else + CFLAGS +=-DCONFIG_RELEASE -g -Os endif ifeq ($(WDOG),1) @@ -149,19 +142,9 @@ ifeq ($(POWER_OFF_VISIBLE),1) CFLAGS +=-DCONFIG_POWER_OFF_VISIBLE endif -ifeq ($(CC_ENABLE),1) - CFLAGS +=-DCONFIG_CC_ENABLE - 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 +ifeq ($(CCCV_ENABLE),1) + CFLAGS +=-DCONFIG_CCCV_ENABLE + OBJS += func_cccv.o gfx-cccv.o endif ifeq ($(FUNCGEN_ENABLE),1) @@ -192,11 +175,11 @@ endif include ../libopencm3.target.mk fonts: - @python ./gen_lookup.py -l -o gfx_lookup - @python ./gen_lookup.py -f $(FULL_FONT_FILE) -s $(FULL_FONT_SMALL_SIZE) -o full_small -a - @python ./gen_lookup.py -f $(METER_FONT_FILE) -s $(METER_FONT_SMALL_SIZE) -o meter_small - @python ./gen_lookup.py -f $(METER_FONT_FILE) -s $(METER_FONT_MEDIUM_SIZE) -o meter_medium - @python ./gen_lookup.py -f $(METER_FONT_FILE) -s $(METER_FONT_LARGE_SIZE) -o meter_large + @python2 ./gen_lookup.py -l -o gfx_lookup + @python2 ./gen_lookup.py -f $(FULL_FONT_FILE) -s $(FULL_FONT_SMALL_SIZE) -o full_small -a + @python2 ./gen_lookup.py -f $(METER_FONT_FILE) -s $(METER_FONT_SMALL_SIZE) -o meter_small + @python2 ./gen_lookup.py -f $(METER_FONT_FILE) -s $(METER_FONT_MEDIUM_SIZE) -o meter_medium + @python2 ./gen_lookup.py -f $(METER_FONT_FILE) -s $(METER_FONT_LARGE_SIZE) -o meter_large test: @make -C tests diff --git a/opendps/dps-model.h b/opendps/dps-model.h index 54fe4e9c..f45060c0 100644 --- a/opendps/dps-model.h +++ b/opendps/dps-model.h @@ -44,7 +44,7 @@ /** Contribution by @cleverfox */ #if defined(DPS5020) #ifndef CONFIG_DPS_MAX_CURRENT - #define CONFIG_DPS_MAX_CURRENT (20000) // Please note that the UI currently does not handle settings larger that 9.99A + #define CONFIG_DPS_MAX_CURRENT (20000) #endif #define CURRENT_DIGITS 2 #define CURRENT_DECIMALS 2 @@ -150,6 +150,6 @@ #define VIN_ADC_C (float)64.112f #endif -#define VIN_VOUT_RATIO (float)1.1f /** (Vin / VIN_VOUT_RATIO) = Max Vout */ +#define VIN_VOUT_RATIO (float)1.1f /** (Vin / VIN_VOUT_RATIO) = Max Vout (or Min Vin) */ #endif // __DPS_MODEL_H__ diff --git a/opendps/font-meter_large.c b/opendps/font-meter_large.c index 4e83ab30..92983bfb 100644 --- a/opendps/font-meter_large.c +++ b/opendps/font-meter_large.c @@ -1,166 +1,126 @@ -/** Font generated from `./gen_lookup.py -f gfx/Ubuntu-C.ttf -s 48 -o meter_large` */ +/** Font generated from `./gen_lookup.py -f gfx/Ubuntu-C.ttf -s 40 -o meter_large` */ #include "font-meter_large.h" -const uint32_t font_meter_large_height = 35; -const uint8_t font_meter_large_pixdata[2025] = { +const uint32_t font_meter_large_height = 29; +const uint8_t font_meter_large_pixdata[1415] = { /* '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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xfe, 0x06, 0x40, 0xff, 0x7f, 0x00, 0xff, 0xff, 0x03, 0xfe, 0xd1, 0x3f, 0xfc, 0x02, 0xfd, + 0xf0, 0x07, 0xf0, 0xd7, 0x0f, 0xc0, 0xaf, 0x3f, 0x00, 0xff, 0xfe, 0x00, 0xf8, 0xff, 0x03, 0xe0, + 0xff, 0x0b, 0x80, 0xff, 0x2f, 0x00, 0xfe, 0xbf, 0x00, 0xf4, 0xff, 0x02, 0xd0, 0xff, 0x0b, 0x40, + 0xff, 0x2f, 0x00, 0xfd, 0xbf, 0x00, 0xf8, 0xff, 0x02, 0xe0, 0xff, 0x0f, 0x80, 0xbf, 0x3f, 0x00, + 0xfe, 0xfe, 0x00, 0xfc, 0xf7, 0x03, 0xf0, 0xcb, 0x1f, 0xc0, 0x1f, 0xbf, 0x40, 0x3f, 0xf8, 0x47, + 0xff, 0xc0, 0xff, 0xff, 0x00, 0xfd, 0xff, 0x01, 0x80, 0xbf, 0x01, 0x00, 0x00, 0x00, 0x00, + /* '1', offset=95 */ + 0x00, 0xfc, 0x00, 0xfe, 0x80, 0xff, 0xe0, 0xff, 0xf8, 0xff, 0xff, 0xff, 0x7e, 0xfd, 0x0c, 0xfd, + 0x00, 0xfd, 0x00, 0xfd, 0x00, 0xfd, 0x00, 0xfd, 0x00, 0xfd, 0x00, 0xfd, 0x00, 0xfd, 0x00, 0xfd, + 0x00, 0xfd, 0x00, 0xfd, 0x00, 0xfd, 0x00, 0xfd, 0x00, 0xfd, 0x00, 0xfd, 0x00, 0xfd, 0x00, 0xfd, + 0x00, 0xfd, 0x00, 0xfd, 0x00, 0xfd, 0x00, 0xfd, 0x00, 0x00, + /* '2', offset=153 */ + 0x90, 0xff, 0x02, 0xf4, 0xff, 0x7f, 0xf0, 0xff, 0xff, 0x43, 0x1f, 0xf0, 0x2f, 0x04, 0x00, 0xff, + 0x00, 0x00, 0xf8, 0x03, 0x00, 0xd0, 0x0f, 0x00, 0x40, 0x3f, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfc, + 0x03, 0x00, 0xf0, 0x07, 0x00, 0xe0, 0x0f, 0x00, 0xd0, 0x2f, 0x00, 0xc0, 0x3f, 0x00, 0x80, 0x7f, + 0x00, 0x40, 0xbf, 0x00, 0x00, 0xff, 0x00, 0x00, 0xfe, 0x01, 0x00, 0xfd, 0x02, 0x00, 0xfc, 0x03, + 0x00, 0xf4, 0x07, 0x00, 0xe0, 0x0f, 0x00, 0xc0, 0x2f, 0x00, 0x00, 0x7f, 0x00, 0x00, 0xfd, 0x00, + 0x00, 0xf8, 0xff, 0xff, 0xef, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + /* '3', offset=248 */ + 0xe0, 0xbf, 0x00, 0xf4, 0xff, 0x2f, 0xe0, 0xff, 0xff, 0x01, 0x0b, 0xf4, 0x0f, 0x00, 0x40, 0x7f, + 0x00, 0x00, 0xfc, 0x02, 0x00, 0xf0, 0x0b, 0x00, 0x80, 0x2f, 0x00, 0x00, 0xbf, 0x00, 0x00, 0xfc, + 0x01, 0x00, 0xf8, 0x03, 0x00, 0xfd, 0x07, 0xd0, 0xff, 0x07, 0x40, 0xff, 0x0b, 0x00, 0xfd, 0xff, + 0x01, 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xf4, 0x03, 0x00, 0xc0, 0x1f, 0x00, 0x00, + 0x7f, 0x00, 0x00, 0xfc, 0x01, 0x00, 0xf0, 0x07, 0x00, 0xd0, 0x0f, 0x00, 0xc0, 0x3f, 0x1e, 0xd0, + 0xbf, 0xfc, 0xff, 0xff, 0xf0, 0xff, 0xff, 0x00, 0xf9, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, + /* '4', offset=343 */ + 0x00, 0x40, 0x7f, 0x00, 0x00, 0xfc, 0x07, 0x00, 0xd0, 0x7f, 0x00, 0x00, 0xff, 0x07, 0x00, 0xf8, + 0x7f, 0x00, 0xc0, 0xef, 0x07, 0x00, 0x7e, 0x7e, 0x00, 0xf0, 0xe3, 0x07, 0x40, 0x1f, 0x7e, 0x00, + 0xfc, 0xe0, 0x07, 0xd0, 0x07, 0x7e, 0x00, 0x3f, 0xe0, 0x07, 0xf0, 0x02, 0x7e, 0x80, 0x0f, 0xe0, + 0x07, 0xfc, 0x00, 0x7e, 0xd0, 0x07, 0xe0, 0x07, 0x3e, 0x00, 0x7e, 0xf0, 0x03, 0xe0, 0x07, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x7e, + 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x7e, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x7e, 0x00, 0x00, + 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, + /* '5', offset=445 */ + 0xd0, 0xff, 0xff, 0x40, 0xff, 0xff, 0x03, 0xfd, 0xff, 0x0f, 0xf8, 0x02, 0x00, 0xe0, 0x0b, 0x00, + 0x80, 0x1f, 0x00, 0x00, 0x7e, 0x00, 0x00, 0xf8, 0x01, 0x00, 0xe0, 0x07, 0x00, 0xc0, 0x1f, 0x00, + 0x00, 0x3f, 0x00, 0x00, 0xfc, 0x1b, 0x00, 0xf0, 0xff, 0x07, 0xc0, 0xff, 0xbf, 0x00, 0x90, 0xff, + 0x07, 0x00, 0xe0, 0x3f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xf4, 0x07, 0x00, 0xc0, 0x1f, 0x00, 0x00, + 0x7f, 0x00, 0x00, 0xfc, 0x01, 0x00, 0xf0, 0x07, 0x00, 0xe0, 0x0f, 0x00, 0xc0, 0x2f, 0x18, 0xd0, + 0x3f, 0xf8, 0xff, 0x7f, 0xf0, 0xff, 0x7f, 0x00, 0xf9, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, + /* '6', offset=540 */ + 0x00, 0x00, 0xb9, 0x00, 0x80, 0xff, 0x02, 0xc0, 0xff, 0x0f, 0xc0, 0xff, 0x06, 0x80, 0xbf, 0x00, + 0x00, 0xbf, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfc, 0x01, 0x00, 0xf4, 0x03, 0x00, 0xf0, 0x0b, 0x00, + 0xc0, 0x1f, 0x00, 0x00, 0xbf, 0xfe, 0x02, 0xfd, 0xff, 0x3f, 0xf4, 0xff, 0xff, 0xd3, 0x2f, 0xe0, + 0x5f, 0x3f, 0x00, 0xff, 0xfd, 0x00, 0xf4, 0xf7, 0x03, 0xd0, 0xdf, 0x0f, 0x00, 0x7f, 0x3f, 0x00, + 0xfc, 0xfc, 0x00, 0xf0, 0xf3, 0x07, 0xd0, 0xcf, 0x1f, 0x40, 0x3f, 0xfe, 0x00, 0xff, 0xf0, 0x0b, + 0xfe, 0x81, 0xff, 0xff, 0x03, 0xfc, 0xff, 0x03, 0x40, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, + /* '7', offset=635 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xbf, 0x00, 0x00, 0xfd, + 0x00, 0x00, 0xfc, 0x02, 0x00, 0xf4, 0x03, 0x00, 0xe0, 0x0f, 0x00, 0xc0, 0x1f, 0x00, 0x40, 0x3f, + 0x00, 0x00, 0xbe, 0x00, 0x00, 0xfc, 0x01, 0x00, 0xf4, 0x03, 0x00, 0xe0, 0x0b, 0x00, 0xc0, 0x1f, + 0x00, 0x00, 0x3f, 0x00, 0x00, 0xfd, 0x00, 0x00, 0xf8, 0x02, 0x00, 0xf0, 0x07, 0x00, 0xc0, 0x0f, + 0x00, 0x40, 0x3f, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xf8, 0x02, 0x00, 0xf0, 0x0b, 0x00, 0xc0, 0x1f, + 0x00, 0x00, 0x7f, 0x00, 0x00, 0xfd, 0x00, 0x00, 0xf4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + /* '8', offset=730 */ + 0x00, 0xfe, 0x07, 0x40, 0xff, 0xff, 0x40, 0xff, 0xff, 0x0f, 0xff, 0x81, 0x7f, 0xfc, 0x01, 0xfc, + 0xf6, 0x03, 0xe0, 0xdf, 0x0f, 0x80, 0x7f, 0x3f, 0x00, 0xfe, 0xfd, 0x00, 0xf8, 0xf2, 0x07, 0xf0, + 0x87, 0x3f, 0xd0, 0x0f, 0xfc, 0xc2, 0x0f, 0xc0, 0xff, 0x1f, 0x00, 0xfd, 0x1f, 0x00, 0xfc, 0xff, + 0x00, 0xfc, 0xf5, 0x0f, 0xfc, 0x02, 0xff, 0xf4, 0x03, 0xf0, 0xeb, 0x0b, 0x80, 0xff, 0x1f, 0x00, + 0xfc, 0x7f, 0x00, 0xf0, 0xff, 0x01, 0xc0, 0xff, 0x0b, 0x40, 0xff, 0x3f, 0x00, 0xff, 0xfd, 0x03, + 0xfe, 0xe1, 0xff, 0xff, 0x02, 0xfe, 0xff, 0x02, 0x90, 0xbf, 0x01, 0x00, 0x00, 0x00, 0x00, + /* '9', offset=825 */ + 0x40, 0xfe, 0x06, 0x40, 0xff, 0x7f, 0x40, 0xff, 0xff, 0x07, 0xff, 0xc1, 0x3f, 0xfc, 0x01, 0xfd, + 0xf4, 0x03, 0xf0, 0xe7, 0x0f, 0x80, 0xaf, 0x3f, 0x00, 0xfe, 0xfe, 0x00, 0xf4, 0xfb, 0x03, 0xd0, + 0xef, 0x0f, 0x40, 0x7f, 0x3f, 0x00, 0xfd, 0xfc, 0x02, 0xf4, 0xf3, 0x1f, 0xf0, 0x4f, 0xff, 0xff, + 0x3f, 0xf4, 0xff, 0xff, 0x00, 0xfe, 0xfe, 0x03, 0x00, 0xf0, 0x0b, 0x00, 0xc0, 0x1f, 0x00, 0x40, + 0x3f, 0x00, 0x00, 0xff, 0x00, 0x00, 0xfd, 0x01, 0x00, 0xfc, 0x03, 0x00, 0xfc, 0x07, 0x40, 0xfe, + 0x07, 0xd0, 0xff, 0x07, 0x40, 0xff, 0x07, 0x00, 0xbc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + /* '.', offset=920 */ 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, - /* 'W', offset=1745 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0xfe, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0x02, 0x00, 0xf0, 0x1f, 0x00, 0x40, 0xff, - 0xfd, 0x03, 0x00, 0xf4, 0x2f, 0x00, 0x40, 0xbf, 0xfd, 0x03, 0x00, 0xf4, 0x3f, 0x00, 0x40, 0xbf, - 0xfc, 0x03, 0x00, 0xf8, 0x3f, 0x00, 0x80, 0x7f, 0xfc, 0x03, 0x00, 0xfc, 0x7f, 0x00, 0x80, 0x7f, - 0xfc, 0x03, 0x00, 0xfc, 0xbf, 0x00, 0xc0, 0x3f, 0xf8, 0x07, 0x00, 0xfd, 0xfe, 0x00, 0xc0, 0x3f, - 0xf8, 0x07, 0x00, 0xbe, 0xfd, 0x00, 0xc0, 0x3f, 0xf4, 0x0b, 0x00, 0xbf, 0xfc, 0x01, 0xc0, 0x2f, - 0xf4, 0x0f, 0x00, 0x7f, 0xfc, 0x02, 0xd0, 0x2f, 0xf0, 0x0f, 0x40, 0x3f, 0xfc, 0x03, 0xd0, 0x1f, - 0xf0, 0x0f, 0x80, 0x3f, 0xf8, 0x03, 0xe0, 0x0f, 0xf0, 0x0f, 0xc0, 0x2f, 0xf4, 0x07, 0xe0, 0x0f, - 0xe0, 0x1f, 0xc0, 0x1f, 0xf0, 0x0b, 0xf0, 0x0f, 0xd0, 0x1f, 0xd0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0b, - 0xd0, 0x2f, 0xe0, 0x0f, 0xe0, 0x0f, 0xf0, 0x0b, 0xc0, 0x3f, 0xf0, 0x0b, 0xd0, 0x1f, 0xf4, 0x07, - 0xc0, 0x3f, 0xf0, 0x07, 0xc0, 0x2f, 0xf4, 0x03, 0x80, 0x3f, 0xf4, 0x03, 0x80, 0x3f, 0xf8, 0x03, - 0x80, 0x7f, 0xf8, 0x02, 0x40, 0x3f, 0xfc, 0x03, 0x40, 0x7f, 0xfc, 0x01, 0x00, 0x7f, 0xfc, 0x02, - 0x00, 0xbf, 0xfd, 0x00, 0x00, 0xbf, 0xfc, 0x01, 0x00, 0xff, 0xfe, 0x00, 0x00, 0xfe, 0xfd, 0x00, - 0x00, 0xfe, 0xbf, 0x00, 0x00, 0xfd, 0xff, 0x00, 0x00, 0xfd, 0x7f, 0x00, 0x00, 0xfc, 0xbf, 0x00, - 0x00, 0xfc, 0x3f, 0x00, 0x00, 0xf8, 0xbf, 0x00, 0x00, 0xfc, 0x2f, 0x00, 0x00, 0xf4, 0x7f, 0x00, - 0x00, 0xfc, 0x1f, 0x00, 0x00, 0xf0, 0x3f, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xf0, 0x3f, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xf4, + 0xef, 0x7f, 0xff, 0xf8, 0x00, + /* 'V', offset=957 */ + 0xbf, 0x00, 0x00, 0xe0, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0xf0, 0xdb, 0x0f, 0x00, + 0x00, 0x7f, 0xfd, 0x01, 0x00, 0xf4, 0xc3, 0x2f, 0x00, 0x80, 0x3f, 0xfc, 0x03, 0x00, 0xfc, 0x82, + 0x3f, 0x00, 0xc0, 0x1f, 0xf4, 0x03, 0x00, 0xfc, 0x00, 0x7f, 0x00, 0xd0, 0x0f, 0xf0, 0x0b, 0x00, + 0xfe, 0x00, 0xfe, 0x00, 0xf0, 0x0b, 0xd0, 0x0f, 0x00, 0x7f, 0x00, 0xfc, 0x01, 0xf4, 0x03, 0xc0, + 0x2f, 0x80, 0x3f, 0x00, 0xf8, 0x03, 0xfc, 0x01, 0x40, 0x3f, 0xc0, 0x0f, 0x00, 0xf0, 0x07, 0xfd, + 0x00, 0x00, 0xbf, 0xe0, 0x0b, 0x00, 0xe0, 0x0f, 0x7f, 0x00, 0x00, 0xfc, 0xf0, 0x03, 0x00, 0xc0, + 0x5f, 0x3f, 0x00, 0x00, 0xf8, 0xfa, 0x02, 0x00, 0x40, 0xff, 0x0f, 0x00, 0x00, 0xf0, 0xff, 0x00, + 0x00, 0x00, 0xff, 0x0b, 0x00, 0x00, 0xd0, 0x7f, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + /* 'A', offset=1088 */ + 0x00, 0xc0, 0x3f, 0x00, 0x00, 0x00, 0xfd, 0x07, 0x00, 0x00, 0xe0, 0xbf, 0x00, 0x00, 0x00, 0xff, + 0x0f, 0x00, 0x00, 0xf0, 0xff, 0x01, 0x00, 0x40, 0xaf, 0x2f, 0x00, 0x00, 0xfc, 0xf5, 0x03, 0x00, + 0xc0, 0x0f, 0x3f, 0x00, 0x00, 0xfd, 0xf0, 0x0b, 0x00, 0xe0, 0x0b, 0xfe, 0x00, 0x00, 0x3f, 0xc0, + 0x0f, 0x00, 0xf0, 0x03, 0xfc, 0x01, 0x80, 0x2f, 0x80, 0x2f, 0x00, 0xfc, 0x01, 0xf4, 0x03, 0xc0, + 0x0f, 0x00, 0x3f, 0x00, 0xfd, 0x00, 0xf0, 0x07, 0xe0, 0x0b, 0x00, 0xbe, 0x00, 0x7f, 0x00, 0xd0, + 0x0f, 0xf0, 0xff, 0xff, 0xff, 0x40, 0xff, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0xff, 0xc2, 0x2f, + 0x00, 0x80, 0x3f, 0xfc, 0x01, 0x00, 0xf4, 0xd3, 0x0f, 0x00, 0x00, 0x7f, 0xfd, 0x00, 0x00, 0xf0, + 0xeb, 0x0b, 0x00, 0x00, 0xfe, 0xbf, 0x00, 0x00, 0xe0, 0xff, 0x07, 0x00, 0x00, 0xfd, 0x00, 0x00, + 0x00, 0x00, 0x00, + /* 'W', offset=1219 */ + 0x7f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xef, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf7, 0x07, 0x00, + 0x00, 0x00, 0x00, 0xfc, 0xfd, 0x02, 0x00, 0xfe, 0x00, 0x00, 0x3f, 0xbf, 0x00, 0xc0, 0x7f, 0x00, + 0xd0, 0x8f, 0x2f, 0x00, 0xf0, 0x1f, 0x00, 0xf4, 0xe3, 0x0f, 0x00, 0xfd, 0x0b, 0x00, 0xfd, 0xf4, + 0x03, 0x80, 0xff, 0x03, 0x80, 0x2f, 0xfd, 0x00, 0xf0, 0xfb, 0x00, 0xe0, 0x0b, 0x3f, 0x00, 0xbc, + 0x7d, 0x00, 0xfc, 0xc1, 0x1f, 0x00, 0x6f, 0x2f, 0x00, 0x7f, 0xf0, 0x07, 0xd0, 0xc7, 0x0f, 0xc0, + 0x0f, 0xf8, 0x02, 0xf8, 0xf0, 0x03, 0xf0, 0x03, 0xbe, 0x00, 0x3f, 0xf8, 0x01, 0xfd, 0x40, 0x3f, + 0xc0, 0x0b, 0xbd, 0x80, 0x2f, 0xc0, 0x0f, 0xf4, 0x01, 0x3f, 0xe0, 0x07, 0xf0, 0x03, 0x3e, 0xc0, + 0x0f, 0xfc, 0x01, 0xfc, 0xc1, 0x0f, 0xe0, 0x07, 0x3f, 0x00, 0x7e, 0xf0, 0x02, 0xf4, 0xc2, 0x0f, + 0x80, 0x2f, 0x7d, 0x00, 0xfc, 0xf4, 0x02, 0xd0, 0x8f, 0x0f, 0x00, 0x3f, 0xbd, 0x00, 0xf0, 0xf3, + 0x03, 0x80, 0x9f, 0x1f, 0x00, 0xfc, 0xbd, 0x00, 0xd0, 0xfb, 0x03, 0x00, 0xfe, 0x1f, 0x00, 0xf0, + 0xff, 0x00, 0x40, 0xff, 0x03, 0x00, 0xf8, 0x2f, 0x00, 0xc0, 0xbf, 0x00, 0x00, 0xfd, 0x07, 0x00, + 0xf0, 0x1f, 0x00, 0x00, 0xff, 0x01, 0x00, 0xfc, 0x03, 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, + 13u, 8u, 13u, 13u, 14u, 13u, 13u, 13u, + 13u, 13u, 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, 22u, 32u, + 0u, 0u, 0u, 0u, 0u, 0u, 18u, 27u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, @@ -170,12 +130,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, 37u, 0u, + 95u, 58u, 95u, 95u, 102u, 95u, 95u, 95u, + 95u, 95u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 131u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 193u, 280u, + 0u, 0u, 0u, 0u, 0u, 0u, 131u, 196u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, @@ -185,12 +145,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, 920u, 0u, + 0u, 95u, 153u, 248u, 343u, 445u, 540u, 635u, + 730u, 825u, 0u, 0u, 0u, 0u, 0u, 0u, + 0u, 1088u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, - 0u, 0u, 0u, 0u, 0u, 0u, 1359u, 1745u, + 0u, 0u, 0u, 0u, 0u, 0u, 957u, 1219u, 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 12fa454f..697de5f2 100644 --- a/opendps/font-meter_large.h +++ b/opendps/font-meter_large.h @@ -1,21 +1,21 @@ -/** Font generated from `./gen_lookup.py -f gfx/Ubuntu-C.ttf -s 48 -o meter_large` */ +/** Font generated from `./gen_lookup.py -f gfx/Ubuntu-C.ttf -s 40 -o meter_large` */ #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 (32) -#define FONT_METER_LARGE_MAX_DIGIT_WIDTH (17) +#define FONT_METER_LARGE_MAX_GLYPH_HEIGHT (29) +#define FONT_METER_LARGE_MAX_GLYPH_WIDTH (27) +#define FONT_METER_LARGE_MAX_DIGIT_WIDTH (14) #define FONT_METER_LARGE_DOT_WIDTH (5) -#define FONT_METER_LARGE_SPACING (6) -#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[2025]; +extern const uint8_t font_meter_large_pixdata[1415]; #endif // __FONT_METER_LARGE_H__ \ No newline at end of file diff --git a/opendps/func_cc.c b/opendps/func_cc.c deleted file mode 100644 index 218d12f6..00000000 --- a/opendps/func_cc.c +++ /dev/null @@ -1,358 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2018 Johan Kanflo (github.com/kanflo) - * - * 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-cc.h" -#include "hw.h" -#include "func_cc.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 CC screen. - * - * It has one editable value, - * 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. - * This allows for ramping the voltage and obsering the current increase. - */ - -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 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); - -/* 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_u, saved_i; - -#define SCREEN_ID (2) -#define PAST_U (0) -#define PAST_I (1) - -/* This is the definition of the voltage item in the UI */ -ui_number_t cc_voltage = { - { - .type = ui_item_number, - .id = 10, - .x = 120, - .y = 15, - .can_focus = true, - }, - .font_size = FONT_METER_LARGE, /** The bigger one, try FONT_SMALL or FONT_MEDIUM for kicks */ - .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, -}; - -/* This is the definition of the current item in the UI */ -ui_number_t cc_current = { - { - .type = ui_item_number, - .id = 11, - .x = 120, - .y = 60, - .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 = CURRENT_DIGITS, - .num_decimals = CURRENT_DECIMALS, - .unit = unit_ampere, - .changed = ¤t_changed, -}; - -/* This is the screen definition */ -ui_screen_t cc_screen = { - .id = SCREEN_ID, - .name = "cc", - .icon_data = (uint8_t *) gfx_cc, - .icon_data_len = sizeof(gfx_cc), - .icon_width = GFX_CC_WIDTH, - .icon_height = GFX_CC_HEIGHT, - .activated = NULL, - .deactivated = NULL, - .enable = &cc_enable, - .past_save = &past_save, - .past_restore = &past_restore, - .set_parameter = &set_parameter, - .get_parameter = &get_parameter, - .tick = &cc_tick, - .num_items = 2, - .parameters = { - { - .name = "voltage", - .unit = unit_volt, - .prefix = si_milli - }, - { - .name = "current", - .unit = unit_ampere, - .prefix = si_milli - }, - { - .name = {'\0'} /** Terminator */ - }, - }, - .items = { (ui_item_t*) &cc_voltage, (ui_item_t*) &cc_current } -}; - -/** - * @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 < cc_voltage.min || ivalue > cc_voltage.max) { - emu_printf("[CC] Voltage %d is out of range (min:%d max:%d)\n", ivalue, cc_voltage.min, cc_voltage.max); - return ps_range_error; - } - emu_printf("[CC] Setting voltage to %d\n", ivalue); - cc_voltage.value = ivalue; - voltage_changed(&cc_voltage); - return ps_ok; - } else if (strcmp("current", name) == 0 || strcmp("i", name) == 0) { - if (ivalue < cc_current.min || ivalue > cc_current.max) { - emu_printf("[CC] Current %d is out of range (min:%d max:%d)\n", ivalue, cc_current.min, cc_current.max); - return ps_range_error; - } - emu_printf("[CC] Setting current to %d\n", ivalue); - cc_current.value = ivalue; - current_changed(&cc_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) { - (void) mini_snprintf(value, value_len, "%d", (pwrctl_vout_enabled() ? saved_u : cc_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 : cc_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 cc_enable(bool enabled) -{ - if (enabled) { - saved_u = cc_voltage.value; - saved_i = cc_current.value; - (void) pwrctl_set_vout(cc_voltage.max - 1000); /** Updated in cc_tick */ - (void) pwrctl_set_iout(cc_current.value); - (void) pwrctl_set_ilimit(0xFFFF); /** Set the current limit to the maximum to prevent OCP (over current protection) firing */ - (void) pwrctl_set_vlimit(cc_voltage.value); - 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 */ - cc_voltage.value = saved_u; - cc_voltage.ui.draw(&cc_voltage.ui); - cc_current.value = saved_i; - cc_current.ui.draw(&cc_current.ui); - } -} - -/** - * @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_u = item->value; - (void) pwrctl_set_vlimit(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); -} - -/** - * @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_u, 4 /* sizeof(cc_voltage.value) */ )) { - /** @todo: handle past write failures */ - } - if (!past_write_unit(past, (SCREEN_ID << 24) | PAST_I, (void*) &saved_i, 4 /* sizeof(cc_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_u = cc_voltage.value = *p; - (void) length; - } - if (past_read_unit(past, (SCREEN_ID << 24) | PAST_I, (const void**) &p, &length)) { - saved_i = cc_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 cc_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 */ - cc_voltage.max = (float) pwrctl_calc_vin(v_in_raw) / VIN_VOUT_RATIO + 0.5f; - if (pwrctl_vout_enabled()) { - if (cc_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 (cc_voltage.value != saved_u) { - cc_voltage.value = saved_u; - cc_voltage.ui.draw(&cc_voltage.ui); - } - } else { - /** No focus, update display if necessary */ - int32_t new_u = pwrctl_calc_vout(v_out_raw); - if (new_u != cc_voltage.value) { - cc_voltage.value = new_u; - cc_voltage.ui.draw(&cc_voltage.ui); - } - } - - if (cc_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 (cc_current.value != saved_i) { - cc_current.value = saved_i; - cc_current.ui.draw(&cc_current.ui); - } - } else { - /** No focus, update display if necessary */ - int32_t new_i = pwrctl_calc_iout(i_out_raw); - if (new_i != cc_current.value) { - cc_current.value = new_i; - cc_current.ui.draw(&cc_current.ui); - } - } - } -} - -/** - * @brief Function init. Initialise the cc module and add its screen to - * the UI - * - * @param ui The user interface - */ -void func_cc_init(uui_t *ui) -{ - cc_voltage.value = pwrctl_get_vout(); - cc_current.value = pwrctl_get_ilimit(); - 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; - cc_voltage.max = pwrctl_calc_vin(v_in_raw); /** @todo: subtract for LDO */ - number_init(&cc_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 */ -// cc_voltage.cur_digit = 2; - number_init(&cc_current); - uui_add_screen(ui, &cc_screen); -} diff --git a/opendps/func_cc.h b/opendps/func_cc.h deleted file mode 100644 index 70861141..00000000 --- a/opendps/func_cc.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2018 Johan Kanflo (github.com/kanflo) - * - * 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_CC_H__ -#define __FUNC_CC_H__ - -#include "uui.h" - -/** - * @brief Add the CV function to the UI - * - * @param ui The user interface - */ -void func_cc_init(uui_t *ui); - -#endif // __FUNC_CC_H__ diff --git a/opendps/func_cv.c b/opendps/func_cccv.c similarity index 68% rename from opendps/func_cv.c rename to opendps/func_cccv.c index ed70077e..13033460 100644 --- a/opendps/func_cv.c +++ b/opendps/func_cccv.c @@ -2,6 +2,7 @@ * The MIT License (MIT) * * Copyright (c) 2018 Johan Kanflo (github.com/kanflo) + * Copyright (c) 2021 Richard Taylor (github.com/art103) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,9 +27,9 @@ #include #include #include -#include "gfx-cv.h" +#include "gfx-cccv.h" #include "hw.h" -#include "func_cv.h" +#include "func_cccv.h" #include "uui.h" #include "uui_number.h" #include "dbg_printf.h" @@ -44,10 +45,10 @@ * This allows for ramping the voltage and obsering the current increase. */ -static void cv_enable(bool _enable); +static void cccv_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 cccv_tick(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); @@ -56,23 +57,24 @@ static set_param_status_t get_parameter(char *name, char *value, uint32_t value_ /* 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_u, saved_i; +static int32_t saved_u; +static int32_t saved_i; -#define SCREEN_ID (1) +#define SCREEN_ID (2) #define PAST_U (0) #define PAST_I (1) /* This is the definition of the voltage item in the UI */ -ui_number_t cv_voltage = { +ui_number_t cccv_voltage = { { .type = ui_item_number, .id = 10, - .x = 120, - .y = 15, + .x = 64, + .y = 6, .can_focus = true, }, .font_size = FONT_METER_LARGE, /** The bigger one, try FONT_SMALL or FONT_MEDIUM for kicks */ - .alignment = ui_text_right_aligned, + .alignment = ui_text_center_aligned, .pad_dot = false, .color = COLOR_VOLTAGE, .value = 0, @@ -86,16 +88,16 @@ ui_number_t cv_voltage = { }; /* This is the definition of the current item in the UI */ -ui_number_t cv_current = { +ui_number_t cccv_current = { { .type = ui_item_number, .id = 11, - .x = 120, - .y = 60, + .x = 64, + .y = 40, .can_focus = true, }, .font_size = FONT_METER_LARGE, - .alignment = ui_text_right_aligned, + .alignment = ui_text_center_aligned, .pad_dot = false, .color = COLOR_AMPERAGE, .value = 0, @@ -108,23 +110,45 @@ ui_number_t cv_current = { .changed = ¤t_changed, }; +/* This is the definition of the power item in the UI */ +ui_number_t cccv_power = { + { + .type = ui_item_number, + .id = 12, + .x = 64, + .y = 72, + .can_focus = false, + }, + .font_size = FONT_METER_LARGE, + .alignment = ui_text_center_aligned, + .pad_dot = false, + .color = COLOR_AMPERAGE, + .value = 0, + .min = 0, + .max = 0, + .si_prefix = si_milli, + .num_digits = 3, + .num_decimals = 1, + .unit = unit_watt, +}; + /* This is the screen definition */ -ui_screen_t cv_screen = { +ui_screen_t cccv_screen = { .id = SCREEN_ID, .name = "cv", - .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_cccv, + .icon_data_len = sizeof(gfx_cccv), + .icon_width = GFX_CCCV_WIDTH, + .icon_height = GFX_CCCV_HEIGHT, .activated = NULL, .deactivated = NULL, - .enable = &cv_enable, + .enable = &cccv_enable, .past_save = &past_save, .past_restore = &past_restore, - .tick = &cv_tick, + .tick = &cccv_tick, .set_parameter = &set_parameter, .get_parameter = &get_parameter, - .num_items = 2, + .num_items = 3, .parameters = { { .name = "voltage", @@ -136,11 +160,16 @@ ui_screen_t cv_screen = { .unit = unit_ampere, .prefix = si_milli }, + { + .name = "power", + .unit = unit_watt, + .prefix = si_milli + }, { .name = {'\0'} /** Terminator */ }, }, - .items = { (ui_item_t*) &cv_voltage, (ui_item_t*) &cv_current } + .items = { (ui_item_t*) &cccv_voltage, (ui_item_t*) &cccv_current, (ui_item_t*) &cccv_power } }; /** @@ -155,22 +184,22 @@ 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 < cv_voltage.min || ivalue > cv_voltage.max) { - emu_printf("[CV] Voltage %d is out of range (min:%d max:%d)\n", ivalue, cv_voltage.min, cv_voltage.max); + if (ivalue < cccv_voltage.min || ivalue > cccv_voltage.max) { + emu_printf("[CV] Voltage %d is out of range (min:%d max:%d)\n", ivalue, cccv_voltage.min, cccv_voltage.max); return ps_range_error; } emu_printf("[CV] Setting voltage to %d\n", ivalue); - cv_voltage.value = ivalue; - voltage_changed(&cv_voltage); + cccv_voltage.value = ivalue; + voltage_changed(&cccv_voltage); return ps_ok; } else if (strcmp("current", name) == 0 || strcmp("i", name) == 0) { - if (ivalue < cv_current.min || ivalue > cv_current.max) { - emu_printf("[CV] Current %d is out of range (min:%d max:%d)\n", ivalue, cv_current.min, cv_current.max); + if (ivalue < cccv_current.min || ivalue > cccv_current.max) { + emu_printf("[CV] Current %d is out of range (min:%d max:%d)\n", ivalue, cccv_current.min, cccv_current.max); return ps_range_error; } emu_printf("[CV] Setting current to %d\n", ivalue); - cv_current.value = ivalue; - current_changed(&cv_current); + cccv_current.value = ivalue; + current_changed(&cccv_current); return ps_ok; } return ps_unknown_name; @@ -188,10 +217,10 @@ 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) { if (strcmp("voltage", name) == 0 || strcmp("u", name) == 0) { - (void) mini_snprintf(value, value_len, "%d", (pwrctl_vout_enabled() ? saved_u : cv_voltage.value)); + (void) mini_snprintf(value, value_len, "%d", (pwrctl_vout_enabled() ? saved_u : cccv_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 : cv_current.value); + (void) mini_snprintf(value, value_len, "%d", pwrctl_vout_enabled() ? saved_i : cccv_current.value); return ps_ok; } return ps_unknown_name; @@ -202,26 +231,28 @@ static set_param_status_t get_parameter(char *name, char *value, uint32_t value_ * * @param[in] enabled true when function is enabled */ -static void cv_enable(bool enabled) +static void cccv_enable(bool enabled) { emu_printf("[CV] %s output\n", enabled ? "Enable" : "Disable"); if (enabled) { /** Display will now show the current values, keep the user setting saved */ - saved_u = cv_voltage.value; - saved_i = cv_current.value; - (void) pwrctl_set_vout(cv_voltage.value); - (void) pwrctl_set_iout(CONFIG_DPS_MAX_CURRENT); - (void) pwrctl_set_ilimit(cv_current.value); + saved_u = cccv_voltage.value; + saved_i = cccv_current.value; + (void) pwrctl_set_vout(saved_u); + (void) pwrctl_set_iout(saved_i); + (void) pwrctl_set_ilimit(CONFIG_DPS_MAX_CURRENT); (void) pwrctl_set_vlimit(0xFFFF); /** Set the voltage limit to the maximum to prevent OVP (over voltage 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 */ - cv_voltage.value = saved_u; - cv_voltage.ui.draw(&cv_voltage.ui); - cv_current.value = saved_i; - cv_current.ui.draw(&cv_current.ui); + cccv_voltage.value = saved_u; + cccv_voltage.ui.draw(&cccv_voltage.ui); + cccv_current.value = saved_i; + cccv_current.ui.draw(&cccv_current.ui); + cccv_power.value = saved_i * saved_u / 1000; + cccv_power.ui.draw(&cccv_power.ui); } } @@ -244,7 +275,7 @@ static void voltage_changed(ui_number_t *item) static void current_changed(ui_number_t *item) { saved_i = item->value; - (void) pwrctl_set_ilimit(item->value); + (void) pwrctl_set_iout(item->value); } /** @@ -255,10 +286,10 @@ static void current_changed(ui_number_t *item) 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_u, 4 /* sizeof(cv_voltage.value) */ )) { + if (!past_write_unit(past, (SCREEN_ID << 24) | PAST_U, (void*) &saved_u, 4 /* sizeof(cccv_voltage.value) */ )) { /** @todo: handle past write failures */ } - if (!past_write_unit(past, (SCREEN_ID << 24) | PAST_I, (void*) &saved_i, 4 /* sizeof(cv_current.value) */ )) { + if (!past_write_unit(past, (SCREEN_ID << 24) | PAST_I, (void*) &saved_i, 4 /* sizeof(cccv_current.value) */ )) { /** @todo: handle past write failures */ } } @@ -273,11 +304,11 @@ 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_u = cv_voltage.value = *p; + saved_u = cccv_voltage.value = *p; (void) length; } if (past_read_unit(past, (SCREEN_ID << 24) | PAST_I, (const void**) &p, &length)) { - saved_i = cv_current.value = *p; + saved_i = cccv_current.value = *p; (void) length; } } @@ -290,46 +321,53 @@ static void past_restore(past_t *past) * Power on : show current output value unless the item has focus * in which case we shall display the current setting. */ -static void cv_tick(void) +static void cccv_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 */ - cv_voltage.max = (float) pwrctl_calc_vin(v_in_raw) / VIN_VOUT_RATIO + 0.5f; + cccv_voltage.max = (float) pwrctl_calc_vin(v_in_raw) / VIN_VOUT_RATIO + 0.5f; if (pwrctl_vout_enabled()) { - if (cv_voltage.ui.has_focus) { + int32_t new_u = pwrctl_calc_vout(v_out_raw); + int32_t new_i = pwrctl_calc_iout(i_out_raw); + int32_t new_p = new_u * new_i / 1000; + + if (cccv_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 (cv_voltage.value != (int32_t) pwrctl_get_vout()) { - cv_voltage.value = pwrctl_get_vout(); - cv_voltage.ui.draw(&cv_voltage.ui); + if (cccv_voltage.value != (int32_t) pwrctl_get_vout()) { + cccv_voltage.value = pwrctl_get_vout(); + cccv_voltage.ui.draw(&cccv_voltage.ui); } } else { /** No focus, update display if necessary */ - int32_t new_u = pwrctl_calc_vout(v_out_raw); - if (new_u != cv_voltage.value) { - cv_voltage.value = new_u; - cv_voltage.ui.draw(&cv_voltage.ui); + if (new_u != cccv_voltage.value) { + cccv_voltage.value = new_u; + cccv_voltage.ui.draw(&cccv_voltage.ui); } } - if (cv_current.ui.has_focus) { + if (cccv_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 (cv_current.value != saved_i) { - cv_current.value = saved_i; - cv_current.ui.draw(&cv_current.ui); + if (cccv_current.value != saved_i) { + cccv_current.value = saved_i; + cccv_current.ui.draw(&cccv_current.ui); } } else { /** No focus, update display if necessary */ - int32_t new_i = pwrctl_calc_iout(i_out_raw); - if (new_i != cv_current.value) { - cv_current.value = new_i; - cv_current.ui.draw(&cv_current.ui); + if (new_i != cccv_current.value) { + cccv_current.value = new_i; + cccv_current.ui.draw(&cccv_current.ui); } } + + if (new_p != cccv_power.value) { + cccv_power.value = new_p; + cccv_power.ui.draw(&cccv_power.ui); + } } } @@ -338,19 +376,20 @@ static void cv_tick(void) * * @param ui The user interface */ -void func_cv_init(uui_t *ui) +void func_cccv_init(uui_t *ui) { - cv_voltage.value = 0; /** read from past */ - cv_current.value = 0; /** read from past */ + cccv_voltage.value = 0; /** read from past */ + cccv_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; - cv_voltage.max = pwrctl_calc_vin(v_in_raw); /** @todo: subtract for LDO */ - number_init(&cv_voltage); /** @todo: add guards for missing init calls */ + cccv_voltage.max = pwrctl_calc_vin(v_in_raw); /** @todo: subtract for LDO */ + number_init(&cccv_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 */ - cv_voltage.cur_digit = 2; - number_init(&cv_current); - uui_add_screen(ui, &cv_screen); + cccv_voltage.cur_digit = 2; + number_init(&cccv_current); + number_init(&cccv_power); + uui_add_screen(ui, &cccv_screen); } diff --git a/opendps/func_cv.h b/opendps/func_cccv.h similarity index 88% rename from opendps/func_cv.h rename to opendps/func_cccv.h index 5dc00cc7..21a0c106 100644 --- a/opendps/func_cv.h +++ b/opendps/func_cccv.h @@ -22,16 +22,16 @@ * THE SOFTWARE. */ -#ifndef __FUNC_CV_H__ -#define __FUNC_CV_H__ +#ifndef __FUNC_CCCV_H__ +#define __FUNC_CCCV_H__ #include "uui.h" /** - * @brief Add the CV function to the UI + * @brief Add the CC/CV function to the UI * * @param ui The user interface */ -void func_cv_init(uui_t *ui); +void func_cccv_init(uui_t *ui); -#endif // __FUNC_CV_H__ +#endif // __FUNC_CCCV_H__ diff --git a/opendps/func_cl.c b/opendps/func_cl.c deleted file mode 100644 index d3e54c95..00000000 --- a/opendps/func_cl.c +++ /dev/null @@ -1,406 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2018 Johan Kanflo (github.com/kanflo) - * - * 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-cc.h" -#include "gfx-cv.h" -#include "gfx-cl.h" -#include "hw.h" -#include "func_cl.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 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. - * This allows for ramping the voltage and obsering the current increase. - */ - -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 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); -static set_param_status_t get_parameter(char *name, char *value, uint32_t value_len); - -/* 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_u, saved_i; - -enum { - CUR_GFX_NOT_DRAWN, - CUR_GFX_CV, - CUR_GFX_CC, -} current_mode_gfx; - -#define SCREEN_ID (3) -#define PAST_U (0) -#define PAST_I (1) -#define XPOS_CCCV (25) - -/* This is the definition of the voltage item in the UI */ -ui_number_t cl_voltage = { - { - .type = ui_item_number, - .id = 10, - .x = 120, - .y = 15, - .can_focus = true, - }, - .font_size = FONT_METER_LARGE, /** The bigger one, try FONT_SMALL or FONT_MEDIUM for kicks */ - .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, -}; - -/* This is the definition of the current item in the UI */ -ui_number_t cl_current = { - { - .type = ui_item_number, - .id = 11, - .x = 120, - .y = 60, - .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 = CURRENT_DIGITS, - .num_decimals = CURRENT_DECIMALS, - .unit = unit_ampere, - .changed = ¤t_changed, -}; - -/* This is the screen definition */ -ui_screen_t cl_screen = { - .id = SCREEN_ID, - .name = "cl", - .icon_data = (uint8_t *) gfx_cl, - .icon_data_len = sizeof(gfx_cl), - .icon_width = GFX_CL_WIDTH, - .icon_height = GFX_CL_HEIGHT, - .activated = NULL, - .deactivated = &deactivated, - .enable = &cl_enable, - .past_save = &past_save, - .past_restore = &past_restore, - .tick = &cl_tick, - .set_parameter = &set_parameter, - .get_parameter = &get_parameter, - .num_items = 2, - .parameters = { - { - .name = "voltage", - .unit = unit_volt, - .prefix = si_milli - }, - { - .name = "current", - .unit = unit_ampere, - .prefix = si_milli - }, - { - .name = {'\0'} /** Terminator */ - }, - }, - .items = { (ui_item_t*) &cl_voltage, (ui_item_t*) &cl_current } -}; - -/** - * @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 < cl_voltage.min || ivalue > cl_voltage.max) { - emu_printf("[CL] Voltage %d is out of range (min:%d max:%d)\n", ivalue, cl_voltage.min, cl_voltage.max); - return ps_range_error; - } - emu_printf("[CL] Setting voltage to %d\n", ivalue); - cl_voltage.value = ivalue; - voltage_changed(&cl_voltage); - return ps_ok; - } else if (strcmp("current", name) == 0 || strcmp("i", name) == 0) { - if (ivalue < cl_current.min || ivalue > cl_current.max) { - emu_printf("[CL] Current %d is out of range (min:%d max:%d)\n", ivalue, cl_current.min, cl_current.max); - return ps_range_error; - } - emu_printf("[CL] Setting current to %d\n", ivalue); - cl_current.value = ivalue; - current_changed(&cl_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_u : cl_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 : cl_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 cl_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_u = cl_voltage.value; - saved_i = cl_current.value; - (void) pwrctl_set_vout(cl_voltage.value); - (void) pwrctl_set_iout(cl_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 */ - cl_voltage.value = saved_u; - cl_voltage.ui.draw(&cl_voltage.ui); - cl_current.value = saved_i; - cl_current.ui.draw(&cl_current.ui); - - /** Ensure the CC or CV logo has been cleared from the screen */ - if (current_mode_gfx == CUR_GFX_CV) { - tft_fill(XPOS_CCCV, 128 - GFX_CV_HEIGHT, GFX_CV_WIDTH, GFX_CV_HEIGHT, BLACK); - } else if (current_mode_gfx == CUR_GFX_CC) { - tft_fill(XPOS_CCCV, 128 - GFX_CC_HEIGHT, GFX_CC_WIDTH, GFX_CC_HEIGHT, BLACK); - } - current_mode_gfx = CUR_GFX_NOT_DRAWN; - } -} - -/** - * @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_u = 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); -} - -/** - * @brief Do any required clean up before changing away from this screen - */ -static void deactivated(void) -{ - /** Ensure the CC or CV logo has been cleared from the screen */ - if (current_mode_gfx == CUR_GFX_CV) { - tft_fill(XPOS_CCCV, 128 - GFX_CV_HEIGHT, GFX_CV_WIDTH, GFX_CV_HEIGHT, BLACK); - } else if (current_mode_gfx == CUR_GFX_CC) { - tft_fill(XPOS_CCCV, 128 - GFX_CC_HEIGHT, GFX_CC_WIDTH, GFX_CC_HEIGHT, BLACK); - } - current_mode_gfx = CUR_GFX_NOT_DRAWN; -} - -/** - * @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_u, 4 /* sizeof(cl_voltage.value) */ )) { - /** @todo: handle past write failures */ - } - if (!past_write_unit(past, (SCREEN_ID << 24) | PAST_I, (void*) &saved_i, 4 /* sizeof(cl_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_u = cl_voltage.value = *p; - (void) length; - } - if (past_read_unit(past, (SCREEN_ID << 24) | PAST_I, (const void**) &p, &length)) { - saved_i = cl_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 cl_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 */ - cl_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); - - if (cl_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 (cl_voltage.value != saved_u) { - cl_voltage.value = saved_u; - cl_voltage.ui.draw(&cl_voltage.ui); - } - } else { - /** No focus, update display if necessary */ - if (cl_voltage.value != vout_actual) { - cl_voltage.value = vout_actual; - cl_voltage.ui.draw(&cl_voltage.ui); - } - } - - if (cl_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 (cl_current.value != saved_i) { - cl_current.value = saved_i; - cl_current.ui.draw(&cl_current.ui); - } - } else { - /** No focus, update display if necessary */ - if (cl_current.value != cout_actual) { - cl_current.value = cout_actual; - cl_current.ui.draw(&cl_current.ui); - } - } - - /** Determine if we are in CV or CC mode and display it */ - int32_t vout_diff = abs(saved_u - vout_actual); - int32_t cout_diff = abs(saved_i - cout_actual); - - if (cout_diff < vout_diff) { - if (current_mode_gfx != CUR_GFX_CC) { - tft_blit((uint16_t*) gfx_cc, GFX_CC_WIDTH, GFX_CC_HEIGHT, XPOS_CCCV, 128 - GFX_CC_HEIGHT); - current_mode_gfx = CUR_GFX_CC; - } - } else { - if (current_mode_gfx != CUR_GFX_CV) { - tft_blit((uint16_t*) gfx_cv, GFX_CV_WIDTH, GFX_CV_HEIGHT, XPOS_CCCV, 128 - GFX_CV_HEIGHT); - current_mode_gfx = CUR_GFX_CV; - } - } - } -} - -/** - * @brief Initialise the CL module and add its screen to the UI - * - * @param ui The user interface - */ -void func_cl_init(uui_t *ui) -{ - cl_voltage.value = 0; /** read from past */ - cl_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; - cl_voltage.max = pwrctl_calc_vin(v_in_raw); /** @todo: subtract for LDO */ - number_init(&cl_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 */ - cl_voltage.cur_digit = 2; - number_init(&cl_current); - uui_add_screen(ui, &cl_screen); -} diff --git a/opendps/func_cl.h b/opendps/func_cl.h deleted file mode 100644 index 79043352..00000000 --- a/opendps/func_cl.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2018 Johan Kanflo (github.com/kanflo) - * - * 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_CL_H__ -#define __FUNC_CL_H__ - -#include "uui.h" - -/** - * @brief Add the CV function to the UI - * - * @param ui The user interface - */ -void func_cl_init(uui_t *ui); - -#endif // __FUNC_CL_H__ diff --git a/opendps/gfx-cccv.c b/opendps/gfx-cccv.c new file mode 100644 index 00000000..461c17cb --- /dev/null +++ b/opendps/gfx-cccv.c @@ -0,0 +1,85 @@ +/** Gfx generated from `gen_lookup.py -i gfx/png/cccv.png -o cccv` */ + +#include "gfx-cccv.h" + +const uint8_t gfx_cccv[1260] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x31, 0x86, 0x4a, 0x69, 0x42, 0x28, + 0x21, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x82, 0x39, 0xe7, 0x4a, 0x69, 0x3a, 0x07, + 0x10, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0xc6, 0x58, 0xef, 0x9d, 0x08, 0x61, + 0x00, 0x00, 0x10, 0xa2, 0x3a, 0x07, 0x4a, 0x69, 0x39, 0xe7, 0x10, 0x82, 0x08, 0x61, 0x21, 0x04, + 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xe3, 0x21, 0x04, 0x10, 0x82, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xa2, 0xa5, 0x34, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5a, 0xeb, 0x00, 0x00, 0x31, 0xa6, 0xd6, 0xba, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x29, 0x65, 0x00, 0x00, 0x00, 0x00, 0x21, 0x04, 0xff, 0xff, + 0x9c, 0xd3, 0x00, 0x00, 0x42, 0x48, 0xef, 0x9d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0x1b, + 0x42, 0x28, 0xff, 0xff, 0xff, 0xff, 0x08, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb5, 0x96, + 0xff, 0xff, 0x29, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0xb2, + 0xff, 0xff, 0xc6, 0x18, 0x63, 0x0c, 0x63, 0x2c, 0xc6, 0x38, 0x31, 0xa6, 0x10, 0xa2, 0xde, 0xfb, + 0xff, 0xff, 0x9c, 0xf3, 0x5a, 0xcb, 0x73, 0xae, 0xd6, 0xda, 0x10, 0x82, 0x00, 0x00, 0x00, 0x00, + 0x42, 0x48, 0xff, 0xff, 0x5a, 0xeb, 0x21, 0x44, 0xff, 0xff, 0xff, 0xff, 0x8c, 0x71, 0x52, 0xca, + 0x84, 0x10, 0xc6, 0x38, 0x08, 0x61, 0xd6, 0xda, 0xff, 0xff, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x61, 0xff, 0xff, 0xff, 0xff, 0x10, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x29, 0x45, 0xff, 0xff, 0xdf, 0x1b, 0x18, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x08, 0x61, 0x00, 0x20, + 0x5a, 0xcb, 0xff, 0xff, 0x9c, 0xf3, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10, 0xa2, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7b, 0xef, 0xff, 0xff, 0x31, 0x86, 0x7c, 0x0f, 0xff, 0xff, 0x7b, 0xef, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xa2, 0x00, 0x00, 0x94, 0xb2, 0xff, 0xff, 0x3a, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x21, 0x24, 0xff, 0xff, 0xb5, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x5a, 0xcb, 0xff, 0xff, 0x84, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xb5, 0x96, 0xff, 0xff, 0x42, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xe7, 0x5c, 0xff, 0xff, 0x18, 0xc3, 0xd6, 0xba, + 0xff, 0xff, 0x29, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0xeb, + 0xff, 0xff, 0x63, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x49, 0xff, 0xff, 0x73, 0xae, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xef, 0xff, 0xff, 0x5a, 0xcb, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0xff, 0xff, 0xff, 0xff, 0x29, 0x45, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x04, 0xff, 0xff, 0x9d, 0x13, + 0x10, 0xa2, 0xff, 0xff, 0xff, 0xff, 0x10, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x31, 0xa6, 0xff, 0xff, 0xad, 0x95, 0x00, 0x00, 0x00, 0x00, 0x73, 0xce, 0xff, 0xff, + 0x42, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0xb2, 0xff, 0xff, + 0x4a, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x82, 0xff, 0xff, 0xff, 0xff, + 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x48, + 0xff, 0xff, 0x5a, 0xcb, 0x21, 0x04, 0xff, 0xff, 0xff, 0xff, 0x08, 0x61, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x82, 0xff, 0xff, 0xff, 0xff, 0x10, 0x82, 0x00, 0x00, + 0xd6, 0x9a, 0xff, 0xff, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x94, 0xd2, 0xff, 0xff, 0x4a, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x82, + 0xff, 0xff, 0xff, 0xff, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7b, 0xef, 0xff, 0xff, 0x31, 0x86, 0x21, 0x04, 0xff, 0xff, 0xff, 0xff, 0x08, 0x61, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x54, 0xff, 0xff, + 0x31, 0x86, 0x18, 0xe3, 0xff, 0xff, 0xd6, 0xda, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x84, 0x30, 0xff, 0xff, 0x52, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x41, 0xff, 0xff, 0xff, 0xff, 0x29, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xc6, 0x18, 0xff, 0xff, 0x10, 0x82, 0x18, 0xe3, 0xff, 0xff, + 0xff, 0xff, 0x10, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x5a, 0xcb, 0xff, 0xff, 0x5a, 0xeb, 0x3a, 0x07, 0xff, 0xff, 0x73, 0x8e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x2c, 0xff, 0xff, 0x7b, 0xcf, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xda, 0xff, 0xff, 0x39, 0xe7, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xe3, 0xff, 0xff, 0x9c, 0xf3, 0x00, 0x00, + 0x08, 0x61, 0xff, 0xff, 0xff, 0xff, 0x21, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x29, 0x65, 0xff, 0xff, 0x9c, 0xd3, 0x73, 0xae, 0xff, 0xff, 0x39, 0xe7, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xe7, 0xff, 0xff, + 0xc6, 0x38, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0xce, 0xff, 0xff, + 0x7b, 0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x28, 0xff, 0xff, + 0x5b, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x9d, 0x13, 0xff, 0xff, 0x52, 0xca, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0xd6, 0xba, 0xe7, 0x3c, 0xe7, 0x3c, + 0xff, 0xff, 0x10, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x61, 0xd6, 0xda, 0xff, 0xff, 0x6b, 0x6d, 0x10, 0x82, 0x08, 0x41, 0x31, 0x86, 0x29, 0x65, + 0x31, 0x86, 0xff, 0xff, 0xff, 0xff, 0x42, 0x08, 0x08, 0x41, 0x10, 0x82, 0x4a, 0x69, 0x10, 0x82, + 0x73, 0xce, 0xff, 0xff, 0x31, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x69, 0xff, 0xff, 0xe7, 0x3c, + 0x29, 0x85, 0x08, 0x41, 0x10, 0xa2, 0x5a, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xef, + 0xff, 0xff, 0xff, 0xff, 0x9c, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x48, 0xff, 0xff, 0xff, 0xff, 0xe7, 0x3c, 0xd6, 0xba, + 0xff, 0xff, 0x7b, 0xcf, 0x00, 0x00, 0x7b, 0xef, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xba, 0xe7, 0x5c, + 0xff, 0xff, 0x42, 0x28, 0xde, 0xfb, 0xff, 0xff, 0x10, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x9c, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xce, 0x99, 0xf7, 0xbe, 0xff, 0xff, 0x29, 0x45, 0x00, 0x00, + 0x00, 0x00, 0x3a, 0x07, 0xff, 0xff, 0xff, 0xff, 0x52, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xe7, 0xa5, 0x14, + 0xff, 0xff, 0xef, 0x9d, 0x94, 0xd2, 0x31, 0xa6, 0x00, 0x00, 0x00, 0x20, 0x5a, 0xcb, 0xb5, 0xd6, + 0xff, 0xff, 0xce, 0x99, 0x7b, 0xef, 0x42, 0x08, 0xff, 0xff, 0xa5, 0x54, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x61, 0x6b, 0x4d, 0xc6, 0x38, 0xff, 0xff, 0xc6, 0x38, 0x6b, 0x6d, + 0x10, 0x82, 0x00, 0x00, 0x00, 0x00, 0x10, 0xa2, 0x94, 0xb2, 0x94, 0xb2, 0x21, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x08, 0x61, 0x08, 0x41, 0x00, 0x00, 0x42, 0x28, 0xff, 0xff, 0x5a, 0xeb, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x61, + 0x00, 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 +}; \ No newline at end of file diff --git a/opendps/gfx-cccv.h b/opendps/gfx-cccv.h new file mode 100644 index 00000000..c7c05760 --- /dev/null +++ b/opendps/gfx-cccv.h @@ -0,0 +1,13 @@ +/** Gfx generated from `gen_lookup.py -i gfx/png/cccv.png -o cccv` */ + +#ifndef __GFX_CCCV_H__ +#define __GFX_CCCV_H__ + +#include + +#define GFX_CCCV_HEIGHT (15) +#define GFX_CCCV_WIDTH (42) + +extern const uint8_t gfx_cccv[1260]; + +#endif // __GFX_CCCV_H__ \ No newline at end of file diff --git a/opendps/opendps.c b/opendps/opendps.c index 302884e5..ca0858ad 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -66,15 +66,9 @@ #include "opendps.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 -#ifdef CONFIG_CL_ENABLE -#include "func_cl.h" -#endif // CONFIG_CL_ENABLE +#ifdef CONFIG_CCCV_ENABLE +#include "func_cccv.h" +#endif // CONFIG_CCCV_ENABLE #ifdef CONFIG_FUNCGEN_ENABLE #include "func_gen.h" #endif // CONFIG_FUNCGEN_ENABLE @@ -96,11 +90,6 @@ /** Timeout for waiting for wifi connction (ms) */ #define WIFI_CONNECT_TIMEOUT (10000) -/** Blit positions */ -#define XPOS_WIFI (4) -#define XPOS_LOCK (27) -#define XPOS_INVOLT (108) /* Right aligned to this position */ - /** Constants describing how certain things on the screen flash when needed */ #define WIFI_CONNECTING_FLASHING_PERIOD (1000) #define WIFI_ERROR_FLASHING_PERIOD (500) @@ -187,7 +176,7 @@ ui_number_t input_voltage = { { .type = ui_item_number, .id = 10, - .x = 0, + .x = XPOS_INVOLT, .y = 0, .can_focus = false, }, @@ -451,15 +440,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 -#ifdef CONFIG_CL_ENABLE - func_cl_init(&func_ui); -#endif // CONFIG_CL_ENABLE +#ifdef CONFIG_CCCV_ENABLE + func_cccv_init(&func_ui); +#endif // CONFIG_CCCV_ENABLE #ifdef CONFIG_FUNCGEN_ENABLE func_gen_init(&func_ui); #endif // CONFIG_FUNCGEN_ENABLE @@ -472,8 +455,7 @@ static void ui_init(void) /** Initialise the main screens */ uui_init(&main_ui, &g_past); number_init(&input_voltage); - input_voltage.ui.x = XPOS_INVOLT; - input_voltage.ui.y = ui_height - font_meter_small_height; + input_voltage.ui.y = ui_height - font_meter_small_height - (GFX_POWERON_HEIGHT - font_meter_small_height) / 2; uui_add_screen(&main_ui, &main_screen); /** Activate the UIs */ diff --git a/opendps/uui.h b/opendps/uui.h index f4c4b2d1..c7b6a832 100644 --- a/opendps/uui.h +++ b/opendps/uui.h @@ -51,9 +51,11 @@ #define MAX_PARAMETER_NAME (10) #endif // CONFIG_UI_MAX_PARAMETER_NAME -/** The position for the screen icon on the status bar */ -#define XPOS_ICON (43) - +/** Blit positions */ +#define XPOS_WIFI (40) +#define XPOS_LOCK (96) +#define XPOS_INVOLT (40) /* Right aligned to this position */ +#define XPOS_ICON (54) /** * Describes units in the user interface @@ -99,7 +101,8 @@ typedef enum { */ typedef enum { ui_text_left_aligned, - ui_text_right_aligned + ui_text_right_aligned, + ui_text_center_aligned } ui_text_alignment_t; /** diff --git a/opendps/uui_number.c b/opendps/uui_number.c index 1c433ce7..8c4e2989 100644 --- a/opendps/uui_number.c +++ b/opendps/uui_number.c @@ -233,6 +233,8 @@ static void number_draw(ui_item_t *_item) /** Adjust drawing position if right aligned */ if (item->alignment == ui_text_right_aligned) xpos -= number_draw_width(_item); + else if (item->alignment == ui_text_center_aligned) + xpos -= number_draw_width(_item) / 2; /** Start printing from left to right */ for (uint8_t place = item->num_digits; place > 0; place--) { From 27147acd4c80ec5652bd7f2bc4a57a43204f7fe9 Mon Sep 17 00:00:00 2001 From: Richard Taylor Date: Tue, 25 May 2021 19:41:34 +0100 Subject: [PATCH 07/11] Add MPPT support / screen. Be careful with this! This screen automatically enables the output (so it starts when the solar panel generates power). It uses a binary tree search to quickly find the maximum power point of the input source. The output is limited to the voltage / current limits set on the screen. --- opendps/Makefile | 12 +- opendps/func_mppt.c | 494 ++++++++++++++++++++++++++++++++++++++++++++ opendps/func_mppt.h | 38 ++++ opendps/gfx-mppt.c | 85 ++++++++ opendps/gfx-mppt.h | 13 ++ opendps/opendps.c | 6 + 6 files changed, 647 insertions(+), 1 deletion(-) create mode 100644 opendps/func_mppt.c create mode 100644 opendps/func_mppt.h create mode 100644 opendps/gfx-mppt.c create mode 100644 opendps/gfx-mppt.h diff --git a/opendps/Makefile b/opendps/Makefile index dc4fce47..a6bba8e5 100644 --- a/opendps/Makefile +++ b/opendps/Makefile @@ -17,7 +17,7 @@ THERMAL_LOCKOUT := 0 # Build wifi version (only change being that the wifi icon will start flashing # on power up) -WIFI := 1 +WIFI := 0 # Maximum current your DPS model can provide. Eg 5000mA for the DPS5005 # This is usually set by MODEL but you can override it here @@ -52,6 +52,11 @@ TINT ?= ffffff # Enable CC/CV mode CCCV_ENABLE ?= 1 +# Enable MPPT mode (Solar panel Maximum Power Point Tracking) +# WARNING: This screen automatically enables the output and ramps up to maximum current. +# Make sure you set the Voltage and Current limits before connecting a load! +MPPT_ENABLE ?= 0 + # Enable function generator mode FUNCGEN_ENABLE ?= 1 @@ -147,6 +152,11 @@ ifeq ($(CCCV_ENABLE),1) OBJS += func_cccv.o gfx-cccv.o endif +ifeq ($(MPPT_ENABLE),1) + CFLAGS +=-DCONFIG_MPPT_ENABLE + OBJS += func_mppt.o gfx-mppt.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_mppt.c b/opendps/func_mppt.c new file mode 100644 index 00000000..1c727cf0 --- /dev/null +++ b/opendps/func_mppt.c @@ -0,0 +1,494 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2018 Johan Kanflo (github.com/kanflo) + * Copyright (c) 2021 Richard Taylor (github.com/art103) + * + * 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-mppt.h" +#include "hw.h" +#include "func_mppt.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 MPPT screen. It has two editable values, + * voltage and current limit. When the screen is selected, it will automatically + * enable the output and perform a binary tree search algorithm to determine the + * maximum output current (up to the set limit) that the input can support. + * This is useful in combination with a solar panel to find the optimum operating + * point. + */ + +static void mppt_enable(bool _enable); +static void voltage_changed(ui_number_t *item); +static void current_changed(ui_number_t *item); +static void mppt_tick(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); +static set_param_status_t get_parameter(char *name, char *value, uint32_t value_len); + +/* 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_u; +static int32_t saved_i; + +#define SCREEN_ID (1) +#define PAST_U (0) +#define PAST_I (1) + +/** Delay after adjusting current to wait for the input to settle. + * Value is in UI ticks (250ms). */ +#define SWEEP_DELAY (8) + +/* This is the definition of the voltage item in the UI */ +ui_number_t mppt_voltage = { + { + .type = ui_item_number, + .id = 10, + .x = 64, + .y = 6, + .can_focus = true, + }, + .font_size = FONT_METER_LARGE, /** The bigger one, try FONT_SMALL or FONT_MEDIUM for kicks */ + .alignment = ui_text_center_aligned, + .pad_dot = false, + .color = COLOR_VOLTAGE, + .value = 0, + .min = 0, + .max = 0, + .si_prefix = si_milli, + .num_digits = 2, + .num_decimals = 2, + .unit = unit_volt, /** Affects the unit printed on screen */ + .changed = &voltage_changed, +}; + +/* This is the definition of the current item in the UI */ +ui_number_t mppt_current = { + { + .type = ui_item_number, + .id = 11, + .x = 64, + .y = 40, + .can_focus = true, + }, + .font_size = FONT_METER_LARGE, + .alignment = ui_text_center_aligned, + .pad_dot = false, + .color = COLOR_AMPERAGE, + .value = 0, + .min = 0, + .max = CONFIG_DPS_MAX_CURRENT, + .si_prefix = si_milli, + .num_digits = CURRENT_DIGITS, + .num_decimals = CURRENT_DECIMALS, + .unit = unit_ampere, + .changed = ¤t_changed, +}; + +/* This is the definition of the power item in the UI */ +ui_number_t mppt_power = { + { + .type = ui_item_number, + .id = 12, + .x = 64, + .y = 72, + .can_focus = false, + }, + .font_size = FONT_METER_LARGE, + .alignment = ui_text_center_aligned, + .pad_dot = false, + .color = COLOR_AMPERAGE, + .value = 0, + .min = 0, + .max = 0, + .si_prefix = si_milli, + .num_digits = 3, + .num_decimals = 1, + .unit = unit_watt, +}; + +/* This is the screen definition */ +ui_screen_t mppt_screen = { + .id = SCREEN_ID, + .name = "cv", + .icon_data = (uint8_t *) gfx_mppt, + .icon_data_len = sizeof(gfx_mppt), + .icon_width = GFX_MPPT_WIDTH, + .icon_height = GFX_MPPT_HEIGHT, + .activated = NULL, + .deactivated = NULL, + .enable = &mppt_enable, + .past_save = &past_save, + .past_restore = &past_restore, + .tick = &mppt_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*) &mppt_voltage, (ui_item_t*) &mppt_current, (ui_item_t*) &mppt_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 < mppt_voltage.min || ivalue > mppt_voltage.max) { + emu_printf("[CV] Voltage %d is out of range (min:%d max:%d)\n", ivalue, mppt_voltage.min, mppt_voltage.max); + return ps_range_error; + } + emu_printf("[CV] Setting voltage to %d\n", ivalue); + mppt_voltage.value = ivalue; + voltage_changed(&mppt_voltage); + return ps_ok; + } else if (strcmp("current", name) == 0 || strcmp("i", name) == 0) { + if (ivalue < mppt_current.min || ivalue > mppt_current.max) { + emu_printf("[CV] Current %d is out of range (min:%d max:%d)\n", ivalue, mppt_current.min, mppt_current.max); + return ps_range_error; + } + emu_printf("[CV] Setting current to %d\n", ivalue); + mppt_current.value = ivalue; + current_changed(&mppt_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) { + (void) mini_snprintf(value, value_len, "%d", (pwrctl_vout_enabled() ? saved_u : mppt_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 : mppt_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 mppt_enable(bool enabled) +{ + emu_printf("[CV] %s output\n", enabled ? "Enable" : "Disable"); + if (enabled) { + /** Display will now show the current values, keep the user setting saved */ + saved_u = mppt_voltage.value; + saved_i = mppt_current.value; + (void) pwrctl_set_vout(saved_u); + (void) pwrctl_set_iout(0); + (void) pwrctl_set_ilimit(CONFIG_DPS_MAX_CURRENT); + (void) pwrctl_set_vlimit(0xFFFF); /** Set the voltage limit to the maximum to prevent OVP (over voltage 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 */ + mppt_voltage.value = saved_u; + mppt_voltage.ui.draw(&mppt_voltage.ui); + mppt_current.value = saved_i; + mppt_current.ui.draw(&mppt_current.ui); + mppt_power.value = saved_i * saved_u / 1000; + mppt_power.ui.draw(&mppt_power.ui); + } +} + +/** + * @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_u = 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(0); +} + +/** + * @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_u, 4 /* sizeof(mppt_voltage.value) */ )) { + /** @todo: handle past write failures */ + } + if (!past_write_unit(past, (SCREEN_ID << 24) | PAST_I, (void*) &saved_i, 4 /* sizeof(mppt_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_u = mppt_voltage.value = *p; + (void) length; + } + if (past_read_unit(past, (SCREEN_ID << 24) | PAST_I, (const void**) &p, &length)) { + saved_i = mppt_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. 250ms ticks. + * 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 mppt_tick(void) +{ + static bool mppt_sweep = true; + static uint32_t tick_count = 0; + static uint32_t next_sweep = 0; + + static uint32_t mppt_wait; + static int32_t mppt_max_i; + static int32_t mppt_i_step; + static int32_t mppt_v_in; + + bool editing = false; + uint16_t i_out_raw, v_in_raw, v_out_raw; + hw_get_adc_values(&i_out_raw, &v_in_raw, &v_out_raw); + + tick_count++; + if (tick_count > next_sweep) { + mppt_sweep = true; + + /** Try and go to max current */ + mppt_max_i = saved_i; + mppt_i_step = 0; + mppt_v_in = 50000; + + /** Re-enable ourselves */ + opendps_enable_output(false); + opendps_enable_output(true); + + /** Scan every 30 mins (1 tick == 0.25s) */ + next_sweep = tick_count + 4 * 60 * 30; + } + + if (pwrctl_vout_enabled()) { + int32_t new_u = pwrctl_calc_vout(v_out_raw); + int32_t new_i = pwrctl_calc_iout(i_out_raw); + int32_t new_p = new_u * new_i / 1000; + int32_t new_v_in = pwrctl_calc_vin(v_in_raw); + + if (mppt_sweep) { + mppt_wait++; + /** Wait for 2s to allow the system to stabilise. */ + if (mppt_wait > SWEEP_DELAY) { + mppt_wait = 0; + + if (new_i < mppt_max_i - 10 || + mppt_i_step < 5) { + /** We're at min input / min step. + * Abort the sweep */ + mppt_sweep = false; + } else { + /** Perform a binary search for the mppt */ + mppt_max_i = mppt_max_i + mppt_i_step; + mppt_i_step /= 2; + } + + /* We know this v_in is good */ + if (new_v_in < mppt_v_in) + mppt_v_in = new_v_in; + } + new_i = mppt_max_i; + } else { + /** Keep tracking around the mpp input voltage */ + if (new_v_in <= mppt_v_in) { + new_i -= 15; + if (new_i < 0) { + next_sweep = tick_count; + new_i = 0; + } + } else { + new_i += 10; + } + } + + /** Make sure we limit the current to our set maximum */ + if (new_i > saved_i) + new_i = saved_i; + + /** Apply the new current setting */ + pwrctl_set_iout(new_i); + + if (mppt_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 (mppt_voltage.value != (int32_t) pwrctl_get_vout()) { + mppt_voltage.value = pwrctl_get_vout(); + mppt_voltage.ui.draw(&mppt_voltage.ui); + } + editing = true; + } else { + /** No focus, update display if necessary */ + if (new_u != mppt_voltage.value) { + mppt_voltage.value = new_u; + mppt_voltage.ui.draw(&mppt_voltage.ui); + } + } + + if (mppt_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 (mppt_current.value != saved_i) { + mppt_current.value = saved_i; + mppt_current.ui.draw(&mppt_current.ui); + } + editing = true; + } else { + /** No focus, update display if necessary */ + if (new_i != mppt_current.value) { + mppt_current.value = new_i; + mppt_current.ui.draw(&mppt_current.ui); + } + } + + /** Update the power value */ + if (new_p != mppt_power.value) { + mppt_power.value = new_p; + mppt_power.ui.draw(&mppt_power.ui); + } + } else { + if (mppt_sweep) { + if (mppt_i_step == 0) { + /** Ignore the first time through */ + mppt_i_step = saved_i / 2; + } else { + /** That current setting failed, next step! */ + mppt_max_i = mppt_max_i - mppt_i_step; + mppt_i_step /= 2; + } + + /** Apply the new setpoint */ + opendps_enable_output(true); + pwrctl_set_iout(mppt_max_i); + } else { + /** Something went wrong, start a new sweep */ + next_sweep = tick_count; + } + } + + if (editing) { + /** Trigger a new MPPT sweep in 2s */ + next_sweep = tick_count + SWEEP_DELAY; + } +} + +/** + * @brief Initialise the CV module and add its screen to the UI + * + * @param ui The user interface + */ +void func_mppt_init(uui_t *ui) +{ + mppt_voltage.value = 0; /** read from past */ + mppt_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; + mppt_voltage.max = pwrctl_calc_vin(v_in_raw); /** @todo: subtract for LDO */ + number_init(&mppt_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 */ + mppt_voltage.cur_digit = 2; + number_init(&mppt_current); + number_init(&mppt_power); + uui_add_screen(ui, &mppt_screen); +} diff --git a/opendps/func_mppt.h b/opendps/func_mppt.h new file mode 100644 index 00000000..389f7c25 --- /dev/null +++ b/opendps/func_mppt.h @@ -0,0 +1,38 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2018 Johan Kanflo (github.com/kanflo) + * Copyright (c) 2021 Richard Taylor (github.com/art103) + * + * 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_MPPT_H__ +#define __FUNC_MPPT_H__ + +#include "uui.h" + +/** + * @brief Add the MPPT function to the UI + * + * @param ui The user interface + */ +void func_mppt_init(uui_t *ui); + +#endif // __FUNC_MPPT_H__ diff --git a/opendps/gfx-mppt.c b/opendps/gfx-mppt.c new file mode 100644 index 00000000..96f8a188 --- /dev/null +++ b/opendps/gfx-mppt.c @@ -0,0 +1,85 @@ +/** Gfx generated from `gen_lookup.py -i gfx/png/mppt.png -o mppt` */ + +#include "gfx-mppt.h" + +const uint8_t gfx_mppt[1260] = { + 0x00, 0x00, 0x6b, 0x6d, 0x94, 0xb2, 0x6b, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x82, 0x94, 0xb2, 0x94, 0xb2, 0x31, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x31, 0xc6, + 0x63, 0x2c, 0x84, 0x30, 0x8c, 0x71, 0x73, 0xce, 0x42, 0x48, 0x08, 0x61, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x82, 0x52, 0xaa, 0x73, 0xae, 0x8c, 0x71, 0x84, 0x30, 0x63, 0x0c, 0x29, 0x65, 0x00, 0x00, + 0x10, 0xa2, 0x94, 0xd2, 0x94, 0xb2, 0x94, 0xb2, 0x94, 0xb2, 0x94, 0xb2, 0x94, 0xb2, 0x94, 0xb2, + 0x94, 0xb2, 0x52, 0xaa, 0x00, 0x00, 0xad, 0x75, 0xff, 0xff, 0xe7, 0x5c, 0x18, 0xc3, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x69, 0xff, 0xff, 0xff, 0xff, 0x4a, 0x89, 0x00, 0x00, + 0x00, 0x00, 0x94, 0xb2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc6, 0x18, + 0x21, 0x04, 0x00, 0x00, 0x21, 0x24, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x6b, 0x6d, 0x18, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6b, 0x4d, 0x00, 0x00, 0xef, 0x9d, 0xff, 0xff, 0xff, 0xff, + 0x52, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xa5, 0x54, 0xff, 0xff, 0xff, 0xff, + 0x5b, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x94, 0xb2, 0xff, 0xff, 0xb5, 0x96, 0x52, 0xca, 0x7c, 0x0f, + 0xef, 0x9d, 0xff, 0xff, 0xad, 0x95, 0x00, 0x20, 0x21, 0x24, 0xff, 0xff, 0xff, 0xff, 0x73, 0x8e, + 0x63, 0x0c, 0xb5, 0xb6, 0xff, 0xff, 0xff, 0xff, 0x52, 0xca, 0x52, 0xaa, 0x52, 0xaa, 0x5a, 0xeb, + 0xe7, 0x3c, 0xff, 0xff, 0x8c, 0x71, 0x52, 0xaa, 0x52, 0xaa, 0x31, 0xa6, 0x08, 0x41, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xb5, 0xd6, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x21, 0x44, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x6b, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x94, 0xb2, 0xff, 0xff, 0x84, 0x50, + 0x00, 0x00, 0x00, 0x00, 0x5a, 0xcb, 0xff, 0xff, 0xff, 0xff, 0x21, 0x44, 0x21, 0x24, 0xff, 0xff, + 0xff, 0xff, 0x29, 0x45, 0x00, 0x00, 0x10, 0x82, 0xc6, 0x58, 0xff, 0xff, 0x8c, 0x71, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x61, 0xce, 0x99, 0xff, 0xff, 0x4a, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x82, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x29, 0x65, 0x00, 0x00, 0x00, 0x00, + 0x6b, 0x4d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x84, 0x10, 0x00, 0x00, 0x00, 0x00, 0x94, 0xb2, + 0xff, 0xff, 0x84, 0x50, 0x00, 0x00, 0x00, 0x00, 0x21, 0x24, 0xff, 0xff, 0xff, 0xff, 0x39, 0xe7, + 0x21, 0x24, 0xff, 0xff, 0xff, 0xff, 0x29, 0x45, 0x00, 0x00, 0x00, 0x00, 0x84, 0x30, 0xff, 0xff, + 0xb5, 0x96, 0x00, 0x20, 0x00, 0x00, 0x08, 0x61, 0xce, 0x99, 0xff, 0xff, 0x4a, 0x89, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0xa2, 0xff, 0xff, 0xf7, 0xde, 0xad, 0x75, 0xff, 0xff, 0x73, 0x8e, + 0x00, 0x00, 0x08, 0x41, 0xc6, 0x58, 0xff, 0xff, 0xb5, 0x96, 0xff, 0xff, 0x8c, 0x91, 0x00, 0x00, + 0x00, 0x00, 0x94, 0xb2, 0xff, 0xff, 0x84, 0x50, 0x00, 0x00, 0x00, 0x00, 0x29, 0x45, 0xff, 0xff, + 0xff, 0xff, 0x39, 0xe7, 0x21, 0x24, 0xff, 0xff, 0xff, 0xff, 0x29, 0x45, 0x00, 0x00, 0x00, 0x00, + 0x84, 0x50, 0xff, 0xff, 0xad, 0x95, 0x00, 0x20, 0x00, 0x00, 0x08, 0x61, 0xce, 0x99, 0xff, 0xff, + 0x4a, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xe3, 0xff, 0xff, 0xef, 0x9d, 0x4a, 0x69, + 0xff, 0xff, 0xce, 0x79, 0x08, 0x61, 0x31, 0x86, 0xff, 0xff, 0xad, 0x55, 0x63, 0x0c, 0xff, 0xff, + 0x9c, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x94, 0xb2, 0xff, 0xff, 0x84, 0x50, 0x00, 0x00, 0x00, 0x00, + 0x6b, 0x4d, 0xff, 0xff, 0xf7, 0xde, 0x21, 0x24, 0x21, 0x24, 0xff, 0xff, 0xff, 0xff, 0x29, 0x45, + 0x00, 0x00, 0x18, 0xe3, 0xd6, 0xba, 0xff, 0xff, 0x84, 0x50, 0x00, 0x00, 0x00, 0x00, 0x08, 0x61, + 0xce, 0x99, 0xff, 0xff, 0x4a, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x24, 0xff, 0xff, + 0xe7, 0x5c, 0x18, 0xe3, 0xbd, 0xd7, 0xff, 0xff, 0x31, 0xa6, 0x6b, 0x8d, 0xff, 0xff, 0x5a, 0xcb, + 0x4a, 0x69, 0xff, 0xff, 0xa5, 0x54, 0x00, 0x20, 0x00, 0x00, 0x94, 0xb2, 0xff, 0xff, 0xb5, 0xd6, + 0x6b, 0x6d, 0x9c, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xa5, 0x14, 0x00, 0x00, 0x21, 0x24, 0xff, 0xff, + 0xff, 0xff, 0x84, 0x10, 0x7b, 0xef, 0xce, 0x99, 0xf7, 0xde, 0xff, 0xff, 0x39, 0xc7, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x61, 0xce, 0x99, 0xff, 0xff, 0x4a, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x29, 0x65, 0xff, 0xff, 0xdf, 0x1b, 0x10, 0x82, 0x5b, 0x0b, 0xff, 0xff, 0x8c, 0x71, 0xbe, 0x17, + 0xff, 0xff, 0x21, 0x04, 0x42, 0x48, 0xff, 0xff, 0xb5, 0xd6, 0x00, 0x20, 0x00, 0x00, 0x94, 0xb2, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xad, 0x75, 0x18, 0xe3, 0x00, 0x00, + 0x21, 0x24, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5a, 0xeb, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x61, 0xce, 0x99, 0xff, 0xff, 0x4a, 0x89, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x31, 0x86, 0xff, 0xff, 0xde, 0xfb, 0x08, 0x61, 0x21, 0x44, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xad, 0x95, 0x00, 0x20, 0x42, 0x08, 0xff, 0xff, 0xce, 0x59, 0x00, 0x20, + 0x00, 0x00, 0x94, 0xb2, 0xff, 0xff, 0xc6, 0x38, 0x7b, 0xef, 0x63, 0x2c, 0x39, 0xc7, 0x08, 0x41, + 0x00, 0x00, 0x00, 0x00, 0x21, 0x24, 0xff, 0xff, 0xff, 0xff, 0x94, 0xb2, 0x73, 0xae, 0x52, 0xaa, + 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x61, 0xce, 0x99, 0xff, 0xff, + 0x4a, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xc7, 0xff, 0xff, 0xd6, 0xda, 0x08, 0x61, + 0x00, 0x20, 0xc6, 0x38, 0xff, 0xff, 0xff, 0xff, 0x63, 0x0c, 0x00, 0x00, 0x39, 0xe7, 0xff, 0xff, + 0xef, 0x9d, 0x08, 0x41, 0x00, 0x00, 0x94, 0xb2, 0xff, 0xff, 0x84, 0x50, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x24, 0xff, 0xff, 0xff, 0xff, 0x29, 0x45, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x61, + 0xce, 0x99, 0xff, 0xff, 0x4a, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xe7, 0xff, 0xff, + 0xd6, 0xda, 0x08, 0x41, 0x00, 0x00, 0x6b, 0x6d, 0xff, 0xff, 0xff, 0xff, 0x29, 0x45, 0x00, 0x00, + 0x39, 0xc7, 0xff, 0xff, 0xff, 0xff, 0x08, 0x41, 0x00, 0x00, 0x94, 0xb2, 0xff, 0xff, 0x84, 0x50, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x24, 0xff, 0xff, + 0xff, 0xff, 0x29, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x61, 0xce, 0x99, 0xff, 0xff, 0x4a, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x42, 0x28, 0xff, 0xff, 0xd6, 0xba, 0x00, 0x20, 0x00, 0x00, 0x31, 0xa6, 0xff, 0xff, 0xd6, 0xda, + 0x08, 0x41, 0x00, 0x00, 0x31, 0xa6, 0xff, 0xff, 0xff, 0xff, 0x08, 0x61, 0x00, 0x00, 0x94, 0xb2, + 0xff, 0xff, 0x84, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x21, 0x24, 0xff, 0xff, 0xff, 0xff, 0x29, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x61, 0xce, 0x99, 0xff, 0xff, 0x4a, 0x89, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x4a, 0x49, 0xff, 0xff, 0xd6, 0xba, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x86, 0xff, 0xff, 0xff, 0xff, 0x10, 0x82, + 0x00, 0x00, 0x94, 0xb2, 0xff, 0xff, 0x84, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x21, 0x24, 0xff, 0xff, 0xff, 0xff, 0x29, 0x45, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x61, 0xce, 0x99, 0xff, 0xff, + 0x4a, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x89, 0xff, 0xff, 0xce, 0x99, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x65, 0xff, 0xff, + 0xff, 0xff, 0x10, 0xa2, 0x00, 0x00, 0x94, 0xb2, 0xff, 0xff, 0x84, 0x50, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x24, 0xff, 0xff, 0xff, 0xff, 0x29, 0x45, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x61, + 0xce, 0x99, 0xff, 0xff, 0x4a, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; \ No newline at end of file diff --git a/opendps/gfx-mppt.h b/opendps/gfx-mppt.h new file mode 100644 index 00000000..92bfe478 --- /dev/null +++ b/opendps/gfx-mppt.h @@ -0,0 +1,13 @@ +/** Gfx generated from `gen_lookup.py -i gfx/png/mppt.png -o mppt` */ + +#ifndef __GFX_MPPT_H__ +#define __GFX_MPPT_H__ + +#include + +#define GFX_MPPT_HEIGHT (15) +#define GFX_MPPT_WIDTH (42) + +extern const uint8_t gfx_mppt[1260]; + +#endif // __GFX_MPPT_H__ \ No newline at end of file diff --git a/opendps/opendps.c b/opendps/opendps.c index ca0858ad..ba0b018b 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -69,6 +69,9 @@ #ifdef CONFIG_CCCV_ENABLE #include "func_cccv.h" #endif // CONFIG_CCCV_ENABLE +#ifdef CONFIG_MPPT_ENABLE +#include "func_mppt.h" +#endif // CONFIG_MPPT_ENABLE #ifdef CONFIG_FUNCGEN_ENABLE #include "func_gen.h" #endif // CONFIG_FUNCGEN_ENABLE @@ -443,6 +446,9 @@ static void ui_init(void) #ifdef CONFIG_CCCV_ENABLE func_cccv_init(&func_ui); #endif // CONFIG_CCCV_ENABLE +#ifdef CONFIG_MPPT_ENABLE + func_mppt_init(&func_ui); +#endif // CONFIG_MPPT_ENABLE #ifdef CONFIG_FUNCGEN_ENABLE func_gen_init(&func_ui); #endif // CONFIG_FUNCGEN_ENABLE From d8b56d20e088433b8b5e97baba715a3e837824f6 Mon Sep 17 00:00:00 2001 From: Richard Taylor Date: Tue, 25 May 2021 19:43:40 +0100 Subject: [PATCH 08/11] Add CC/CV and MPPT graphics. --- opendps/gfx/png/cccv.png | Bin 0 -> 8092 bytes opendps/gfx/png/mppt.png | Bin 0 -> 1419 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 opendps/gfx/png/cccv.png create mode 100644 opendps/gfx/png/mppt.png diff --git a/opendps/gfx/png/cccv.png b/opendps/gfx/png/cccv.png new file mode 100644 index 0000000000000000000000000000000000000000..1757bff67ef4704cd4785e4137e0b0dd92667403 GIT binary patch literal 8092 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 Z#6KoFEto$shhqQ$002ovPDHLkV1o0Wl&Js! literal 0 HcmV?d00001 From 1ee3f37531a4936bcde52c2ee8f38f163fb2cf03 Mon Sep 17 00:00:00 2001 From: Richard Taylor Date: Tue, 25 May 2021 19:49:45 +0100 Subject: [PATCH 09/11] Update names in CC/CV and MPPT screens. --- opendps/func_cccv.c | 12 ++++++------ opendps/func_mppt.c | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/opendps/func_cccv.c b/opendps/func_cccv.c index 13033460..dc4045ad 100644 --- a/opendps/func_cccv.c +++ b/opendps/func_cccv.c @@ -135,7 +135,7 @@ ui_number_t cccv_power = { /* This is the screen definition */ ui_screen_t cccv_screen = { .id = SCREEN_ID, - .name = "cv", + .name = "cccv", .icon_data = (uint8_t *) gfx_cccv, .icon_data_len = sizeof(gfx_cccv), .icon_width = GFX_CCCV_WIDTH, @@ -185,19 +185,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 < cccv_voltage.min || ivalue > cccv_voltage.max) { - emu_printf("[CV] Voltage %d is out of range (min:%d max:%d)\n", ivalue, cccv_voltage.min, cccv_voltage.max); + emu_printf("[CCCV] Voltage %d is out of range (min:%d max:%d)\n", ivalue, cccv_voltage.min, cccv_voltage.max); return ps_range_error; } - emu_printf("[CV] Setting voltage to %d\n", ivalue); + emu_printf("[CCCV] Setting voltage to %d\n", ivalue); cccv_voltage.value = ivalue; voltage_changed(&cccv_voltage); return ps_ok; } else if (strcmp("current", name) == 0 || strcmp("i", name) == 0) { if (ivalue < cccv_current.min || ivalue > cccv_current.max) { - emu_printf("[CV] Current %d is out of range (min:%d max:%d)\n", ivalue, cccv_current.min, cccv_current.max); + emu_printf("[CCCV] Current %d is out of range (min:%d max:%d)\n", ivalue, cccv_current.min, cccv_current.max); return ps_range_error; } - emu_printf("[CV] Setting current to %d\n", ivalue); + emu_printf("[CCCV] Setting current to %d\n", ivalue); cccv_current.value = ivalue; current_changed(&cccv_current); return ps_ok; @@ -233,7 +233,7 @@ static set_param_status_t get_parameter(char *name, char *value, uint32_t value_ */ static void cccv_enable(bool enabled) { - emu_printf("[CV] %s output\n", enabled ? "Enable" : "Disable"); + emu_printf("[CCCV] %s output\n", enabled ? "Enable" : "Disable"); if (enabled) { /** Display will now show the current values, keep the user setting saved */ saved_u = cccv_voltage.value; diff --git a/opendps/func_mppt.c b/opendps/func_mppt.c index 1c727cf0..571112bb 100644 --- a/opendps/func_mppt.c +++ b/opendps/func_mppt.c @@ -141,7 +141,7 @@ ui_number_t mppt_power = { /* This is the screen definition */ ui_screen_t mppt_screen = { .id = SCREEN_ID, - .name = "cv", + .name = "mppt", .icon_data = (uint8_t *) gfx_mppt, .icon_data_len = sizeof(gfx_mppt), .icon_width = GFX_MPPT_WIDTH, @@ -191,19 +191,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 < mppt_voltage.min || ivalue > mppt_voltage.max) { - emu_printf("[CV] Voltage %d is out of range (min:%d max:%d)\n", ivalue, mppt_voltage.min, mppt_voltage.max); + emu_printf("[MPPT] Voltage %d is out of range (min:%d max:%d)\n", ivalue, mppt_voltage.min, mppt_voltage.max); return ps_range_error; } - emu_printf("[CV] Setting voltage to %d\n", ivalue); + emu_printf("[MPPT] Setting voltage to %d\n", ivalue); mppt_voltage.value = ivalue; voltage_changed(&mppt_voltage); return ps_ok; } else if (strcmp("current", name) == 0 || strcmp("i", name) == 0) { if (ivalue < mppt_current.min || ivalue > mppt_current.max) { - emu_printf("[CV] Current %d is out of range (min:%d max:%d)\n", ivalue, mppt_current.min, mppt_current.max); + emu_printf("[MPPT] Current %d is out of range (min:%d max:%d)\n", ivalue, mppt_current.min, mppt_current.max); return ps_range_error; } - emu_printf("[CV] Setting current to %d\n", ivalue); + emu_printf("[MPPT] Setting current to %d\n", ivalue); mppt_current.value = ivalue; current_changed(&mppt_current); return ps_ok; @@ -239,7 +239,7 @@ static set_param_status_t get_parameter(char *name, char *value, uint32_t value_ */ static void mppt_enable(bool enabled) { - emu_printf("[CV] %s output\n", enabled ? "Enable" : "Disable"); + emu_printf("[MPPT] %s output\n", enabled ? "Enable" : "Disable"); if (enabled) { /** Display will now show the current values, keep the user setting saved */ saved_u = mppt_voltage.value; From 469da3ce3c08c5f6ca3d6e526453cc173cb3661b Mon Sep 17 00:00:00 2001 From: Richard Taylor Date: Wed, 26 May 2021 08:38:25 +0100 Subject: [PATCH 10/11] Update calibration values for DPS5020 --- opendps/dps-model.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/opendps/dps-model.h b/opendps/dps-model.h index f45060c0..63b3bdf1 100644 --- a/opendps/dps-model.h +++ b/opendps/dps-model.h @@ -49,14 +49,14 @@ #define CURRENT_DIGITS 2 #define CURRENT_DECIMALS 2 #define ADC_CHA_IOUT_GOLDEN_VALUE (59) - #define A_ADC_K (float)6.75449f - #define A_ADC_C (float)-358.73f - #define A_DAC_K (float)0.16587f - #define A_DAC_C (float)243.793f - #define V_ADC_K (float)13.2930f - #define V_ADC_C (float)-179.91f - #define V_DAC_K (float)0.07528f - #define V_DAC_C (float)6.68949f + #define A_ADC_K (float)6.810f + #define A_ADC_C (float)-397.0f + #define A_DAC_K (float)0.1655f + #define A_DAC_C (float)273.0f + #define V_ADC_K (float)13.01f + #define V_ADC_C (float)-171.0f + #define V_DAC_K (float)0.077f + #define V_DAC_C (float)5.09f #define VIN_ADC_K (float)16.956f #define VIN_ADC_C (float)6.6895f From 59be8932739a6fc5ddb26adb2553c36e708900de Mon Sep 17 00:00:00 2001 From: Richard Taylor Date: Wed, 26 May 2021 09:23:05 +0100 Subject: [PATCH 11/11] Update MPPT settings slightly. Change screen colours. --- opendps/Makefile | 15 ++++++++------- opendps/func_cccv.c | 2 +- opendps/func_mppt.c | 29 ++++++++++++++++++++--------- opendps/opendps.c | 12 ++++++++---- 4 files changed, 37 insertions(+), 21 deletions(-) diff --git a/opendps/Makefile b/opendps/Makefile index a6bba8e5..94ce7d40 100644 --- a/opendps/Makefile +++ b/opendps/Makefile @@ -5,12 +5,12 @@ COMMANDLINE := 0 BAUDRATE ?= 9600 # Set build model, defaults to DPS5005 -MODEL := DPS5005 +MODEL := DPS5020 BINARY = opendps_$(MODEL) # Include splash screen -SPLASH_SCREEN := 0 +SPLASH_SCREEN := 1 # Include support for thermal lockout via the serial interface THERMAL_LOCKOUT := 0 @@ -42,8 +42,9 @@ FULL_FONT_SMALL_SIZE ?= 16 COLORSPACE ?= 0 # Colors for the main UI elements -- see ili9163c.h for list of colors -COLOR_VOLTAGE ?= WHITE -COLOR_AMPERAGE ?= WHITE +COLOR_VOLTAGE ?= 0x87F0 +COLOR_AMPERAGE ?= 0xFFF0 +COLOR_WATTAGE ?= 0xC41F COLOR_INPUT ?= WHITE # Optional tinting for UI elements @@ -55,7 +56,7 @@ CCCV_ENABLE ?= 1 # Enable MPPT mode (Solar panel Maximum Power Point Tracking) # WARNING: This screen automatically enables the output and ramps up to maximum current. # Make sure you set the Voltage and Current limits before connecting a load! -MPPT_ENABLE ?= 0 +MPPT_ENABLE ?= 1 # Enable function generator mode FUNCGEN_ENABLE ?= 1 @@ -64,7 +65,7 @@ FUNCGEN_ENABLE ?= 1 INVERT_ENABLE ?= 0 # Power buttons in color -POWER_COLORED ?= 1 +POWER_COLORED ?= 0 # Power off button visible POWER_OFF_VISIBLE ?= 0 @@ -81,6 +82,7 @@ CFLAGS += \ -DCOLORSPACE=$(COLORSPACE) \ -DCOLOR_VOLTAGE=$(COLOR_VOLTAGE) \ -DCOLOR_AMPERAGE=$(COLOR_AMPERAGE) \ + -DCOLOR_WATTAGE=$(COLOR_WATTAGE) \ -DCOLOR_INPUT=$(COLOR_INPUT) \ -D$(MODEL) @@ -131,7 +133,6 @@ ifeq ($(WDOG),1) OBJS += wdog.o endif - ifeq ($(INVERT_ENABLE),1) CFLAGS +=-DCONFIG_INVERT_ENABLE endif diff --git a/opendps/func_cccv.c b/opendps/func_cccv.c index dc4045ad..067e3b84 100644 --- a/opendps/func_cccv.c +++ b/opendps/func_cccv.c @@ -122,7 +122,7 @@ ui_number_t cccv_power = { .font_size = FONT_METER_LARGE, .alignment = ui_text_center_aligned, .pad_dot = false, - .color = COLOR_AMPERAGE, + .color = COLOR_WATTAGE, .value = 0, .min = 0, .max = 0, diff --git a/opendps/func_mppt.c b/opendps/func_mppt.c index 571112bb..f2e3065d 100644 --- a/opendps/func_mppt.c +++ b/opendps/func_mppt.c @@ -68,7 +68,8 @@ static int32_t saved_i; /** Delay after adjusting current to wait for the input to settle. * Value is in UI ticks (250ms). */ -#define SWEEP_DELAY (8) +#define SWEEP_DELAY (12) +#define INCREASE_DELAY (8) /* This is the definition of the voltage item in the UI */ ui_number_t mppt_voltage = { @@ -128,7 +129,7 @@ ui_number_t mppt_power = { .font_size = FONT_METER_LARGE, .alignment = ui_text_center_aligned, .pad_dot = false, - .color = COLOR_AMPERAGE, + .color = COLOR_WATTAGE, .value = 0, .min = 0, .max = 0, @@ -364,6 +365,7 @@ static void mppt_tick(void) int32_t new_i = pwrctl_calc_iout(i_out_raw); int32_t new_p = new_u * new_i / 1000; int32_t new_v_in = pwrctl_calc_vin(v_in_raw); + bool update_iout = false; if (mppt_sweep) { mppt_wait++; @@ -372,7 +374,7 @@ static void mppt_tick(void) mppt_wait = 0; if (new_i < mppt_max_i - 10 || - mppt_i_step < 5) { + mppt_i_step < 10) { /** We're at min input / min step. * Abort the sweep */ mppt_sweep = false; @@ -387,16 +389,23 @@ static void mppt_tick(void) mppt_v_in = new_v_in; } new_i = mppt_max_i; + update_iout = true; } else { /** Keep tracking around the mpp input voltage */ - if (new_v_in <= mppt_v_in) { - new_i -= 15; + if (new_v_in < mppt_v_in) { + new_i -= 100; if (new_i < 0) { next_sweep = tick_count; new_i = 0; } - } else { - new_i += 10; + update_iout = true; + } else if (new_v_in > mppt_v_in + 250) { + mppt_wait++; + if (mppt_wait > INCREASE_DELAY) { + mppt_wait = 0; + new_i += 10; + update_iout = true; + } } } @@ -404,8 +413,10 @@ static void mppt_tick(void) if (new_i > saved_i) new_i = saved_i; - /** Apply the new current setting */ - pwrctl_set_iout(new_i); + if (update_iout) { + /** Apply the new current setting */ + pwrctl_set_iout(new_i); + } if (mppt_voltage.ui.has_focus) { /** If the voltage setting has focus, make sure we're displaying diff --git a/opendps/opendps.c b/opendps/opendps.c index ba0b018b..d00e75ec 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -102,6 +102,10 @@ #define TFT_FLASHING_PERIOD (100) #define TFT_FLASHING_COUNTER (2) +#ifndef GFX_POWERON_HEIGHT + #define GFX_POWERON_HEIGHT GFX_POWER_HEIGHT +#endif + static void ui_flash(void); static void read_past_settings(void); static void write_past_settings(void); @@ -443,12 +447,12 @@ static void ui_init(void) /** Initialise the function screens */ uui_init(&func_ui, &g_past); -#ifdef CONFIG_CCCV_ENABLE - func_cccv_init(&func_ui); -#endif // CONFIG_CCCV_ENABLE #ifdef CONFIG_MPPT_ENABLE func_mppt_init(&func_ui); #endif // CONFIG_MPPT_ENABLE +#ifdef CONFIG_CCCV_ENABLE + func_cccv_init(&func_ui); +#endif // CONFIG_CCCV_ENABLE #ifdef CONFIG_FUNCGEN_ENABLE func_gen_init(&func_ui); #endif // CONFIG_FUNCGEN_ENABLE @@ -517,7 +521,7 @@ static void ui_handle_event(event_t event, uint8_t data) uint16_t trig = hw_get_itrig_ma(); dbg_printf("%10u OCP: trig:%umA limit:%umA cur:%umA\n", (uint32_t) (get_ticks()), pwrctl_calc_iout(trig), pwrctl_calc_iout(pwrctl_i_limit_raw), pwrctl_calc_iout(i_out_raw)); #endif // CONFIG_OCP_DEBUGGING - ui_flash(); /** @todo When OCP kicks in, show last I_out on screen */ + //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); }