diff --git a/opendps/Makefile b/opendps/Makefile index 1ee30863..94ce7d40 100644 --- a/opendps/Makefile +++ b/opendps/Makefile @@ -5,19 +5,19 @@ 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 # 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 @@ -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 @@ -42,21 +42,21 @@ 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 TINT ?= ffffff -# Enable CC mode -CC_ENABLE ?= 1 +# Enable CC/CV mode +CCCV_ENABLE ?= 1 -# Enable CV mode -CV_ENABLE ?= 1 - -# Enable cl mode -CL_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 ?= 1 # Enable function generator mode FUNCGEN_ENABLE ?= 1 @@ -65,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 @@ -82,6 +82,7 @@ CFLAGS += \ -DCOLORSPACE=$(COLORSPACE) \ -DCOLOR_VOLTAGE=$(COLOR_VOLTAGE) \ -DCOLOR_AMPERAGE=$(COLOR_AMPERAGE) \ + -DCOLOR_WATTAGE=$(COLOR_WATTAGE) \ -DCOLOR_INPUT=$(COLOR_INPUT) \ -D$(MODEL) @@ -110,10 +111,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 +122,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) @@ -133,7 +133,6 @@ ifeq ($(WDOG),1) OBJS += wdog.o endif - ifeq ($(INVERT_ENABLE),1) CFLAGS +=-DCONFIG_INVERT_ENABLE endif @@ -149,19 +148,14 @@ 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 +ifeq ($(CCCV_ENABLE),1) + CFLAGS +=-DCONFIG_CCCV_ENABLE + OBJS += func_cccv.o gfx-cccv.o endif -ifeq ($(CL_ENABLE),1) - CFLAGS +=-DCONFIG_CL_ENABLE - OBJS += func_cl.o +ifeq ($(MPPT_ENABLE),1) + CFLAGS +=-DCONFIG_MPPT_ENABLE + OBJS += func_mppt.o gfx-mppt.o endif ifeq ($(FUNCGEN_ENABLE),1) @@ -192,11 +186,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..63b3bdf1 100644 --- a/opendps/dps-model.h +++ b/opendps/dps-model.h @@ -44,19 +44,19 @@ /** 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 #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 @@ -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 6d18533d..92983bfb 100644 --- a/opendps/font-meter_large.c +++ b/opendps/font-meter_large.c @@ -1,147 +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[1745] = { +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, + 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, 0u, + 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, @@ -151,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, 0u, + 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, @@ -166,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, 0u, + 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 5a145c45..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 (22) -#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 (4) -#define FONT_METER_LARGE_SPACE_WIDTH (9) +#define FONT_METER_LARGE_SPACING (5) +#define FONT_METER_LARGE_SPACE_WIDTH (8) extern const uint32_t font_meter_large_height; extern const uint8_t font_meter_large_widths[96]; extern const uint8_t font_meter_large_sizes[96]; extern const uint16_t font_meter_large_offsets[96]; -extern const uint8_t font_meter_large_pixdata[1745]; +extern const uint8_t font_meter_large_pixdata[1415]; #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/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_cv.c b/opendps/func_cccv.c similarity index 66% rename from opendps/func_cv.c rename to opendps/func_cccv.c index ed70077e..067e3b84 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_WATTAGE, + .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, + .name = "cccv", + .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("[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); - cv_voltage.value = ivalue; - voltage_changed(&cv_voltage); + 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 < 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("[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); - cv_current.value = ivalue; - current_changed(&cv_current); + emu_printf("[CCCV] Setting current to %d\n", ivalue); + 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"); + 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 = 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/func_mppt.c b/opendps/func_mppt.c new file mode 100644 index 00000000..f2e3065d --- /dev/null +++ b/opendps/func_mppt.c @@ -0,0 +1,505 @@ +/* + * 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 (12) +#define INCREASE_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_WATTAGE, + .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 = "mppt", + .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("[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("[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("[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("[MPPT] 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("[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; + 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); + bool update_iout = false; + + 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 < 10) { + /** 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; + update_iout = true; + } else { + /** Keep tracking around the mpp input voltage */ + if (new_v_in < mppt_v_in) { + new_i -= 100; + if (new_i < 0) { + next_sweep = tick_count; + new_i = 0; + } + 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; + } + } + } + + /** Make sure we limit the current to our set maximum */ + if (new_i > saved_i) + new_i = saved_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 + * 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_cc.h b/opendps/func_mppt.h similarity index 85% rename from opendps/func_cc.h rename to opendps/func_mppt.h index 70861141..389f7c25 100644 --- a/opendps/func_cc.h +++ b/opendps/func_mppt.h @@ -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 @@ -22,16 +23,16 @@ * THE SOFTWARE. */ -#ifndef __FUNC_CC_H__ -#define __FUNC_CC_H__ +#ifndef __FUNC_MPPT_H__ +#define __FUNC_MPPT_H__ #include "uui.h" /** - * @brief Add the CV function to the UI + * @brief Add the MPPT function to the UI * * @param ui The user interface */ -void func_cc_init(uui_t *ui); +void func_mppt_init(uui_t *ui); -#endif // __FUNC_CC_H__ +#endif // __FUNC_MPPT_H__ 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/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/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/gfx/png/cccv.png b/opendps/gfx/png/cccv.png new file mode 100644 index 00000000..1757bff6 Binary files /dev/null and b/opendps/gfx/png/cccv.png differ diff --git a/opendps/gfx/png/mppt.png b/opendps/gfx/png/mppt.png new file mode 100644 index 00000000..8617859e Binary files /dev/null and b/opendps/gfx/png/mppt.png differ diff --git a/opendps/hw.c b/opendps/hw.c index 0b91ac70..98cec3d8 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,8 @@ 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 +285,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 +296,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 +332,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 || !pwrctl_check_limits()) { /** OCP! */ + handle_ocp(i); + } } #ifdef CONFIG_FUNCGEN_ENABLE 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 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 diff --git a/opendps/opendps.c b/opendps/opendps.c index 302884e5..d00e75ec 100644 --- a/opendps/opendps.c +++ b/opendps/opendps.c @@ -66,15 +66,12 @@ #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_MPPT_ENABLE +#include "func_mppt.h" +#endif // CONFIG_MPPT_ENABLE #ifdef CONFIG_FUNCGEN_ENABLE #include "func_gen.h" #endif // CONFIG_FUNCGEN_ENABLE @@ -96,11 +93,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) @@ -110,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); @@ -187,7 +183,7 @@ ui_number_t input_voltage = { { .type = ui_item_number, .id = 10, - .x = 0, + .x = XPOS_INVOLT, .y = 0, .can_focus = false, }, @@ -451,15 +447,12 @@ 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_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 @@ -472,8 +465,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 */ @@ -529,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); } 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 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 d91908ce..8c4e2989 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: @@ -232,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--) { @@ -312,6 +315,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); }